xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 9f196a0264fbaf0568fead3a30c861c7ae4cf663)
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;
4386bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
439f1580f4eSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the edge constant vectors via PCHYPRESetEdgeConstantVectors() or the interpolation matrix via PCHYPRESetInterpolations()");
4406bf688a0SCe Qin     }
44148a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
4425ac14e1cSStefano Zampini     if (jac->constants[0]) {
4435ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
444792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
445792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
44648a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
447792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
4485ac14e1cSStefano Zampini     }
4495ac14e1cSStefano Zampini     if (jac->coords[0]) {
4505ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
4515ac14e1cSStefano Zampini       coords[0] = NULL;
4525ac14e1cSStefano Zampini       coords[1] = NULL;
4535ac14e1cSStefano Zampini       coords[2] = NULL;
454792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
455792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
456792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
457792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
4585ac14e1cSStefano Zampini     }
4595f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
460f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
461792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
462792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
4635ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
464f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->alpha_Poisson->data;
465792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
466792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
4675ac14e1cSStefano Zampini     }
4685ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
469792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
4705ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
471f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->beta_Poisson->data;
472792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
473792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
474be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
475be14dc20SKerry Key       if (jac->interior) {
476be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
477be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
478be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
479be14dc20SKerry Key       } else {
480be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
481be14dc20SKerry Key       }
4825ac14e1cSStefano Zampini     }
4836bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
4846bf688a0SCe Qin       PetscInt           i;
4856bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
4866bf688a0SCe Qin       if (jac->ND_PiFull) {
487f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
488792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4896bf688a0SCe Qin       } else {
4906bf688a0SCe Qin         nd_parcsrfull = NULL;
4916bf688a0SCe Qin       }
4926bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4936bf688a0SCe Qin         if (jac->ND_Pi[i]) {
494f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
495792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4966bf688a0SCe Qin         } else {
4976bf688a0SCe Qin           nd_parcsr[i] = NULL;
4986bf688a0SCe Qin         }
4996bf688a0SCe Qin       }
500792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
5016bf688a0SCe Qin     }
5024cb006feSStefano Zampini   }
503863406b8SStefano Zampini   /* special case for ADS */
504863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
5055ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
5065ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
5076bf688a0SCe 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])))) {
5086bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
5099371c9d4SSatish 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");
5105f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
5115f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
5125ac14e1cSStefano Zampini     if (jac->coords[0]) {
5135ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
5145ac14e1cSStefano Zampini       coords[0] = NULL;
5155ac14e1cSStefano Zampini       coords[1] = NULL;
5165ac14e1cSStefano Zampini       coords[2] = NULL;
517792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
518792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
519792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
520792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
5215ac14e1cSStefano Zampini     }
522f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
523792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
524792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
525f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->C->data;
526792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
527792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
5286bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
5296bf688a0SCe Qin       PetscInt           i;
5306bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
5316bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
5326bf688a0SCe Qin       if (jac->RT_PiFull) {
533f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->RT_PiFull->data;
534792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
5356bf688a0SCe Qin       } else {
5366bf688a0SCe Qin         rt_parcsrfull = NULL;
5376bf688a0SCe Qin       }
5386bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
5396bf688a0SCe Qin         if (jac->RT_Pi[i]) {
540f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->RT_Pi[i]->data;
541792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
5426bf688a0SCe Qin         } else {
5436bf688a0SCe Qin           rt_parcsr[i] = NULL;
5446bf688a0SCe Qin         }
5456bf688a0SCe Qin       }
5466bf688a0SCe Qin       if (jac->ND_PiFull) {
547f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
548792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
5496bf688a0SCe Qin       } else {
5506bf688a0SCe Qin         nd_parcsrfull = NULL;
5516bf688a0SCe Qin       }
5526bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
5536bf688a0SCe Qin         if (jac->ND_Pi[i]) {
554f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
555792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
5566bf688a0SCe Qin         } else {
5576bf688a0SCe Qin           nd_parcsr[i] = NULL;
5586bf688a0SCe Qin         }
5596bf688a0SCe Qin       }
560792fecdfSBarry 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]);
5616bf688a0SCe Qin     }
562863406b8SStefano Zampini   }
563792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
564792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
565792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
56697c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
567792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
56897c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
5693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57016d9e3a6SLisandro Dalcin }
57116d9e3a6SLisandro Dalcin 
572d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
573d71ae5a4SJacob Faibussowitsch {
57416d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
575f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
57616d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
57716d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
57816d9e3a6SLisandro Dalcin 
57916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5809566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
5819566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
5829566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
5839566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
5849566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
585792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
586792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
587792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
5889371c9d4SSatish Balay   PetscStackCallExternalVoid(
5899371c9d4SSatish Balay     "Hypre solve", do {
5905f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
5915f80ce2aSJacob Faibussowitsch       if (hierr) {
5925f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
59385245615SPierre Jolivet         HYPRE_ClearAllErrors();
5945f80ce2aSJacob Faibussowitsch       }
5955f80ce2aSJacob Faibussowitsch     } while (0));
59616d9e3a6SLisandro Dalcin 
59748a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
5989566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
5999566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
6003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60116d9e3a6SLisandro Dalcin }
60216d9e3a6SLisandro Dalcin 
60385245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
60485245615SPierre Jolivet {
60585245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
606f4f49eeaSPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)jac->hpmat->data;
60785245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
60885245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
60985245615SPierre Jolivet   const PetscScalar  *b;
61085245615SPierre Jolivet   PetscScalar        *x;
61185245615SPierre Jolivet   PetscInt            m, N, lda;
61285245615SPierre Jolivet   hypre_Vector       *x_local;
61385245615SPierre Jolivet   PetscMemType        type;
61485245615SPierre Jolivet 
61585245615SPierre Jolivet   PetscFunctionBegin;
61685245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
61785245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
61885245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
61985245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
62085245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
62185245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
62285245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
62385245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
62485245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &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   PetscCall(MatDenseGetLDA(X, &lda));
62785245615SPierre 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);
62885245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
62985245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
63085245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
63185245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
63285245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
63385245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
63485245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
63585245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
63685245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
63785245615SPierre Jolivet   PetscStackCallExternalVoid(
63885245615SPierre Jolivet     "Hypre solve", do {
63985245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
64085245615SPierre Jolivet       if (hierr) {
64185245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
64285245615SPierre Jolivet         HYPRE_ClearAllErrors();
64385245615SPierre Jolivet       }
64485245615SPierre Jolivet     } while (0));
64585245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
64685245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
64785245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
64885245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
64985245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
65085245615SPierre Jolivet }
65185245615SPierre Jolivet 
652d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
653d71ae5a4SJacob Faibussowitsch {
6548695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6558695de01SBarry Smith 
6568695de01SBarry Smith   PetscFunctionBegin;
6579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
6589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
6599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
6609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
6619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
6629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
6639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
6649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
6659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
6669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
6679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
6689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
6699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
6709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
6719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
6729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
6739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
6749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
6759566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
676be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
6779566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
6785ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
679be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
6805ac14e1cSStefano Zampini   jac->dim                   = 0;
6813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6828695de01SBarry Smith }
6838695de01SBarry Smith 
684d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
685d71ae5a4SJacob Faibussowitsch {
68616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
68716d9e3a6SLisandro Dalcin 
68816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6899566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
690792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
6919566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
6929566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
6939566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
69416d9e3a6SLisandro Dalcin 
6959566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
6969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
6979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
6989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
6999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
7009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
7019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
7029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
7032e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
704be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
7059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
7069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
70742e5ec60SJeff-Hadley   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", NULL));
7089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
7099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
7102e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
7113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71216d9e3a6SLisandro Dalcin }
71316d9e3a6SLisandro Dalcin 
714ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems PetscOptionsObject)
715d71ae5a4SJacob Faibussowitsch {
71616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
717ace3abfcSBarry Smith   PetscBool flag;
71816d9e3a6SLisandro Dalcin 
71916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
720d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
7219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
722792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
7239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
724792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
7259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
726792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
727d0609cedSBarry Smith   PetscOptionsHeadEnd();
7283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72916d9e3a6SLisandro Dalcin }
73016d9e3a6SLisandro Dalcin 
731d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
732d71ae5a4SJacob Faibussowitsch {
73316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
734*9f196a02SMartin Diehl   PetscBool isascii;
73516d9e3a6SLisandro Dalcin 
73616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
737*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
738*9f196a02SMartin Diehl   if (isascii) {
7399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
74016d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
74163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
74216d9e3a6SLisandro Dalcin     } else {
7439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
74416d9e3a6SLisandro Dalcin     }
74516d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
7469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
74716d9e3a6SLisandro Dalcin     } else {
7489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
74916d9e3a6SLisandro Dalcin     }
75016d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
75163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
75216d9e3a6SLisandro Dalcin     } else {
7539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
75416d9e3a6SLisandro Dalcin     }
75516d9e3a6SLisandro Dalcin   }
7563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75716d9e3a6SLisandro Dalcin }
75816d9e3a6SLisandro Dalcin 
7593c61a47dSLukas static const char *HYPREILUType[] = {
7603c61a47dSLukas   "Block-Jacobi-ILUk", "Block-Jacobi-ILUT", "", "", "", "", "", "", "", "", /* 0-9 */
7613c61a47dSLukas   "GMRES-ILUk",        "GMRES-ILUT",        "", "", "", "", "", "", "", "", /* 10-19 */
7623c61a47dSLukas   "NSH-ILUk",          "NSH-ILUT",          "", "", "", "", "", "", "", "", /* 20-29 */
7633c61a47dSLukas   "RAS-ILUk",          "RAS-ILUT",          "", "", "", "", "", "", "", "", /* 30-39 */
7643c61a47dSLukas   "ddPQ-GMRES-ILUk",   "ddPQ-GMRES-ILUT",   "", "", "", "", "", "", "", "", /* 40-49 */
7653c61a47dSLukas   "GMRES-ILU0"                                                              /* 50 */
7663c61a47dSLukas };
7673c61a47dSLukas 
7683c61a47dSLukas static const char *HYPREILUIterSetup[] = {"default", "async-in-place", "async-explicit", "sync-explicit", "semisync-explicit"};
7693c61a47dSLukas 
770ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ILU(PC pc, PetscOptionItems PetscOptionsObject)
7713c61a47dSLukas {
7723c61a47dSLukas   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7733c61a47dSLukas   PetscBool flg;
7743c61a47dSLukas   PetscInt  indx;
7753c61a47dSLukas   PetscReal tmpdbl;
7763c61a47dSLukas   PetscBool tmp_truth;
7773c61a47dSLukas 
7783c61a47dSLukas   PetscFunctionBegin;
7793c61a47dSLukas   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ILU Options");
7803c61a47dSLukas 
7813c61a47dSLukas   /* ILU: ILU Type */
7823c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
7833c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetType, jac->hsolver, indx); }
7843c61a47dSLukas 
7853c61a47dSLukas   /* ILU: ILU iterative setup type*/
7863c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_iterative_setup_type", "Set ILU iterative setup type", "None", HYPREILUIterSetup, PETSC_STATIC_ARRAY_LENGTH(HYPREILUIterSetup), HYPREILUIterSetup[0], &indx, &flg));
7873c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupType, jac->hsolver, indx); }
7883c61a47dSLukas 
7893c61a47dSLukas   /* ILU: ILU iterative setup option*/
7903c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
7913c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupOption, jac->hsolver, indx); }
7923c61a47dSLukas 
7933c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
7943c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
7953c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupMaxIter, jac->hsolver, indx); }
7963c61a47dSLukas 
7973c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
7983c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
7993c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetIterativeSetupTolerance, jac->hsolver, tmpdbl); }
8003c61a47dSLukas 
8013c61a47dSLukas   /* ILU: ILU Print Level */
8023c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
8033c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetPrintLevel, jac->hsolver, indx); }
8043c61a47dSLukas 
8053c61a47dSLukas   /* ILU: Logging */
8063c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
8073c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLogging, jac->hsolver, indx); }
8083c61a47dSLukas 
8093c61a47dSLukas   /* ILU: ILU Level */
8103c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
8113c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLevelOfFill, jac->hsolver, indx); }
8123c61a47dSLukas 
8133c61a47dSLukas   /* ILU: ILU Max NNZ per row */
8143c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
8153c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetMaxNnzPerRow, jac->hsolver, indx); }
8163c61a47dSLukas 
8173c61a47dSLukas   /* ILU: tolerance */
8183c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_tol", "Tolerance for ILU", "None", 0, &tmpdbl, &flg));
8193c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetTol, jac->hsolver, tmpdbl); }
8203c61a47dSLukas 
8213c61a47dSLukas   /* ILU: maximum iteration count */
8223c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
8233c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetMaxIter, jac->hsolver, indx); }
8243c61a47dSLukas 
8253c61a47dSLukas   /* ILU: drop threshold */
8263c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_drop_threshold", "Drop threshold for ILU", "None", 0, &tmpdbl, &flg));
8273c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetDropThreshold, jac->hsolver, tmpdbl); }
8283c61a47dSLukas 
8293c61a47dSLukas   /* ILU: Triangular Solve */
8303c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
8313c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetTriSolve, jac->hsolver, tmp_truth); }
8323c61a47dSLukas 
8333c61a47dSLukas   /* ILU: Lower Jacobi iteration */
8343c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
8353c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLowerJacobiIters, jac->hsolver, indx); }
8363c61a47dSLukas 
8373c61a47dSLukas   /* ILU: Upper Jacobi iteration */
8383c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
8393c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetUpperJacobiIters, jac->hsolver, indx); }
8403c61a47dSLukas 
8413c61a47dSLukas   /* ILU: local reordering */
8423c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
8433c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_ILUSetLocalReordering, jac->hsolver, tmp_truth); }
8443c61a47dSLukas 
8453c61a47dSLukas   PetscOptionsHeadEnd();
8463c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
8473c61a47dSLukas }
8483c61a47dSLukas 
8493c61a47dSLukas static PetscErrorCode PCView_HYPRE_ILU(PC pc, PetscViewer viewer)
8503c61a47dSLukas {
8513c61a47dSLukas   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
8523c61a47dSLukas   hypre_ParILUData *ilu_data = (hypre_ParILUData *)jac->hsolver;
853*9f196a02SMartin Diehl   PetscBool         isascii;
8543c61a47dSLukas   PetscInt          indx;
8553c61a47dSLukas   PetscReal         tmpdbl;
8563c61a47dSLukas   PetscReal        *tmpdbl3;
8573c61a47dSLukas 
8583c61a47dSLukas   PetscFunctionBegin;
859*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
860*9f196a02SMartin Diehl   if (isascii) {
8613c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ILU preconditioning\n"));
8623c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIluType", indx = hypre_ParILUDataIluType(ilu_data));
8633c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
8643c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLfil", indx = hypre_ParILUDataLfil(ilu_data));
8653c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
8663c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxIter", indx = hypre_ParILUDataMaxIter(ilu_data));
8673c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
8683c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxRowNnz", indx = hypre_ParILUDataMaxRowNnz(ilu_data));
8693c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
8703c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTriSolve", indx = hypre_ParILUDataTriSolve(ilu_data));
8713c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
8723c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTol", tmpdbl = hypre_ParILUDataTol(ilu_data));
8733c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", tmpdbl));
8743c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataDroptol", tmpdbl3 = hypre_ParILUDataDroptol(ilu_data));
8753c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e / %e / %e\n", tmpdbl3[0], tmpdbl3[1], tmpdbl3[2]));
8763c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataReorderingType", indx = hypre_ParILUDataReorderingType(ilu_data));
8773c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
8783c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLowerJacobiIters", indx = hypre_ParILUDataLowerJacobiIters(ilu_data));
8793c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
8803c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataUpperJacobiIters", indx = hypre_ParILUDataUpperJacobiIters(ilu_data));
8813c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
8823c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataPrintLevel", indx = hypre_ParILUDataPrintLevel(ilu_data));
8833c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
8843c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLogging", indx = hypre_ParILUDataLogging(ilu_data));
8853c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
8863c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupType", indx = hypre_ParILUDataIterativeSetupType(ilu_data));
8873c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
8883c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupOption", indx = hypre_ParILUDataIterativeSetupOption(ilu_data));
8893c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
8903c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupMaxIter", indx = hypre_ParILUDataIterativeSetupMaxIter(ilu_data));
8913c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
8923c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupTolerance", tmpdbl = hypre_ParILUDataIterativeSetupTolerance(ilu_data));
8933c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", tmpdbl));
8943c61a47dSLukas   }
8953c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
8963c61a47dSLukas }
8973c61a47dSLukas 
898ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems PetscOptionsObject)
899d71ae5a4SJacob Faibussowitsch {
900db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
9018bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
902db966c6cSHong Zhang 
903db966c6cSHong Zhang   PetscFunctionBegin;
904d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
9059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
906792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
9078bf83915SBarry Smith 
9089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
9098bf83915SBarry Smith   if (flag) {
9108bf83915SBarry Smith     PetscMPIInt size;
9118bf83915SBarry Smith 
9129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
9137827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
914792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
9158bf83915SBarry Smith   }
9168bf83915SBarry Smith 
9179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
9188bf83915SBarry Smith   if (flag) {
9198bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
920792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
9218bf83915SBarry Smith   }
922d0609cedSBarry Smith   PetscOptionsHeadEnd();
9233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
924db966c6cSHong Zhang }
925db966c6cSHong Zhang 
926d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
927d71ae5a4SJacob Faibussowitsch {
928db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
929*9f196a02SMartin Diehl   PetscBool isascii;
930db966c6cSHong Zhang 
931db966c6cSHong Zhang   PetscFunctionBegin;
932*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
933*9f196a02SMartin Diehl   if (isascii) {
9349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
935db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
93663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
937db966c6cSHong Zhang     } else {
9389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
939db966c6cSHong Zhang     }
9409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
94163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
942db966c6cSHong Zhang   }
9433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
944db966c6cSHong Zhang }
945db966c6cSHong Zhang 
946d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
947d71ae5a4SJacob Faibussowitsch {
94816d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
949f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
95016d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
95116d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
95216d9e3a6SLisandro Dalcin 
95316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9549566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
9559566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
956af221044SPierre Jolivet   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
957af221044SPierre Jolivet   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
95816d9e3a6SLisandro Dalcin 
959792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
960792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
961792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
96216d9e3a6SLisandro Dalcin 
9639371c9d4SSatish Balay   PetscStackCallExternalVoid(
9649371c9d4SSatish Balay     "Hypre Transpose solve", do {
9655f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
9665f80ce2aSJacob Faibussowitsch       if (hierr) {
96716d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
9685f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
96985245615SPierre Jolivet         HYPRE_ClearAllErrors();
9705f80ce2aSJacob Faibussowitsch       }
9715f80ce2aSJacob Faibussowitsch     } while (0));
97216d9e3a6SLisandro Dalcin 
9739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
9749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
9753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97616d9e3a6SLisandro Dalcin }
97716d9e3a6SLisandro Dalcin 
978d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
979d71ae5a4SJacob Faibussowitsch {
980db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
981db6f9c32SMark Adams 
982db6f9c32SMark Adams   PetscFunctionBegin;
983db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
984db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
985db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
986db6f9c32SMark Adams #endif
9873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
988db6f9c32SMark Adams }
989db6f9c32SMark Adams 
99016d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
9910f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
99216d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
99365de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
9943c61a47dSLukas static const char *HYPREBoomerAMGSmoothType[] = {"ILU", "Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
9959371c9d4SSatish 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"};
9969371c9d4SSatish 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"};
997d7185485SAlex Lindsay 
998ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems PetscOptionsObject)
999d71ae5a4SJacob Faibussowitsch {
100016d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
100122e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
1002ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
100373dcfd97SStefano Zampini   PetscReal   tmpdbl, twodbl[2];
1004589dcaf0SStefano Zampini   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
100516d9e3a6SLisandro Dalcin 
100616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1007d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
10089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
100916d9e3a6SLisandro Dalcin   if (flg) {
10104336a9eeSBarry Smith     jac->cycletype = indx + 1;
1011792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
101216d9e3a6SLisandro Dalcin   }
101352ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg, 2));
101452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
101552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg, 1));
101652ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
101752ce0ab5SPierre 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));
101852ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
101922e51d31SStefano Zampini   bs = 1;
102048a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
102248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
102316d9e3a6SLisandro Dalcin 
102452ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg, 0.0));
102552ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
102616d9e3a6SLisandro Dalcin 
102752ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg, 0));
102852ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
10290f1074feSSatish Balay 
10309566063dSJacob 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));
1031792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
10320f1074feSSatish Balay 
103352ce0ab5SPierre 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));
103452ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
10350f1074feSSatish Balay 
103652ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg, 0.0));
103752ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
103852ce0ab5SPierre Jolivet   PetscCall(PetscOptionsRangeReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg, 0.0, 1.0));
103952ce0ab5SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
104016d9e3a6SLisandro Dalcin 
104116d9e3a6SLisandro Dalcin   /* Grid sweeps */
10429566063dSJacob 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));
104316d9e3a6SLisandro Dalcin   if (flg) {
104416d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
104516d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
10460f1074feSSatish Balay     jac->gridsweeps[1] = indx;
10470f1074feSSatish Balay     /*defaults coarse to 1 */
10480f1074feSSatish Balay     jac->gridsweeps[2] = 1;
104916d9e3a6SLisandro Dalcin   }
10509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
105148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
10529566063dSJacob 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));
105348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
10549566063dSJacob 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));
105548a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
10569566063dSJacob 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));
105748a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
10589566063dSJacob 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));
105948a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
10609566063dSJacob 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));
106148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
10629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
106316d9e3a6SLisandro Dalcin   if (flg) {
1064792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
10650f1074feSSatish Balay     jac->gridsweeps[0] = indx;
106616d9e3a6SLisandro Dalcin   }
10679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
106816d9e3a6SLisandro Dalcin   if (flg) {
1069792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
10700f1074feSSatish Balay     jac->gridsweeps[1] = indx;
107116d9e3a6SLisandro Dalcin   }
10729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
107316d9e3a6SLisandro Dalcin   if (flg) {
1074792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
10750f1074feSSatish Balay     jac->gridsweeps[2] = indx;
107616d9e3a6SLisandro Dalcin   }
107716d9e3a6SLisandro Dalcin 
10786a251517SEike Mueller   /* Smooth type */
1079dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
10806a251517SEike Mueller   if (flg) {
10816a251517SEike Mueller     jac->smoothtype = indx;
10823c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 5);
10838131ecf7SEike Mueller     jac->smoothnumlevels = 25;
1084792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
10858131ecf7SEike Mueller   }
10868131ecf7SEike Mueller 
10878131ecf7SEike Mueller   /* Number of smoothing levels */
10889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
10898131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
10908131ecf7SEike Mueller     jac->smoothnumlevels = indx;
1091792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
10926a251517SEike Mueller   }
10936a251517SEike Mueller 
10943c61a47dSLukas   /* Smooth num sweeps */
10953c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_sweeps", "Set number of smoother sweeps", "None", 1, &indx, &flg));
10963c61a47dSLukas   if (flg && indx > 0) {
10973c61a47dSLukas     jac->smoothsweeps = indx;
10983c61a47dSLukas     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumSweeps, jac->hsolver, indx);
10993c61a47dSLukas   }
11003c61a47dSLukas 
11013c61a47dSLukas   /* ILU: ILU Type */
11023c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
11033c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUType, jac->hsolver, indx); }
11043c61a47dSLukas 
11053c61a47dSLukas   /* ILU: ILU iterative setup type*/
11063c61a47dSLukas   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));
11073c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupType, jac->hsolver, indx); }
11083c61a47dSLukas 
11093c61a47dSLukas   /* ILU: ILU iterative setup option*/
11103c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
11113c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupOption, jac->hsolver, indx); }
11123c61a47dSLukas 
11133c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
11143c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
11153c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUIterSetupMaxIter, jac->hsolver, indx); }
11163c61a47dSLukas 
11173c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
11183c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
11193c61a47dSLukas   if (flg) { PetscCallExternal(hypre_BoomerAMGSetILUIterSetupTolerance, jac->hsolver, tmpdbl); }
11203c61a47dSLukas 
11213c61a47dSLukas   /* ILU: ILU Print Level */
11223c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
11233c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, indx); }
11243c61a47dSLukas 
11253c61a47dSLukas   /* ILU: Logging */
11263c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
11273c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetLogging, jac->hsolver, indx); }
11283c61a47dSLukas 
11293c61a47dSLukas   /* ILU: ILU Level */
11303c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
11313c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULevel, jac->hsolver, indx); }
11323c61a47dSLukas 
11333c61a47dSLukas   /* ILU: ILU Max NNZ per row */
11343c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
11353c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUMaxRowNnz, jac->hsolver, indx); }
11363c61a47dSLukas 
11373c61a47dSLukas   /* ILU: maximum iteration count */
11383c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
11393c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUMaxIter, jac->hsolver, indx); }
11403c61a47dSLukas 
11413c61a47dSLukas   /* ILU: drop threshold */
11423c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_drop_tol", "Drop tolerance for ILU", "None", 0, &tmpdbl, &flg));
11433c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUDroptol, jac->hsolver, tmpdbl); }
11443c61a47dSLukas 
11453c61a47dSLukas   /* ILU: Triangular Solve */
11463c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
11473c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUTriSolve, jac->hsolver, tmp_truth); }
11483c61a47dSLukas 
11493c61a47dSLukas   /* ILU: Lower Jacobi iteration */
11503c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
11513c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULowerJacobiIters, jac->hsolver, indx); }
11523c61a47dSLukas 
11533c61a47dSLukas   /* ILU: Upper Jacobi iteration */
11543c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
11553c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILUUpperJacobiIters, jac->hsolver, indx); }
11563c61a47dSLukas 
11573c61a47dSLukas   /* ILU: local reordering */
11583c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
11593c61a47dSLukas   if (flg) { PetscCallExternal(HYPRE_BoomerAMGSetILULocalReordering, jac->hsolver, tmp_truth); }
11603c61a47dSLukas 
11611810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
11629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
11633c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11641810e44eSEike Mueller     jac->eu_level = indx;
1165792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
11661810e44eSEike Mueller   }
11671810e44eSEike Mueller 
11681810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
116973dcfd97SStefano Zampini   PetscReal droptolerance;
11709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
11713c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11721810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
1173792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
11741810e44eSEike Mueller   }
11751810e44eSEike Mueller 
11761810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
11779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
11783c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11791810e44eSEike Mueller     jac->eu_bj = tmp_truth;
1180792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
11811810e44eSEike Mueller   }
11821810e44eSEike Mueller 
118316d9e3a6SLisandro Dalcin   /* Relax type */
1184dd39110bSPierre 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));
118516d9e3a6SLisandro Dalcin   if (flg) {
11860f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
1187792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
11880f1074feSSatish Balay     /* by default, coarse type set to 9 */
11890f1074feSSatish Balay     jac->relaxtype[2] = 9;
1190792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
119116d9e3a6SLisandro Dalcin   }
1192dd39110bSPierre 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));
119316d9e3a6SLisandro Dalcin   if (flg) {
119416d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
1195792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
119616d9e3a6SLisandro Dalcin   }
1197dd39110bSPierre 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));
119816d9e3a6SLisandro Dalcin   if (flg) {
11990f1074feSSatish Balay     jac->relaxtype[1] = indx;
1200792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
120116d9e3a6SLisandro Dalcin   }
1202dd39110bSPierre 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));
120316d9e3a6SLisandro Dalcin   if (flg) {
12040f1074feSSatish Balay     jac->relaxtype[2] = indx;
1205792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
120616d9e3a6SLisandro Dalcin   }
120716d9e3a6SLisandro Dalcin 
120816d9e3a6SLisandro Dalcin   /* Relaxation Weight */
12099566063dSJacob 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));
121016d9e3a6SLisandro Dalcin   if (flg) {
1211792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
121216d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
121316d9e3a6SLisandro Dalcin   }
121416d9e3a6SLisandro Dalcin 
121516d9e3a6SLisandro Dalcin   n         = 2;
121616d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
12179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
121816d9e3a6SLisandro Dalcin   if (flg) {
12190fdf79fbSJacob 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);
122016d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1221792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
122216d9e3a6SLisandro Dalcin   }
122316d9e3a6SLisandro Dalcin 
122416d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
12259566063dSJacob 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));
122616d9e3a6SLisandro Dalcin   if (flg) {
1227792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
122816d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
122916d9e3a6SLisandro Dalcin   }
123016d9e3a6SLisandro Dalcin 
123116d9e3a6SLisandro Dalcin   n         = 2;
123216d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
12339566063dSJacob 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));
123416d9e3a6SLisandro Dalcin   if (flg) {
12350fdf79fbSJacob 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);
123616d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1237792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
123816d9e3a6SLisandro Dalcin   }
123916d9e3a6SLisandro Dalcin 
124016d9e3a6SLisandro Dalcin   /* the Relax Order */
12419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
124216d9e3a6SLisandro Dalcin 
12438afaa268SBarry Smith   if (flg && tmp_truth) {
124416d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
1245792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
124616d9e3a6SLisandro Dalcin   }
1247dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
124816d9e3a6SLisandro Dalcin   if (flg) {
124916d9e3a6SLisandro Dalcin     jac->measuretype = indx;
1250792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
125116d9e3a6SLisandro Dalcin   }
12520f1074feSSatish Balay   /* update list length 3/07 */
1253dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
125416d9e3a6SLisandro Dalcin   if (flg) {
125516d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
1256792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
125716d9e3a6SLisandro Dalcin   }
12580f1074feSSatish Balay 
12599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
126048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
12619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
126248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
1263db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
1264db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
1265d7185485SAlex 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));
1266d7185485SAlex Lindsay   if (flg) PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, HYPRESpgemmTypes[indx]));
1267db6f9c32SMark Adams #endif
1268589dcaf0SStefano Zampini   /* AIR */
1269589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
12709566063dSJacob 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));
1271792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1272589dcaf0SStefano Zampini   if (jac->Rtype) {
127319be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
127419be502cSAlexander     char       *prerelax[256];
127519be502cSAlexander     char       *postrelax[256];
127619be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
127719be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
127819be502cSAlexander     PetscBool   matchF, matchC, matchA;
127919be502cSAlexander 
1280589dcaf0SStefano 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 */
1281589dcaf0SStefano Zampini 
12829566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
1283792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1284589dcaf0SStefano Zampini 
12859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1286792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1287589dcaf0SStefano Zampini 
12889566063dSJacob 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));
1289792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1290589dcaf0SStefano Zampini 
12919566063dSJacob 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));
1292792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
129319be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
129419be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
129519be502cSAlexander     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");
129619be502cSAlexander     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");
129719be502cSAlexander 
129819be502cSAlexander     grid_relax_points[0]    = NULL;
129919be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
130019be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
130119be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
130219be502cSAlexander     grid_relax_points[3][0] = 0;
130319be502cSAlexander 
130419be502cSAlexander     // set down relax scheme
130519be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
130619be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
130719be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
130819be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
130919be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
131019be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
131119be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
131219be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
131319be502cSAlexander     }
131419be502cSAlexander 
131519be502cSAlexander     // set up relax scheme
131619be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
131719be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
131819be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
131919be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
132019be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
132119be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
132219be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
132319be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
132419be502cSAlexander     }
132519be502cSAlexander 
132619be502cSAlexander     // set coarse relax scheme
132719be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
132819be502cSAlexander 
132919be502cSAlexander     // Pass relax schemes to hypre
133019be502cSAlexander     PetscCallExternal(HYPRE_BoomerAMGSetGridRelaxPoints, jac->hsolver, grid_relax_points);
133119be502cSAlexander 
133219be502cSAlexander     // cleanup memory
133319be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
133419be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1335589dcaf0SStefano Zampini   }
1336589dcaf0SStefano Zampini #endif
1337589dcaf0SStefano Zampini 
1338ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
133963a3b9bcSJacob 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);
1340ecae95adSPierre Jolivet #endif
1341ecae95adSPierre Jolivet 
13420f1074feSSatish Balay   /* new 3/07 */
1343dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1344589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1345589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1346792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
13470f1074feSSatish Balay   }
13480f1074feSSatish Balay 
13499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
135016d9e3a6SLisandro Dalcin   if (flg) {
1351b96a4a96SBarry Smith     level = 3;
13529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
13532fa5cd67SKarl Rupp 
1354b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1355792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
13562ae77aedSBarry Smith   }
13572ae77aedSBarry Smith 
13589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
13592ae77aedSBarry Smith   if (flg) {
1360b96a4a96SBarry Smith     level = 3;
13619566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
13622fa5cd67SKarl Rupp 
1363b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1364792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
136516d9e3a6SLisandro Dalcin   }
13668f87f92bSBarry Smith 
13679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
13688f87f92bSBarry Smith   if (flg && tmp_truth) {
13698f87f92bSBarry Smith     PetscInt tmp_int;
13709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
13718f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1372792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1373792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1374792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1375792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
13768f87f92bSBarry Smith   }
13778f87f92bSBarry Smith 
13789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1379792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1380589dcaf0SStefano Zampini 
1381589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1382dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1383589dcaf0SStefano Zampini   if (flg) {
1384589dcaf0SStefano Zampini     jac->symt = indx;
1385792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1386589dcaf0SStefano Zampini   }
1387589dcaf0SStefano Zampini 
1388d0609cedSBarry Smith   PetscOptionsHeadEnd();
13893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
139016d9e3a6SLisandro Dalcin }
139116d9e3a6SLisandro Dalcin 
1392d71ae5a4SJacob 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)
1393d71ae5a4SJacob Faibussowitsch {
139416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13952cf14000SStefano Zampini   HYPRE_Int oits;
139616d9e3a6SLisandro Dalcin 
139716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13989566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1399792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1400792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
140116d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
14029566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
140316d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1404792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
14054d0a8057SBarry Smith   *outits = oits;
14064d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
14074d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1408792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1409792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
14103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141116d9e3a6SLisandro Dalcin }
141216d9e3a6SLisandro Dalcin 
1413d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1414d71ae5a4SJacob Faibussowitsch {
141516d9e3a6SLisandro Dalcin   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
14163c61a47dSLukas   hypre_ParAMGData *amg_data = (hypre_ParAMGData *)jac->hsolver;
1417*9f196a02SMartin Diehl   PetscBool         isascii;
14183c61a47dSLukas   PetscInt          indx;
14193c61a47dSLukas   PetscReal         val;
142016d9e3a6SLisandro Dalcin 
142116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1422*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1423*9f196a02SMartin Diehl   if (isascii) {
14249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
14259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
142663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
142763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
14289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
14299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
14309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
143163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
143248a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
143363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
143463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
14350f1074feSSatish Balay 
14369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
143716d9e3a6SLisandro Dalcin 
143863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
143963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
144063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
144116d9e3a6SLisandro Dalcin 
14429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
14439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
14449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
144516d9e3a6SLisandro Dalcin 
14469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
14479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
144816d9e3a6SLisandro Dalcin 
144919be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
145019be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
145119be502cSAlexander 
145216d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
14539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
145416d9e3a6SLisandro Dalcin     } else {
14559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
145616d9e3a6SLisandro Dalcin     }
14576a251517SEike Mueller     if (jac->smoothtype != -1) {
14589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
145963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
14603c61a47dSLukas       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num sweeps    %" PetscInt_FMT "\n", jac->smoothsweeps));
14613c61a47dSLukas       if (jac->smoothtype == 0) {
14623c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUType", indx = hypre_ParAMGDataILUType(amg_data));
14633c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
14643c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULevel", indx = hypre_ParAMGDataILULevel(amg_data));
14653c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
14663c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxIter", indx = hypre_ParAMGDataILUMaxIter(amg_data));
14673c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
14683c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxRowNnz", indx = hypre_ParAMGDataILUMaxRowNnz(amg_data));
14693c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
14703c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUTriSolve", indx = hypre_ParAMGDataILUTriSolve(amg_data));
14713c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
14723c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataTol", val = hypre_ParAMGDataTol(amg_data));
14733c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", val));
14743c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUDroptol", val = hypre_ParAMGDataILUDroptol(amg_data));
14753c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e\n", val));
14763c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULocalReordering", indx = hypre_ParAMGDataILULocalReordering(amg_data));
14773c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
14783c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULowerJacobiIters", indx = hypre_ParAMGDataILULowerJacobiIters(amg_data));
14793c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
14803c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUUpperJacobiIters", indx = hypre_ParAMGDataILUUpperJacobiIters(amg_data));
14813c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
14823c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataPrintLevel", indx = hypre_ParAMGDataPrintLevel(amg_data));
14833c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
14843c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataLogging", indx = hypre_ParAMGDataLogging(amg_data));
14853c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
14863c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupType", indx = hypre_ParAMGDataILUIterSetupType(amg_data));
14873c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
14883c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupOption", indx = hypre_ParAMGDataILUIterSetupOption(amg_data));
14893c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
14903c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupMaxIter", indx = hypre_ParAMGDataILUIterSetupMaxIter(amg_data));
14913c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
14923c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupTolerance", val = hypre_ParAMGDataILUIterSetupTolerance(amg_data));
14933c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", val));
14943c61a47dSLukas       }
14957e352d70SEike Mueller     } else {
14969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
14971810e44eSEike Mueller     }
14981810e44eSEike Mueller     if (jac->smoothtype == 3) {
149963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
15009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
150163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
15026a251517SEike Mueller     }
15039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
15049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
15059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
150648a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
15075272c319SBarry Smith     if (jac->vec_interp_variant) {
150863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
150963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
15109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
15118f87f92bSBarry Smith     }
151248a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1513db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
15149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
15152d6c3ceeSStefano Zampini #else
15162d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1517db6f9c32SMark Adams #endif
1518589dcaf0SStefano Zampini     /* AIR */
1519589dcaf0SStefano Zampini     if (jac->Rtype) {
152063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
15219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
15229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
15239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
152463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1525589dcaf0SStefano Zampini     }
152616d9e3a6SLisandro Dalcin   }
15273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152816d9e3a6SLisandro Dalcin }
152916d9e3a6SLisandro Dalcin 
1530ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems PetscOptionsObject)
1531d71ae5a4SJacob Faibussowitsch {
153216d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
15334ddd07fcSJed Brown   PetscInt    indx;
1534ace3abfcSBarry Smith   PetscBool   flag;
153516d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
153616d9e3a6SLisandro Dalcin 
153716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1538d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
15399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
15409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1541792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
154216d9e3a6SLisandro Dalcin 
15439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1544792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
154516d9e3a6SLisandro Dalcin 
15469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1547792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
154816d9e3a6SLisandro Dalcin 
15499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1550792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
155116d9e3a6SLisandro Dalcin 
15529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1553792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
155416d9e3a6SLisandro Dalcin 
1555dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
155616d9e3a6SLisandro Dalcin   if (flag) {
155716d9e3a6SLisandro Dalcin     jac->symt = indx;
1558792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
155916d9e3a6SLisandro Dalcin   }
156016d9e3a6SLisandro Dalcin 
1561d0609cedSBarry Smith   PetscOptionsHeadEnd();
15623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
156316d9e3a6SLisandro Dalcin }
156416d9e3a6SLisandro Dalcin 
1565d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1566d71ae5a4SJacob Faibussowitsch {
156716d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1568*9f196a02SMartin Diehl   PetscBool   isascii;
1569feb237baSPierre Jolivet   const char *symt = 0;
157016d9e3a6SLisandro Dalcin 
157116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1572*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1573*9f196a02SMartin Diehl   if (isascii) {
15749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
157563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
15769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
15779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
15789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
15799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
15809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
15812fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
15822fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
15832fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
158463a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
15859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
158616d9e3a6SLisandro Dalcin   }
15873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
158816d9e3a6SLisandro Dalcin }
1589f1580f4eSBarry Smith 
1590ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems PetscOptionsObject)
1591d71ae5a4SJacob Faibussowitsch {
15924cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15934cb006feSStefano Zampini   PetscInt  n;
15944cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
15954cb006feSStefano Zampini 
15964cb006feSStefano Zampini   PetscFunctionBegin;
1597d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
15989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1599792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
16009566063dSJacob 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));
1601792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
16029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1603792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
16049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1605792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
16069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
16079566063dSJacob 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));
16089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
16099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
161048a46eb9SPierre 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);
16119566063dSJacob 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));
16124cb006feSStefano Zampini   n = 5;
16139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
16144cb006feSStefano Zampini   if (flag || flag2) {
1615792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1616863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1617863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
16189371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1619a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
16204cb006feSStefano Zampini   }
16219566063dSJacob 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));
16224cb006feSStefano Zampini   n = 5;
16239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
16244cb006feSStefano Zampini   if (flag || flag2) {
1625792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1626863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1627863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
16289371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1629a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
16304cb006feSStefano Zampini   }
16319566063dSJacob 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));
163223df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1633792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
163423df4f25SStefano Zampini   }
1635d0609cedSBarry Smith   PetscOptionsHeadEnd();
16363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16374cb006feSStefano Zampini }
16384cb006feSStefano Zampini 
1639d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1640d71ae5a4SJacob Faibussowitsch {
16414cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1642*9f196a02SMartin Diehl   PetscBool isascii;
16434cb006feSStefano Zampini 
16444cb006feSStefano Zampini   PetscFunctionBegin;
1645*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1646*9f196a02SMartin Diehl   if (isascii) {
16479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
164863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
164963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
165063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
165163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
165263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
165363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
165463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
16554cb006feSStefano Zampini     if (jac->alpha_Poisson) {
16569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
16574cb006feSStefano Zampini     } else {
16589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
16594cb006feSStefano Zampini     }
166063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
166163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
166263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
166363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
166463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
166563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
16664cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
16674cb006feSStefano Zampini       if (jac->beta_Poisson) {
16689566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
16694cb006feSStefano Zampini       } else {
16709566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
16714cb006feSStefano Zampini       }
167263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
167363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
167463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
167563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
167663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
167763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
167848a46eb9SPierre 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));
167923df4f25SStefano Zampini     } else {
16809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
16814cb006feSStefano Zampini     }
16824cb006feSStefano Zampini   }
16833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16844cb006feSStefano Zampini }
16854cb006feSStefano Zampini 
1686ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems PetscOptionsObject)
1687d71ae5a4SJacob Faibussowitsch {
1688863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1689863406b8SStefano Zampini   PetscInt  n;
1690863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1691863406b8SStefano Zampini 
1692863406b8SStefano Zampini   PetscFunctionBegin;
1693d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
16949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1695792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
16969566063dSJacob 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));
1697792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
16989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1699792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
17009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1701792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
17029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
17039566063dSJacob 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));
17049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
17059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
170648a46eb9SPierre 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);
17079566063dSJacob 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));
1708863406b8SStefano Zampini   n = 5;
17099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
17109566063dSJacob 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));
1711863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1712792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1713863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1714863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1715863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
17169371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1717a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1718863406b8SStefano Zampini   }
17199566063dSJacob 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));
1720863406b8SStefano Zampini   n = 5;
17219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1722863406b8SStefano Zampini   if (flag || flag2) {
1723792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1724863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1725863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
17269371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1727a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1728863406b8SStefano Zampini   }
1729d0609cedSBarry Smith   PetscOptionsHeadEnd();
17303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1731863406b8SStefano Zampini }
1732863406b8SStefano Zampini 
1733d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1734d71ae5a4SJacob Faibussowitsch {
1735863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1736*9f196a02SMartin Diehl   PetscBool isascii;
1737863406b8SStefano Zampini 
1738863406b8SStefano Zampini   PetscFunctionBegin;
1739*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1740*9f196a02SMartin Diehl   if (isascii) {
17419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
174263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
174363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
174463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
174563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
174663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
174763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
174863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
17499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
175063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
175163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
175263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
175363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
175463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
175563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
175663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
17579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
175863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
175963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
176063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
176163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
176263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
176363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1764863406b8SStefano Zampini   }
17653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1766863406b8SStefano Zampini }
1767863406b8SStefano Zampini 
1768d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1769d71ae5a4SJacob Faibussowitsch {
17704cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17715ac14e1cSStefano Zampini   PetscBool ishypre;
17724cb006feSStefano Zampini 
17734cb006feSStefano Zampini   PetscFunctionBegin;
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
17755ac14e1cSStefano Zampini   if (ishypre) {
17769566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
17779566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17785ac14e1cSStefano Zampini     jac->G = G;
17795ac14e1cSStefano Zampini   } else {
17809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17819566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
17825ac14e1cSStefano Zampini   }
17833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17844cb006feSStefano Zampini }
17854cb006feSStefano Zampini 
17864cb006feSStefano Zampini /*@
1787f1580f4eSBarry Smith   PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
17884cb006feSStefano Zampini 
1789c3339decSBarry Smith   Collective
17904cb006feSStefano Zampini 
17914cb006feSStefano Zampini   Input Parameters:
17924cb006feSStefano Zampini + pc - the preconditioning context
17934cb006feSStefano Zampini - G  - the discrete gradient
17944cb006feSStefano Zampini 
17954cb006feSStefano Zampini   Level: intermediate
17964cb006feSStefano Zampini 
179795452b02SPatrick Sanan   Notes:
179895452b02SPatrick Sanan   G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1799147403d9SBarry Smith 
1800863406b8SStefano Zampini   Each row of G has 2 nonzeros, with column indexes being the global indexes of edge's endpoints: matrix entries are +1 and -1 depending on edge orientation
18014cb006feSStefano Zampini 
1802feefa0e1SJacob Faibussowitsch   Developer Notes:
1803f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1804f1580f4eSBarry Smith 
1805562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
18064cb006feSStefano Zampini @*/
1807d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1808d71ae5a4SJacob Faibussowitsch {
18094cb006feSStefano Zampini   PetscFunctionBegin;
18104cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18114cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
18124cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1813cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
18143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18154cb006feSStefano Zampini }
18164cb006feSStefano Zampini 
1817d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1818d71ae5a4SJacob Faibussowitsch {
1819863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18205ac14e1cSStefano Zampini   PetscBool ishypre;
1821863406b8SStefano Zampini 
1822863406b8SStefano Zampini   PetscFunctionBegin;
18239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
18245ac14e1cSStefano Zampini   if (ishypre) {
18259566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
18269566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
18275ac14e1cSStefano Zampini     jac->C = C;
18285ac14e1cSStefano Zampini   } else {
18299566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
18309566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
18315ac14e1cSStefano Zampini   }
18323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1833863406b8SStefano Zampini }
1834863406b8SStefano Zampini 
1835863406b8SStefano Zampini /*@
18366e415bd2SNuno Nobre   PCHYPRESetDiscreteCurl - Set discrete curl matrix for `PCHYPRE` type of ads
1837863406b8SStefano Zampini 
1838c3339decSBarry Smith   Collective
1839863406b8SStefano Zampini 
1840863406b8SStefano Zampini   Input Parameters:
1841863406b8SStefano Zampini + pc - the preconditioning context
1842863406b8SStefano Zampini - C  - the discrete curl
1843863406b8SStefano Zampini 
1844863406b8SStefano Zampini   Level: intermediate
1845863406b8SStefano Zampini 
184695452b02SPatrick Sanan   Notes:
184795452b02SPatrick Sanan   C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1848147403d9SBarry Smith 
18496e415bd2SNuno Nobre   Each row of C has as many nonzeros as the number of edges of a face, with column indexes being the global indexes of the corresponding edge: matrix entries are +1 and -1 depending on edge orientation with respect to the face orientation
1850863406b8SStefano Zampini 
1851feefa0e1SJacob Faibussowitsch   Developer Notes:
1852f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1853f1580f4eSBarry Smith 
1854f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1855f1580f4eSBarry Smith 
1856562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1857863406b8SStefano Zampini @*/
1858d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1859d71ae5a4SJacob Faibussowitsch {
1860863406b8SStefano Zampini   PetscFunctionBegin;
1861863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1862863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1863863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1864cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
18653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1866863406b8SStefano Zampini }
1867863406b8SStefano Zampini 
1868d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1869d71ae5a4SJacob Faibussowitsch {
18706bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18716bf688a0SCe Qin   PetscBool ishypre;
18726bf688a0SCe Qin   PetscInt  i;
18736bf688a0SCe Qin 
18744d86920dSPierre Jolivet   PetscFunctionBegin;
18759566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
18769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
18776bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
18789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
18799566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
18806bf688a0SCe Qin   }
18816bf688a0SCe Qin 
18826bf688a0SCe Qin   jac->dim = dim;
18836bf688a0SCe Qin   if (RT_PiFull) {
18849566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
18856bf688a0SCe Qin     if (ishypre) {
18869566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
18876bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
18886bf688a0SCe Qin     } else {
18899566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
18906bf688a0SCe Qin     }
18916bf688a0SCe Qin   }
18926bf688a0SCe Qin   if (RT_Pi) {
18936bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18946bf688a0SCe Qin       if (RT_Pi[i]) {
18959566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
18966bf688a0SCe Qin         if (ishypre) {
18979566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
18986bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
18996bf688a0SCe Qin         } else {
19009566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
19016bf688a0SCe Qin         }
19026bf688a0SCe Qin       }
19036bf688a0SCe Qin     }
19046bf688a0SCe Qin   }
19056bf688a0SCe Qin   if (ND_PiFull) {
19069566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
19076bf688a0SCe Qin     if (ishypre) {
19089566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
19096bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
19106bf688a0SCe Qin     } else {
19119566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
19126bf688a0SCe Qin     }
19136bf688a0SCe Qin   }
19146bf688a0SCe Qin   if (ND_Pi) {
19156bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19166bf688a0SCe Qin       if (ND_Pi[i]) {
19179566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
19186bf688a0SCe Qin         if (ishypre) {
19199566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
19206bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
19216bf688a0SCe Qin         } else {
19229566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
19236bf688a0SCe Qin         }
19246bf688a0SCe Qin       }
19256bf688a0SCe Qin     }
19266bf688a0SCe Qin   }
19273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19286bf688a0SCe Qin }
19296bf688a0SCe Qin 
19306bf688a0SCe Qin /*@
1931f1580f4eSBarry Smith   PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
19326bf688a0SCe Qin 
1933c3339decSBarry Smith   Collective
19346bf688a0SCe Qin 
19356bf688a0SCe Qin   Input Parameters:
19366bf688a0SCe Qin + pc        - the preconditioning context
19372fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
19382fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
19392fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
19402fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
19416bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
19426bf688a0SCe Qin 
1943f1580f4eSBarry Smith   Level: intermediate
1944f1580f4eSBarry Smith 
194595452b02SPatrick Sanan   Notes:
194695452b02SPatrick Sanan   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1947147403d9SBarry Smith 
19486bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1949147403d9SBarry Smith 
1950feefa0e1SJacob Faibussowitsch   Developer Notes:
1951f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
19526bf688a0SCe Qin 
1953562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
19546bf688a0SCe Qin @*/
1955d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1956d71ae5a4SJacob Faibussowitsch {
19576bf688a0SCe Qin   PetscInt i;
19586bf688a0SCe Qin 
19596bf688a0SCe Qin   PetscFunctionBegin;
19606bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19616bf688a0SCe Qin   if (RT_PiFull) {
19626bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
19636bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
19646bf688a0SCe Qin   }
19656bf688a0SCe Qin   if (RT_Pi) {
19664f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
19676bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19686bf688a0SCe Qin       if (RT_Pi[i]) {
19696bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
19706bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
19716bf688a0SCe Qin       }
19726bf688a0SCe Qin     }
19736bf688a0SCe Qin   }
19746bf688a0SCe Qin   if (ND_PiFull) {
19756bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
19766bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
19776bf688a0SCe Qin   }
19786bf688a0SCe Qin   if (ND_Pi) {
19794f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
19806bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19816bf688a0SCe Qin       if (ND_Pi[i]) {
19826bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
19836bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
19846bf688a0SCe Qin       }
19856bf688a0SCe Qin     }
19866bf688a0SCe Qin   }
1987cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
19883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19896bf688a0SCe Qin }
19906bf688a0SCe Qin 
1991d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1992d71ae5a4SJacob Faibussowitsch {
19934cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
19945ac14e1cSStefano Zampini   PetscBool ishypre;
19954cb006feSStefano Zampini 
19964cb006feSStefano Zampini   PetscFunctionBegin;
19979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
19985ac14e1cSStefano Zampini   if (ishypre) {
19995ac14e1cSStefano Zampini     if (isalpha) {
20009566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
20019566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
20025ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
20035ac14e1cSStefano Zampini     } else {
20045ac14e1cSStefano Zampini       if (A) {
20059566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
20065ac14e1cSStefano Zampini       } else {
20075ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
20085ac14e1cSStefano Zampini       }
20099566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
20105ac14e1cSStefano Zampini       jac->beta_Poisson = A;
20115ac14e1cSStefano Zampini     }
20125ac14e1cSStefano Zampini   } else {
20135ac14e1cSStefano Zampini     if (isalpha) {
20149566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
20159566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
20165ac14e1cSStefano Zampini     } else {
20175ac14e1cSStefano Zampini       if (A) {
20189566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
20199566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
20205ac14e1cSStefano Zampini       } else {
20219566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
20225ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
20235ac14e1cSStefano Zampini       }
20245ac14e1cSStefano Zampini     }
20255ac14e1cSStefano Zampini   }
20263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20274cb006feSStefano Zampini }
20284cb006feSStefano Zampini 
20294cb006feSStefano Zampini /*@
2030f1580f4eSBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
20314cb006feSStefano Zampini 
2032c3339decSBarry Smith   Collective
20334cb006feSStefano Zampini 
20344cb006feSStefano Zampini   Input Parameters:
20354cb006feSStefano Zampini + pc - the preconditioning context
20364cb006feSStefano Zampini - A  - the matrix
20374cb006feSStefano Zampini 
20384cb006feSStefano Zampini   Level: intermediate
20394cb006feSStefano Zampini 
2040f1580f4eSBarry Smith   Note:
204195452b02SPatrick Sanan   A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
20424cb006feSStefano Zampini 
2043feefa0e1SJacob Faibussowitsch   Developer Notes:
2044f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2045f1580f4eSBarry Smith 
2046f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
2047f1580f4eSBarry Smith 
2048562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
20494cb006feSStefano Zampini @*/
2050d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
2051d71ae5a4SJacob Faibussowitsch {
20524cb006feSStefano Zampini   PetscFunctionBegin;
20534cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20544cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20554cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
2056cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
20573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20584cb006feSStefano Zampini }
20594cb006feSStefano Zampini 
20604cb006feSStefano Zampini /*@
2061f1580f4eSBarry Smith   PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
20624cb006feSStefano Zampini 
2063c3339decSBarry Smith   Collective
20644cb006feSStefano Zampini 
20654cb006feSStefano Zampini   Input Parameters:
20664cb006feSStefano Zampini + pc - the preconditioning context
2067f1580f4eSBarry Smith - A  - the matrix, or NULL to turn it off
20684cb006feSStefano Zampini 
20694cb006feSStefano Zampini   Level: intermediate
20704cb006feSStefano Zampini 
2071f1580f4eSBarry Smith   Note:
207295452b02SPatrick Sanan   A should be obtained by discretizing the Poisson problem with linear finite elements.
20734cb006feSStefano Zampini 
2074feefa0e1SJacob Faibussowitsch   Developer Notes:
2075f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2076f1580f4eSBarry Smith 
2077f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
2078f1580f4eSBarry Smith 
2079562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
20804cb006feSStefano Zampini @*/
2081d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
2082d71ae5a4SJacob Faibussowitsch {
20834cb006feSStefano Zampini   PetscFunctionBegin;
20844cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20854cb006feSStefano Zampini   if (A) {
20864cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20874cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
20884cb006feSStefano Zampini   }
2089cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
20903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20914cb006feSStefano Zampini }
20924cb006feSStefano Zampini 
2093d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
2094d71ae5a4SJacob Faibussowitsch {
20954cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
20964cb006feSStefano Zampini 
20974cb006feSStefano Zampini   PetscFunctionBegin;
20984cb006feSStefano Zampini   /* throw away any vector if already set */
20999566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
21009566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
21019566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
21029566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
21039566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
21049566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
21059566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
21065ac14e1cSStefano Zampini   jac->dim = 2;
21074cb006feSStefano Zampini   if (zzo) {
21089566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
21099566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
21105ac14e1cSStefano Zampini     jac->dim++;
21114cb006feSStefano Zampini   }
21123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21134cb006feSStefano Zampini }
21144cb006feSStefano Zampini 
21154cb006feSStefano Zampini /*@
2116f1580f4eSBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
21174cb006feSStefano Zampini 
2118c3339decSBarry Smith   Collective
21194cb006feSStefano Zampini 
21204cb006feSStefano Zampini   Input Parameters:
21214cb006feSStefano Zampini + pc  - the preconditioning context
21222fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
21232fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
21244cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
21254cb006feSStefano Zampini 
21264cb006feSStefano Zampini   Level: intermediate
21274cb006feSStefano Zampini 
2128feefa0e1SJacob Faibussowitsch   Developer Notes:
2129f1580f4eSBarry Smith   If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
2130f1580f4eSBarry Smith 
2131562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
21324cb006feSStefano Zampini @*/
2133d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
2134d71ae5a4SJacob Faibussowitsch {
21354cb006feSStefano Zampini   PetscFunctionBegin;
21364cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
21374cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
21384cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
21394cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
21404cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
21414cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
21424cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
2143cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
21443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21454cb006feSStefano Zampini }
21464cb006feSStefano Zampini 
2147d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
2148d71ae5a4SJacob Faibussowitsch {
2149be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2150be14dc20SKerry Key 
2151be14dc20SKerry Key   PetscFunctionBegin;
2152be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
2153be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
2154be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
2155be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
21563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2157be14dc20SKerry Key }
2158be14dc20SKerry Key 
2159be14dc20SKerry Key /*@
2160f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
2161be14dc20SKerry Key 
2162c3339decSBarry Smith   Collective
2163be14dc20SKerry Key 
2164be14dc20SKerry Key   Input Parameters:
2165be14dc20SKerry Key + pc       - the preconditioning context
2166be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
2167be14dc20SKerry Key 
2168be14dc20SKerry Key   Level: intermediate
2169be14dc20SKerry Key 
2170be14dc20SKerry Key   Note:
2171f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
2172f1580f4eSBarry Smith 
2173562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
2174be14dc20SKerry Key @*/
2175d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
2176d71ae5a4SJacob Faibussowitsch {
2177be14dc20SKerry Key   PetscFunctionBegin;
2178be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2179be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
2180be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
2181be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
21823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2183be14dc20SKerry Key }
2184be14dc20SKerry Key 
2185d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2186d71ae5a4SJacob Faibussowitsch {
21874cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
21884cb006feSStefano Zampini   Vec       tv;
21894cb006feSStefano Zampini   PetscInt  i;
21904cb006feSStefano Zampini 
21914cb006feSStefano Zampini   PetscFunctionBegin;
21924cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
21939566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
21949566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
21959566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
21965ac14e1cSStefano Zampini   jac->dim = dim;
21975ac14e1cSStefano Zampini 
21984cb006feSStefano Zampini   /* compute IJ vector for coordinates */
21999566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
22009566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
22019566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
22024cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
22034cb006feSStefano Zampini     PetscScalar *array;
22044cb006feSStefano Zampini     PetscInt     j;
22054cb006feSStefano Zampini 
22069566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
22079566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
22086ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
22099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
22109566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
22114cb006feSStefano Zampini   }
22129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
22133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22144cb006feSStefano Zampini }
22154cb006feSStefano Zampini 
2216d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
2217d71ae5a4SJacob Faibussowitsch {
221816d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
221916d9e3a6SLisandro Dalcin 
222016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
222116d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
22223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222316d9e3a6SLisandro Dalcin }
222416d9e3a6SLisandro Dalcin 
2225d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
2226d71ae5a4SJacob Faibussowitsch {
222716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2228ace3abfcSBarry Smith   PetscBool flag;
222916d9e3a6SLisandro Dalcin 
223016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
223116d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
22329566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
2233d7185485SAlex Lindsay     if (flag) PetscFunctionReturn(PETSC_SUCCESS);
223416d9e3a6SLisandro Dalcin   }
223516d9e3a6SLisandro Dalcin 
2236d7185485SAlex Lindsay   PetscCall(PCReset_HYPRE(pc));
2237d7185485SAlex Lindsay   PetscCall(PetscFree(jac->hypre_type));
2238d7185485SAlex Lindsay   PetscCall(PetscStrallocpy(name, &jac->hypre_type));
2239d7185485SAlex Lindsay 
224016d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
224116d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
224216d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
224316d9e3a6SLisandro Dalcin 
22443c61a47dSLukas   PetscCall(PetscStrcmp("ilu", jac->hypre_type, &flag));
22453c61a47dSLukas   if (flag) {
22463c61a47dSLukas     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
22473c61a47dSLukas     PetscCallExternal(HYPRE_ILUCreate, &jac->hsolver);
22483c61a47dSLukas     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ILU;
22493c61a47dSLukas     pc->ops->view           = PCView_HYPRE_ILU;
22503c61a47dSLukas     jac->destroy            = HYPRE_ILUDestroy;
22513c61a47dSLukas     jac->setup              = HYPRE_ILUSetup;
22523c61a47dSLukas     jac->solve              = HYPRE_ILUSolve;
22533c61a47dSLukas     jac->factorrowsize      = PETSC_DEFAULT;
22543c61a47dSLukas     PetscFunctionReturn(PETSC_SUCCESS);
22553c61a47dSLukas   }
22563c61a47dSLukas 
22579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
225816d9e3a6SLisandro Dalcin   if (flag) {
22599566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2260792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
226116d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
226216d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
226316d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
226416d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
226516d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
226616d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
22673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
226816d9e3a6SLisandro Dalcin   }
22699566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
2270db966c6cSHong Zhang   if (flag) {
22714e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
22727de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
22738bf83915SBarry Smith #endif
22749566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2275792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
2276db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
2277db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
2278db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
2279db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
2280db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
2281db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
2282db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
22833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2284db966c6cSHong Zhang   }
22859566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
228616d9e3a6SLisandro Dalcin   if (flag) {
22879566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2288792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
228916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
229016d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
229116d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
229216d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
229316d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
229416d9e3a6SLisandro Dalcin     /* initialize */
229516d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
22968966356dSPierre Jolivet     jac->threshold = .1;
229716d9e3a6SLisandro Dalcin     jac->filter    = .1;
229816d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
22992fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
23002fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
23012fa5cd67SKarl Rupp 
230216d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
230316d9e3a6SLisandro Dalcin     jac->symt = 0;
2304792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
2305792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
2306792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
2307792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
2308792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
2309792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
23103ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
231116d9e3a6SLisandro Dalcin   }
23129566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
231316d9e3a6SLisandro Dalcin   if (flag) {
2314792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
231516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
231616d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
231716d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
231816d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
231985245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
23209566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
23219566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
232242e5ec60SJeff-Hadley     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", PCHYPREGetCFMarkers_BoomerAMG));
232316d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
232416d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
232516d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
232616d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
232716d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
232816d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
232916d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
233016d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
23318f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
233216d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
233316d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
233416d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
233516d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
23360f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
23376a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2338b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
23391810e44eSEike Mueller     jac->eu_level                                                = 0;
23401810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
23411810e44eSEike Mueller     jac->eu_bj                                                   = 0;
234216d9e3a6SLisandro Dalcin     jac->relaxweight                                             = 1.0;
234316d9e3a6SLisandro Dalcin     jac->outerrelaxweight                                        = 1.0;
2344589dcaf0SStefano Zampini     jac->Rtype                                                   = 0;
2345589dcaf0SStefano Zampini     jac->Rstrongthreshold                                        = 0.25;
2346589dcaf0SStefano Zampini     jac->Rfilterthreshold                                        = 0.0;
2347589dcaf0SStefano Zampini     jac->Adroptype                                               = -1;
2348589dcaf0SStefano Zampini     jac->Adroptol                                                = 0.0;
23490f1074feSSatish Balay     jac->agg_nl                                                  = 0;
23500f1074feSSatish Balay     jac->pmax                                                    = 0;
23510f1074feSSatish Balay     jac->truncfactor                                             = 0.0;
23520f1074feSSatish Balay     jac->agg_num_paths                                           = 1;
2353589dcaf0SStefano Zampini     jac->maxc                                                    = 9;
2354589dcaf0SStefano Zampini     jac->minc                                                    = 1;
235522e51d31SStefano Zampini     jac->nodal_coarsening                                        = 0;
235622e51d31SStefano Zampini     jac->nodal_coarsening_diag                                   = 0;
235722e51d31SStefano Zampini     jac->vec_interp_variant                                      = 0;
235822e51d31SStefano Zampini     jac->vec_interp_qmax                                         = 0;
235922e51d31SStefano Zampini     jac->vec_interp_smooth                                       = PETSC_FALSE;
236022e51d31SStefano Zampini     jac->interp_refine                                           = 0;
23618f87f92bSBarry Smith     jac->nodal_relax                                             = PETSC_FALSE;
23628f87f92bSBarry Smith     jac->nodal_relax_levels                                      = 1;
23636ea7df73SStefano Zampini     jac->rap2                                                    = 0;
2364d7185485SAlex Lindsay     PetscObjectParameterSetDefault(jac, relaxorder, -1); /* Initialize with invalid value so we can recognize user input */
23653ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
236616d9e3a6SLisandro Dalcin   }
23679566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
23684cb006feSStefano Zampini   if (flag) {
23693ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
23704cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
23714cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
23724cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
23734cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
23744cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
23754cb006feSStefano Zampini     jac->coords[0]          = NULL;
23764cb006feSStefano Zampini     jac->coords[1]          = NULL;
23774cb006feSStefano Zampini     jac->coords[2]          = NULL;
2378be14dc20SKerry Key     jac->interior           = NULL;
23794cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2380863406b8SStefano Zampini     jac->as_print       = 0;
2381863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2382863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
23834cb006feSStefano Zampini     jac->ams_cycle_type = 13;
23844cb006feSStefano Zampini     /* Smoothing options */
2385863406b8SStefano Zampini     jac->as_relax_type   = 2;
2386863406b8SStefano Zampini     jac->as_relax_times  = 1;
2387863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2388863406b8SStefano Zampini     jac->as_omega        = 1.0;
23894cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2390863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2391863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
23920bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2393863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2394863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2395863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
23964cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2397863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2398863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
23990bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2400863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2401863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2402863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2403792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2404792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2405792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2406792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
24079371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2408792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2409863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2410863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
24119371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2412a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2413792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2414863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2415863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
24169371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2417a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
241823df4f25SStefano Zampini     /* Zero conductivity */
241923df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
242023df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
24213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
24224cb006feSStefano Zampini   }
24239566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2424863406b8SStefano Zampini   if (flag) {
24253ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2426863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2427863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2428863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2429863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2430863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2431863406b8SStefano Zampini     jac->coords[0]          = NULL;
2432863406b8SStefano Zampini     jac->coords[1]          = NULL;
2433863406b8SStefano Zampini     jac->coords[2]          = NULL;
2434863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2435863406b8SStefano Zampini     jac->as_print       = 0;
2436863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2437863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2438863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2439863406b8SStefano Zampini     /* Smoothing options */
2440863406b8SStefano Zampini     jac->as_relax_type   = 2;
2441863406b8SStefano Zampini     jac->as_relax_times  = 1;
2442863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2443863406b8SStefano Zampini     jac->as_omega        = 1.0;
2444863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2445863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2446863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2447863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2448863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2449863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2450863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2451863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2452863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2453863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2454863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2455863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2456863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2457863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2458863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2459792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2460792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2461792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2462792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
24639371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2464792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2465863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2466863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2467863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
24689371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2469a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2470792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2471863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2472863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
24739371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2474a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
24753ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2476863406b8SStefano Zampini   }
24779566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
24782fa5cd67SKarl Rupp 
24790298fd71SBarry Smith   jac->hypre_type = NULL;
2480b06c524fSNuno Nobre   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, ilu, pilut, parasails, boomeramg, ams, ads", name);
248116d9e3a6SLisandro Dalcin }
248216d9e3a6SLisandro Dalcin 
248316d9e3a6SLisandro Dalcin /*
248416d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
248516d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
248616d9e3a6SLisandro Dalcin */
2487ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems PetscOptionsObject)
2488d71ae5a4SJacob Faibussowitsch {
24894ddd07fcSJed Brown   PetscInt    indx;
24903c61a47dSLukas   const char *type[] = {"ilu", "euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2491ace3abfcSBarry Smith   PetscBool   flg;
2492d7185485SAlex Lindsay   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
249316d9e3a6SLisandro Dalcin 
249416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2495d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2496dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
2497d7185485SAlex Lindsay   if (flg) PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
2498d7185485SAlex Lindsay   /*
2499d7185485SAlex Lindsay     Set the type if it was never set.
2500d7185485SAlex Lindsay   */
2501d7185485SAlex Lindsay   if (!jac->hypre_type) PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
2502dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2503d0609cedSBarry Smith   PetscOptionsHeadEnd();
25043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250516d9e3a6SLisandro Dalcin }
250616d9e3a6SLisandro Dalcin 
2507cc4c1da9SBarry Smith /*@
250816d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
250916d9e3a6SLisandro Dalcin 
251016d9e3a6SLisandro Dalcin   Input Parameters:
251116d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2512b06c524fSNuno Nobre - name - either euclid, ilu, pilut, parasails, boomeramg, ams, ads
251316d9e3a6SLisandro Dalcin 
2514f1580f4eSBarry Smith   Options Database Key:
2515b06c524fSNuno Nobre . pc_hypre_type - One of euclid, ilu, pilut, parasails, boomeramg, ams, ads
251616d9e3a6SLisandro Dalcin 
251716d9e3a6SLisandro Dalcin   Level: intermediate
251816d9e3a6SLisandro Dalcin 
2519562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
252016d9e3a6SLisandro Dalcin @*/
2521d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2522d71ae5a4SJacob Faibussowitsch {
252316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25240700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25254f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2526cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
25273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
252816d9e3a6SLisandro Dalcin }
252916d9e3a6SLisandro Dalcin 
253042e5ec60SJeff-Hadley /*@C
253142e5ec60SJeff-Hadley   PCHYPREGetCFMarkers - Gets CF marker arrays for all levels (except the finest level)
253242e5ec60SJeff-Hadley 
253342e5ec60SJeff-Hadley   Logically Collective
253442e5ec60SJeff-Hadley 
253542e5ec60SJeff-Hadley   Input Parameter:
253642e5ec60SJeff-Hadley . pc - the preconditioner context
253742e5ec60SJeff-Hadley 
253842e5ec60SJeff-Hadley   Output Parameters:
253942e5ec60SJeff-Hadley + n_per_level - the number of nodes per level (size of `num_levels`)
254042e5ec60SJeff-Hadley - CFMarkers   - the Coarse/Fine Boolean arrays (size of `num_levels` - 1)
254142e5ec60SJeff-Hadley 
254242e5ec60SJeff-Hadley   Note:
254342e5ec60SJeff-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.
254442e5ec60SJeff-Hadley 
254542e5ec60SJeff-Hadley   Level: advanced
254642e5ec60SJeff-Hadley 
254742e5ec60SJeff-Hadley .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
254842e5ec60SJeff-Hadley @*/
254942e5ec60SJeff-Hadley PetscErrorCode PCHYPREGetCFMarkers(PC pc, PetscInt *n_per_level[], PetscBT *CFMarkers[])
255042e5ec60SJeff-Hadley {
255142e5ec60SJeff-Hadley   PetscFunctionBegin;
255242e5ec60SJeff-Hadley   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
255342e5ec60SJeff-Hadley   PetscAssertPointer(n_per_level, 2);
255442e5ec60SJeff-Hadley   PetscAssertPointer(CFMarkers, 3);
255542e5ec60SJeff-Hadley   PetscUseMethod(pc, "PCHYPREGetCFMarkers_C", (PC, PetscInt *[], PetscBT *[]), (pc, n_per_level, CFMarkers));
255642e5ec60SJeff-Hadley   PetscFunctionReturn(PETSC_SUCCESS);
255742e5ec60SJeff-Hadley }
255842e5ec60SJeff-Hadley 
2559cc4c1da9SBarry Smith /*@
256016d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
256116d9e3a6SLisandro Dalcin 
256216d9e3a6SLisandro Dalcin   Input Parameter:
256316d9e3a6SLisandro Dalcin . pc - the preconditioner context
256416d9e3a6SLisandro Dalcin 
256516d9e3a6SLisandro Dalcin   Output Parameter:
2566b06c524fSNuno Nobre . name - either euclid, ilu, pilut, parasails, boomeramg, ams, ads
256716d9e3a6SLisandro Dalcin 
256816d9e3a6SLisandro Dalcin   Level: intermediate
256916d9e3a6SLisandro Dalcin 
2570562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
257116d9e3a6SLisandro Dalcin @*/
2572d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2573d71ae5a4SJacob Faibussowitsch {
257416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25750700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25764f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2577cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
25783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257916d9e3a6SLisandro Dalcin }
258016d9e3a6SLisandro Dalcin 
2581cc4c1da9SBarry Smith /*@
2582f1580f4eSBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2583db6f9c32SMark Adams 
2584c3339decSBarry Smith   Logically Collective
2585db6f9c32SMark Adams 
2586db6f9c32SMark Adams   Input Parameters:
2587db6f9c32SMark Adams + pc   - the hypre context
2588feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2589db6f9c32SMark Adams 
2590db6f9c32SMark Adams   Options Database Key:
259167b8a455SSatish Balay . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2592db6f9c32SMark Adams 
2593db6f9c32SMark Adams   Level: intermediate
2594db6f9c32SMark Adams 
2595feefa0e1SJacob Faibussowitsch   Developer Notes:
2596f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2597db6f9c32SMark Adams 
2598562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2599db6f9c32SMark Adams @*/
2600d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2601d71ae5a4SJacob Faibussowitsch {
2602db6f9c32SMark Adams   PetscFunctionBegin;
2603db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2604cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
26053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2606db6f9c32SMark Adams }
2607db6f9c32SMark Adams 
2608cc4c1da9SBarry Smith /*@
2609f1580f4eSBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2610db6f9c32SMark Adams 
2611db6f9c32SMark Adams   Not Collective
2612db6f9c32SMark Adams 
2613db6f9c32SMark Adams   Input Parameter:
2614db6f9c32SMark Adams . pc - the multigrid context
2615db6f9c32SMark Adams 
2616db6f9c32SMark Adams   Output Parameter:
2617db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2618db6f9c32SMark Adams 
2619db6f9c32SMark Adams   Level: intermediate
2620db6f9c32SMark Adams 
2621a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinSetMatProductAlgorithm()`
2622db6f9c32SMark Adams @*/
2623d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2624d71ae5a4SJacob Faibussowitsch {
2625db6f9c32SMark Adams   PetscFunctionBegin;
2626db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2627cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
26283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2629db6f9c32SMark Adams }
2630db6f9c32SMark Adams 
263116d9e3a6SLisandro Dalcin /*MC
2632f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
263316d9e3a6SLisandro Dalcin 
263416d9e3a6SLisandro Dalcin    Options Database Keys:
2635e1ded407SBarry Smith +   -pc_hypre_type - One of `euclid`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
26367cbeddf0SNuno Nobre .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BoomerAMGSetNodal()`)
2637f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
26387cbeddf0SNuno Nobre -   Many others - run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
263916d9e3a6SLisandro Dalcin 
264016d9e3a6SLisandro Dalcin    Level: intermediate
264116d9e3a6SLisandro Dalcin 
264295452b02SPatrick Sanan    Notes:
2643e1ded407SBarry Smith     Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
264416d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
264549567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
264616d9e3a6SLisandro Dalcin 
2647e1ded407SBarry Smith           The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2648e1ded407SBarry Smith           (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2649e1ded407SBarry Smith           `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2650e1ded407SBarry Smith           (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2651e1ded407SBarry Smith           iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2652e1ded407SBarry Smith           and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2653e1ded407SBarry Smith           then AT MOST twenty V-cycles of boomeramg will be used.
265416d9e3a6SLisandro Dalcin 
2655e1ded407SBarry Smith            Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
26560f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2657e1ded407SBarry Smith            Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
265816d9e3a6SLisandro Dalcin 
2659f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2660e1ded407SBarry Smith           the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
26610b1a5bd9SEric Chamberland 
2662f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2663f1580f4eSBarry Smith 
2664e1ded407SBarry Smith           For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2665f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
266649567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2667f1580f4eSBarry Smith 
2668e1ded407SBarry 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
2669e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2670e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2671e1ded407SBarry Smith 
2672f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
26739e5bc791SBarry Smith 
2674ead8c081SBarry Smith    GPU Notes:
2675ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2676f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2677ead8c081SBarry Smith 
2678ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2679f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2680ead8c081SBarry Smith 
2681562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2682f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2683f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
268416d9e3a6SLisandro Dalcin M*/
268516d9e3a6SLisandro Dalcin 
2686d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2687d71ae5a4SJacob Faibussowitsch {
268816d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
268916d9e3a6SLisandro Dalcin 
269016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
26914dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
26922fa5cd67SKarl Rupp 
269316d9e3a6SLisandro Dalcin   pc->data                = jac;
26948695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
269516d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
269616d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
269716d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
269816d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
2699d7185485SAlex Lindsay   jac->hypre_type         = NULL;
270016d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
27019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
27029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
27039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
27049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
27059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
27069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
27079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2708be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
27099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
27109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
27119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
27126ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
27136ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
27149566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
27156ea7df73SStefano Zampini   #endif
27166ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
27179566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
27186ea7df73SStefano Zampini   #endif
27196ea7df73SStefano Zampini #endif
2720ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
27213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
272216d9e3a6SLisandro Dalcin }
2723ebc551c0SBarry Smith 
2724ebc551c0SBarry Smith typedef struct {
272568326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2726f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
27279e5bc791SBarry Smith 
27289e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
27294ddd07fcSJed Brown   PetscInt  its;
273073dcfd97SStefano Zampini   PetscReal tol;
27314ddd07fcSJed Brown   PetscInt  relax_type;
27324ddd07fcSJed Brown   PetscInt  rap_type;
27334ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
27344ddd07fcSJed Brown   PetscInt  max_levels;
27350be8cd64Sftrigaux   PetscInt  skip_relax;
27360be8cd64Sftrigaux   PetscBool print_statistics;
2737ebc551c0SBarry Smith } PC_PFMG;
2738ebc551c0SBarry Smith 
2739ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2740d71ae5a4SJacob Faibussowitsch {
2741f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2742ebc551c0SBarry Smith 
2743ebc551c0SBarry Smith   PetscFunctionBegin;
2744792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
27459566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27469566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
27473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2748ebc551c0SBarry Smith }
2749ebc551c0SBarry Smith 
27509e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
27519e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
27529e5bc791SBarry Smith 
2753ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2754d71ae5a4SJacob Faibussowitsch {
2755*9f196a02SMartin Diehl   PetscBool isascii;
2756f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2757ebc551c0SBarry Smith 
2758ebc551c0SBarry Smith   PetscFunctionBegin;
2759*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2760*9f196a02SMartin Diehl   if (isascii) {
27619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
276263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
27659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
276663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
276763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
27680be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
27699e5bc791SBarry Smith   }
27703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2771ebc551c0SBarry Smith }
2772ebc551c0SBarry Smith 
2773ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems PetscOptionsObject)
2774d71ae5a4SJacob Faibussowitsch {
2775f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2776ebc551c0SBarry Smith 
2777ebc551c0SBarry Smith   PetscFunctionBegin;
2778d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
27790be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
27809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2781792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
27829566063dSJacob 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));
2783792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
27849566063dSJacob 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));
2785792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
27869e5bc791SBarry Smith 
27879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2788792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
27893b46a515SGlenn Hammond 
27909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2791792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2792dd39110bSPierre 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));
2793792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2794dd39110bSPierre 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));
2795792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
27960be8cd64Sftrigaux   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));
27970be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2798d0609cedSBarry Smith   PetscOptionsHeadEnd();
27993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2800ebc551c0SBarry Smith }
2801ebc551c0SBarry Smith 
2802ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2803d71ae5a4SJacob Faibussowitsch {
2804f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2805d9ca1df4SBarry Smith   PetscScalar       *yy;
2806d9ca1df4SBarry Smith   const PetscScalar *xx;
28074ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
28082cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2809f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
2810f91d8e95SBarry Smith 
2811f91d8e95SBarry Smith   PetscFunctionBegin;
28129566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28139566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28142cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2815f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2816f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2817f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
28182cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
28192cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
28202cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
28212cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
28222cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
28232cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2824f91d8e95SBarry Smith 
2825f91d8e95SBarry Smith   /* copy x values over to hypre */
2826792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28279566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2828792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2830792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2831792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2832f91d8e95SBarry Smith 
2833f91d8e95SBarry Smith   /* copy solution values back to PETSc */
28349566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2835792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
28369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
28373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2838f91d8e95SBarry Smith }
2839f91d8e95SBarry Smith 
2840d71ae5a4SJacob 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)
2841d71ae5a4SJacob Faibussowitsch {
28429e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
28432cf14000SStefano Zampini   HYPRE_Int oits;
28449e5bc791SBarry Smith 
28459e5bc791SBarry Smith   PetscFunctionBegin;
28469566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2847792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2848792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
28499e5bc791SBarry Smith 
28509566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2851792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
28529e5bc791SBarry Smith   *outits = oits;
28539e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28549e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2855792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2856792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
28573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28589e5bc791SBarry Smith }
28599e5bc791SBarry Smith 
2860ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2861d71ae5a4SJacob Faibussowitsch {
28623a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
2863f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
2864ace3abfcSBarry Smith   PetscBool        flg;
28653a32d3dbSGlenn Hammond 
28663a32d3dbSGlenn Hammond   PetscFunctionBegin;
28679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
286828b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28693a32d3dbSGlenn Hammond 
28703a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2871792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2872792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
28730be8cd64Sftrigaux 
28740be8cd64Sftrigaux   // Print Hypre statistics about the solve process
28750be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
28760be8cd64Sftrigaux 
28770be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
28780be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
28790be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28800be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28810be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
28820be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
28830be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
28840be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
28850be8cd64Sftrigaux 
2886792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2887792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
28883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28893a32d3dbSGlenn Hammond }
28903a32d3dbSGlenn Hammond 
2891ebc551c0SBarry Smith /*MC
2892ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2893ebc551c0SBarry Smith 
2894f1580f4eSBarry Smith    Options Database Keys:
289567b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
289667b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
289767b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
289867b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
28999e5bc791SBarry 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
29000be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2901f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2902f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2903f1580f4eSBarry Smith 
2904f1580f4eSBarry Smith    Level: advanced
2905f91d8e95SBarry Smith 
290695452b02SPatrick Sanan    Notes:
290795452b02SPatrick Sanan    This is for CELL-centered descretizations
29089e5bc791SBarry Smith 
2909f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
29109e5bc791SBarry Smith 
2911f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2912f1580f4eSBarry Smith 
2913f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2914f1580f4eSBarry Smith 
2915f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2916f1580f4eSBarry Smith 
2917562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2918ebc551c0SBarry Smith M*/
2919ebc551c0SBarry Smith 
2920d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2921d71ae5a4SJacob Faibussowitsch {
2922ebc551c0SBarry Smith   PC_PFMG *ex;
2923ebc551c0SBarry Smith 
2924ebc551c0SBarry Smith   PetscFunctionBegin;
29259371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
292668326731SBarry Smith   pc->data = ex;
2927ebc551c0SBarry Smith 
29289e5bc791SBarry Smith   ex->its              = 1;
29299e5bc791SBarry Smith   ex->tol              = 1.e-8;
29309e5bc791SBarry Smith   ex->relax_type       = 1;
29319e5bc791SBarry Smith   ex->rap_type         = 0;
29329e5bc791SBarry Smith   ex->num_pre_relax    = 1;
29339e5bc791SBarry Smith   ex->num_post_relax   = 1;
29343b46a515SGlenn Hammond   ex->max_levels       = 0;
29350be8cd64Sftrigaux   ex->skip_relax       = 0;
29360be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
29379e5bc791SBarry Smith 
2938ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2939ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2940ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2941f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
29429e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
294368326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
29442fa5cd67SKarl Rupp 
29459566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2946ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2947792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
29483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2949ebc551c0SBarry Smith }
2950d851a50bSGlenn Hammond 
2951d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2952d851a50bSGlenn Hammond typedef struct {
2953d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2954d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2955d851a50bSGlenn Hammond 
2956d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
29574ddd07fcSJed Brown   PetscInt  its;
295873dcfd97SStefano Zampini   PetscReal tol;
29594ddd07fcSJed Brown   PetscInt  relax_type;
29604ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
2961d851a50bSGlenn Hammond } PC_SysPFMG;
2962d851a50bSGlenn Hammond 
2963ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2964d71ae5a4SJacob Faibussowitsch {
2965d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2966d851a50bSGlenn Hammond 
2967d851a50bSGlenn Hammond   PetscFunctionBegin;
2968792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
29699566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29709566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
29713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2972d851a50bSGlenn Hammond }
2973d851a50bSGlenn Hammond 
2974d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2975d851a50bSGlenn Hammond 
2976ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2977d71ae5a4SJacob Faibussowitsch {
2978*9f196a02SMartin Diehl   PetscBool   isascii;
2979d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2980d851a50bSGlenn Hammond 
2981d851a50bSGlenn Hammond   PetscFunctionBegin;
2982*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2983*9f196a02SMartin Diehl   if (isascii) {
29849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
298563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
29869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
29879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
298863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2989d851a50bSGlenn Hammond   }
29903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2991d851a50bSGlenn Hammond }
2992d851a50bSGlenn Hammond 
2993ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems PetscOptionsObject)
2994d71ae5a4SJacob Faibussowitsch {
2995d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2996ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2997d851a50bSGlenn Hammond 
2998d851a50bSGlenn Hammond   PetscFunctionBegin;
2999d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
30009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
300148a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
30029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
3003792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
30049566063dSJacob 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));
3005792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
30069566063dSJacob 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));
3007792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
3008d851a50bSGlenn Hammond 
30099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
3010792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
3011dd39110bSPierre 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));
3012792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
3013d0609cedSBarry Smith   PetscOptionsHeadEnd();
30143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3015d851a50bSGlenn Hammond }
3016d851a50bSGlenn Hammond 
3017ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
3018d71ae5a4SJacob Faibussowitsch {
3019d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
3020d9ca1df4SBarry Smith   PetscScalar       *yy;
3021d9ca1df4SBarry Smith   const PetscScalar *xx;
30224ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
30232cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
3024f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)pc->pmat->data;
30254ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
30264ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
30274ddd07fcSJed Brown   PetscInt           part     = 0;
30284ddd07fcSJed Brown   PetscInt           size;
30294ddd07fcSJed Brown   PetscInt           i;
3030d851a50bSGlenn Hammond 
3031d851a50bSGlenn Hammond   PetscFunctionBegin;
30329566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
30339566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
30342cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
3035d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
3036d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
3037d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
30382cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
30392cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
30402cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
30412cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
30422cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
30432cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
3044d851a50bSGlenn Hammond 
3045d851a50bSGlenn Hammond   size = 1;
30462fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
30472fa5cd67SKarl Rupp 
3048d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
3049d851a50bSGlenn Hammond   if (ordering) {
3050792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
30519566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3052792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
30539566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3054792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
3055792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
3056792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
3057d851a50bSGlenn Hammond 
3058d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30599566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3060792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
30619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
3062a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
3063d851a50bSGlenn Hammond     PetscScalar *z;
30644ddd07fcSJed Brown     PetscInt     j, k;
3065d851a50bSGlenn Hammond 
30669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
3067792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
30689566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3069d851a50bSGlenn Hammond 
3070d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
3071d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3072d851a50bSGlenn Hammond       k = i * nvars;
30732fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
3074d851a50bSGlenn Hammond     }
3075792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
30769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3077792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
3078792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
3079d851a50bSGlenn Hammond 
3080d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3082792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
3083d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
3084d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3085d851a50bSGlenn Hammond       k = i * nvars;
30862fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
3087d851a50bSGlenn Hammond     }
30889566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
30899566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
3090d851a50bSGlenn Hammond   }
30913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3092d851a50bSGlenn Hammond }
3093d851a50bSGlenn Hammond 
3094d71ae5a4SJacob 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)
3095d71ae5a4SJacob Faibussowitsch {
3096d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
30972cf14000SStefano Zampini   HYPRE_Int   oits;
3098d851a50bSGlenn Hammond 
3099d851a50bSGlenn Hammond   PetscFunctionBegin;
31009566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
3101792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
3102792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
31039566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
3104792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
3105d851a50bSGlenn Hammond   *outits = oits;
3106d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
3107d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
3108792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
3109792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
31103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3111d851a50bSGlenn Hammond }
3112d851a50bSGlenn Hammond 
3113ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
3114d71ae5a4SJacob Faibussowitsch {
3115d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
3116f4f49eeaSPierre Jolivet   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)pc->pmat->data;
3117ace3abfcSBarry Smith   PetscBool         flg;
3118d851a50bSGlenn Hammond 
3119d851a50bSGlenn Hammond   PetscFunctionBegin;
31209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
312128b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
3122d851a50bSGlenn Hammond 
3123d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
3124792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
3125792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
3126792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
3127792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
31283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3129d851a50bSGlenn Hammond }
3130d851a50bSGlenn Hammond 
3131d851a50bSGlenn Hammond /*MC
3132f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
3133d851a50bSGlenn Hammond 
3134d851a50bSGlenn Hammond    Level: advanced
3135d851a50bSGlenn Hammond 
3136f1580f4eSBarry Smith    Options Database Keys:
313767b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
313867b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
313967b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
314067b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
314167b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
3142d851a50bSGlenn Hammond 
314395452b02SPatrick Sanan    Notes:
3144f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
3145f1580f4eSBarry Smith 
3146f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
3147f1580f4eSBarry Smith 
314895452b02SPatrick Sanan    This is for CELL-centered descretizations
3149d851a50bSGlenn Hammond 
3150f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
3151d851a50bSGlenn Hammond 
3152f1580f4eSBarry 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`.
3153f1580f4eSBarry Smith 
3154562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
3155d851a50bSGlenn Hammond M*/
3156d851a50bSGlenn Hammond 
3157d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
3158d71ae5a4SJacob Faibussowitsch {
3159d851a50bSGlenn Hammond   PC_SysPFMG *ex;
3160d851a50bSGlenn Hammond 
3161d851a50bSGlenn Hammond   PetscFunctionBegin;
31629371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
3163d851a50bSGlenn Hammond   pc->data = ex;
3164d851a50bSGlenn Hammond 
3165d851a50bSGlenn Hammond   ex->its            = 1;
3166d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
3167d851a50bSGlenn Hammond   ex->relax_type     = 1;
3168d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
3169d851a50bSGlenn Hammond   ex->num_post_relax = 1;
3170d851a50bSGlenn Hammond 
3171d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
3172d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
3173d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
3174d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
3175d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
3176d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
31772fa5cd67SKarl Rupp 
31789566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3179ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3180792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
31813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3182d851a50bSGlenn Hammond }
31831c188c59Sftrigaux 
3184f1580f4eSBarry Smith /* PC SMG */
31851c188c59Sftrigaux typedef struct {
31861c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
31871c188c59Sftrigaux   HYPRE_StructSolver hsolver;
31881c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
318973dcfd97SStefano Zampini   PetscReal          tol;
31901c188c59Sftrigaux   PetscBool          print_statistics;
31911c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
31921c188c59Sftrigaux } PC_SMG;
31931c188c59Sftrigaux 
3194ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
3195d71ae5a4SJacob Faibussowitsch {
31961c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
31971c188c59Sftrigaux 
31981c188c59Sftrigaux   PetscFunctionBegin;
31991c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
32001c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
32011c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
32023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32031c188c59Sftrigaux }
32041c188c59Sftrigaux 
3205ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
3206d71ae5a4SJacob Faibussowitsch {
3207*9f196a02SMartin Diehl   PetscBool isascii;
32081c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
32091c188c59Sftrigaux 
32101c188c59Sftrigaux   PetscFunctionBegin;
3211*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
3212*9f196a02SMartin Diehl   if (isascii) {
32131c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
32141c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
32151c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
32161c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
32171c188c59Sftrigaux   }
32183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32191c188c59Sftrigaux }
32201c188c59Sftrigaux 
3221ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems PetscOptionsObject)
3222d71ae5a4SJacob Faibussowitsch {
32231c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
32241c188c59Sftrigaux 
32251c188c59Sftrigaux   PetscFunctionBegin;
32261c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
32271c188c59Sftrigaux 
32281c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
32291c188c59Sftrigaux   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));
32301c188c59Sftrigaux   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));
32311c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
32321c188c59Sftrigaux 
32331c188c59Sftrigaux   PetscOptionsHeadEnd();
32343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32351c188c59Sftrigaux }
32361c188c59Sftrigaux 
3237ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
3238d71ae5a4SJacob Faibussowitsch {
32391c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
32401c188c59Sftrigaux   PetscScalar       *yy;
32411c188c59Sftrigaux   const PetscScalar *xx;
32421c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
32431c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
3244f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
32451c188c59Sftrigaux 
32461c188c59Sftrigaux   PetscFunctionBegin;
32471c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32481c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
32491c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
32501c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
32511c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
32521c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
32531c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
32541c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
32551c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
32561c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
32571c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
32581c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
32591c188c59Sftrigaux 
32601c188c59Sftrigaux   /* copy x values over to hypre */
32611c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
32621c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
32631c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
32641c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
32651c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
32661c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
32671c188c59Sftrigaux 
32681c188c59Sftrigaux   /* copy solution values back to PETSc */
32691c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
32701c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
32711c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
32723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32731c188c59Sftrigaux }
32741c188c59Sftrigaux 
3275d71ae5a4SJacob 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)
3276d71ae5a4SJacob Faibussowitsch {
32771c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
32781c188c59Sftrigaux   HYPRE_Int oits;
32791c188c59Sftrigaux 
32801c188c59Sftrigaux   PetscFunctionBegin;
32811c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32821c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
32831c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
32841c188c59Sftrigaux 
32851c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
32861c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
32871c188c59Sftrigaux   *outits = oits;
32881c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
32891c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
32901c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
32911c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
32923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32931c188c59Sftrigaux }
32941c188c59Sftrigaux 
3295ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
3296d71ae5a4SJacob Faibussowitsch {
32971c188c59Sftrigaux   PetscInt         i, dim;
32981c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
3299f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
33001c188c59Sftrigaux   PetscBool        flg;
33011c188c59Sftrigaux   DMBoundaryType   p[3];
33021c188c59Sftrigaux   PetscInt         M[3];
33031c188c59Sftrigaux 
33041c188c59Sftrigaux   PetscFunctionBegin;
33051c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
33061c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
33071c188c59Sftrigaux 
33081c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
33091c188c59Sftrigaux   // Check if power of 2 in periodic directions
33101c188c59Sftrigaux   for (i = 0; i < dim; i++) {
33111c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
33121c188c59Sftrigaux       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "With SMG, the number of points in a periodic direction must be a power of 2, but is here %" PetscInt_FMT ".", M[i]);
33131c188c59Sftrigaux     }
33141c188c59Sftrigaux   }
33151c188c59Sftrigaux 
33161c188c59Sftrigaux   /* create the hypre solver object and set its information */
331757508eceSPierre Jolivet   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
33181c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
33191c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
33201c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
33211c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
33221c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
33231c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
33241c188c59Sftrigaux 
33251c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
33261c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
33273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33281c188c59Sftrigaux }
33291c188c59Sftrigaux 
33301c188c59Sftrigaux /*MC
33315cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
33321c188c59Sftrigaux 
33331c188c59Sftrigaux    Level: advanced
33341c188c59Sftrigaux 
3335f1580f4eSBarry Smith    Options Database Keys:
33365cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
33375cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
33385cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
33395cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
33401c188c59Sftrigaux 
33411c188c59Sftrigaux    Notes:
33421c188c59Sftrigaux    This is for CELL-centered descretizations
33431c188c59Sftrigaux 
33445cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
33451c188c59Sftrigaux 
3346f1580f4eSBarry 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`.
3347f1580f4eSBarry Smith 
3348f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3349f1580f4eSBarry Smith 
3350f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
33511c188c59Sftrigaux M*/
33521c188c59Sftrigaux 
3353d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3354d71ae5a4SJacob Faibussowitsch {
33551c188c59Sftrigaux   PC_SMG *ex;
33561c188c59Sftrigaux 
33571c188c59Sftrigaux   PetscFunctionBegin;
33589371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
33591c188c59Sftrigaux   pc->data = ex;
33601c188c59Sftrigaux 
33611c188c59Sftrigaux   ex->its            = 1;
33621c188c59Sftrigaux   ex->tol            = 1.e-8;
33631c188c59Sftrigaux   ex->num_pre_relax  = 1;
33641c188c59Sftrigaux   ex->num_post_relax = 1;
33651c188c59Sftrigaux 
33661c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
33671c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
33681c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
33691c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
33701c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
33711c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
33721c188c59Sftrigaux 
33731c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3374ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
33751c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
33763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33771c188c59Sftrigaux }
3378