xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 47c84c5acc69ca2c78267fc7dfb4d7203bd055c8)
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 */
85abf5c9d9SBarry Smith   PetscObjectParameterDeclare(PetscBool3, 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 */
PCGetCoarseOperators_BoomerAMG(PC pc,PetscInt * nlevels,Mat * operators[])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 */
PCGetInterpolations_BoomerAMG(PC pc,PetscInt * nlevels,Mat * interpolations[])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 */
PCHYPREGetCFMarkers_BoomerAMG(PC pc,PetscInt * n_per_level[],PetscBT * CFMarkers[])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 */
PCHYPREResetNearNullSpace_Private(PC pc)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"};
PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc,const char name[])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 
263d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
264d7185485SAlex Lindsay   PetscFunctionBegin;
265abf5c9d9SBarry Smith   jac->spgemm_type = name;
266d7185485SAlex Lindsay   PetscFunctionReturn(PETSC_SUCCESS);
267d7185485SAlex Lindsay #endif
268d7185485SAlex Lindsay }
269d7185485SAlex Lindsay 
PCSetUp_HYPRE(PC pc)270d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
271d71ae5a4SJacob Faibussowitsch {
27216d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
27349a781f5SStefano Zampini   Mat_HYPRE         *hjac;
27416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
27516d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
27649a781f5SStefano Zampini   PetscBool          ishypre;
27716d9e3a6SLisandro Dalcin 
27816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2790df1829cSStefano Zampini   /* default type is boomerAMG */
28048a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2815f5c5b43SBarry Smith 
2820df1829cSStefano Zampini   /* get hypre matrix */
2830df1829cSStefano Zampini   if (pc->flag == DIFFERENT_NONZERO_PATTERN) PetscCall(MatDestroy(&jac->hpmat));
2849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
28549a781f5SStefano Zampini   if (!ishypre) {
286e6519f9fSJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) && PETSC_PKG_HYPRE_VERSION_LE(2, 30, 0)
2870df1829cSStefano Zampini     /* Temporary fix since we do not support MAT_REUSE_MATRIX with HYPRE device */
2880df1829cSStefano Zampini     PetscBool iscuda, iship, iskokkos;
2890df1829cSStefano Zampini 
2900df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
2910df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
2920df1829cSStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)pc->pmat, &iskokkos, MATSEQAIJKOKKOS, MATMPIAIJKOKKOS, ""));
2930df1829cSStefano Zampini     if (iscuda || iship || iskokkos) PetscCall(MatDestroy(&jac->hpmat));
2940df1829cSStefano Zampini #endif
2950df1829cSStefano Zampini     PetscCall(MatConvert(pc->pmat, MATHYPRE, jac->hpmat ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &jac->hpmat));
29649a781f5SStefano Zampini   } else {
2979566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
29949a781f5SStefano Zampini     jac->hpmat = pc->pmat;
30016d9e3a6SLisandro Dalcin   }
3010df1829cSStefano Zampini 
3026ea7df73SStefano Zampini   /* allow debug */
3039566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
304f4f49eeaSPierre Jolivet   hjac = (Mat_HYPRE *)jac->hpmat->data;
3055f5c5b43SBarry Smith 
30616d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
30716d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
3085272c319SBarry Smith     MatNullSpace mnull;
3095272c319SBarry Smith     PetscBool    has_const;
31049a781f5SStefano Zampini     PetscInt     bs, nvec, i;
311d7185485SAlex Lindsay     PetscMemType memtype;
3125272c319SBarry Smith     const Vec   *vecs;
3135272c319SBarry Smith 
314d7185485SAlex Lindsay     PetscCall(MatGetCurrentMemType(jac->hpmat, &memtype));
315d7185485SAlex Lindsay     if (PetscMemTypeDevice(memtype)) {
316d7185485SAlex Lindsay       /* GPU defaults
317d7185485SAlex Lindsay          From https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
318d7185485SAlex Lindsay          and /src/parcsr_ls/par_amg.c
319d7185485SAlex Lindsay          First handle options which users have interfaces for changing */
320d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, coarsentype, 8);
321d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxorder, 0);
322d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, interptype, 6);
323d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[0], 18);
324d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[1], 18);
325d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
326d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, spgemm_type, HYPRESpgemmTypes[0]);
327d7185485SAlex Lindsay #endif
328d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
329abf5c9d9SBarry Smith       PetscObjectParameterSetDefault(jac, keeptranspose, PETSC_BOOL3_TRUE);
330d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, mod_rap2, 1);
331d7185485SAlex Lindsay #endif
332d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, agg_interptype, 7);
333d7185485SAlex Lindsay     } else {
334d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, coarsentype, 6);
335d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxorder, 1);
336d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, interptype, 0);
337d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[0], 6);
338d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, relaxtype[1], 6); /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
339d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
340d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, spgemm_type, "hypre");
341d7185485SAlex Lindsay #endif
342d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
343abf5c9d9SBarry Smith       PetscObjectParameterSetDefault(jac, keeptranspose, PETSC_BOOL3_FALSE);
344d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, mod_rap2, 0);
345d7185485SAlex Lindsay #endif
346d7185485SAlex Lindsay       PetscObjectParameterSetDefault(jac, agg_interptype, 4);
347d7185485SAlex Lindsay     }
348f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleType(jac->hsolver, (HYPRE_Int)jac->cycletype));
349f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMaxLevels(jac->hsolver, (HYPRE_Int)jac->maxlevels));
350f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMaxIter(jac->hsolver, (HYPRE_Int)jac->maxiter));
351a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetTol(jac->hsolver, jac->tol));
352a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetTruncFactor(jac->hsolver, jac->truncfactor));
353a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver, jac->strongthreshold));
354a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver, jac->maxrowsum));
355f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMeasureType(jac->hsolver, (HYPRE_Int)jac->measuretype));
356f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetAggNumLevels(jac->hsolver, (HYPRE_Int)jac->agg_nl));
357f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetPMaxElmts(jac->hsolver, (HYPRE_Int)jac->pmax));
358f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetNumPaths(jac->hsolver, (HYPRE_Int)jac->agg_num_paths));
359f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver, (HYPRE_Int)jac->gridsweeps[0], 1));
360f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver, (HYPRE_Int)jac->gridsweeps[1], 2));
361f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver, (HYPRE_Int)jac->gridsweeps[2], 3));
362f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMaxCoarseSize(jac->hsolver, (HYPRE_Int)jac->maxc));
363f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMinCoarseSize(jac->hsolver, (HYPRE_Int)jac->minc));
364f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCoarsenType(jac->hsolver, (HYPRE_Int)jac->coarsentype));
365f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, (HYPRE_Int)jac->relaxorder));
366f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetInterpType(jac->hsolver, (HYPRE_Int)jac->interptype));
367f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetRelaxType(jac->hsolver, (HYPRE_Int)jac->relaxtype[0]));
368f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, (HYPRE_Int)jac->relaxtype[0], 1));
369f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, (HYPRE_Int)jac->relaxtype[1], 2));
370f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, (HYPRE_Int)jac->relaxtype[2], 3));
371d7185485SAlex Lindsay     /* GPU */
372d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
373abf5c9d9SBarry Smith     {
374abf5c9d9SBarry Smith       PetscBool flg_cusparse, flg_hypre;
375abf5c9d9SBarry Smith 
376abf5c9d9SBarry Smith       PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flg_cusparse));
377abf5c9d9SBarry Smith       PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flg_hypre));
378a333fa2bSZach Atkins       if (flg_cusparse) PetscCallHYPRE(HYPRE_SetSpGemmUseCusparse(1));
379a333fa2bSZach Atkins       else if (flg_hypre) PetscCallHYPRE(HYPRE_SetSpGemmUseCusparse(0));
380abf5c9d9SBarry Smith       else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", jac->spgemm_type);
381abf5c9d9SBarry Smith     }
382d7185485SAlex Lindsay #endif
383d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
384a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetKeepTranspose(jac->hsolver, jac->keeptranspose == PETSC_BOOL3_TRUE ? 1 : 0));
385f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetRAP2(jac->hsolver, (HYPRE_Int)jac->rap2));
386f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetModuleRAP2(jac->hsolver, (HYPRE_Int)jac->mod_rap2));
387d7185485SAlex Lindsay #endif
388f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetAggInterpType(jac->hsolver, (HYPRE_Int)jac->agg_interptype));
389d7185485SAlex Lindsay 
390d7185485SAlex Lindsay     /* AIR */
391d7185485SAlex Lindsay #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
392f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetRestriction(jac->hsolver, (HYPRE_Int)jac->Rtype));
393a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetStrongThresholdR(jac->hsolver, jac->Rstrongthreshold));
394a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetFilterThresholdR(jac->hsolver, jac->Rfilterthreshold));
395a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetADropTol(jac->hsolver, jac->Adroptol));
396f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetADropType(jac->hsolver, (HYPRE_Int)jac->Adroptype));
397d7185485SAlex Lindsay #endif
398d7185485SAlex Lindsay 
3999566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
400f2f41e48SZach Atkins     if (bs > 1) PetscCallHYPRE(HYPRE_BoomerAMGSetNumFunctions(jac->hsolver, (HYPRE_Int)bs));
4019566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
4025272c319SBarry Smith     if (mnull) {
4039566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4049566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
4059566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
4069566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
4075272c319SBarry Smith       for (i = 0; i < nvec; i++) {
4089566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
4099566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
410a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->hmnull[i]->ij, (void **)&jac->phmnull[i]));
4115272c319SBarry Smith       }
4125272c319SBarry Smith       if (has_const) {
4139566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
4149566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
4159566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
4169566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
4179566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
418a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]));
4195272c319SBarry Smith         nvec++;
4205272c319SBarry Smith       }
421f2f41e48SZach Atkins       PetscCallHYPRE(HYPRE_BoomerAMGSetInterpVectors(jac->hsolver, (HYPRE_Int)nvec, jac->phmnull));
4225272c319SBarry Smith       jac->n_hmnull = nvec;
4235272c319SBarry Smith     }
4244cb006feSStefano Zampini   }
425863406b8SStefano Zampini 
4264cb006feSStefano Zampini   /* special case for AMS */
4274cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
4285ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
4295ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
430966bd95aSPierre Jolivet     PetscCheck(jac->coords[0] || jac->constants[0] || jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]), PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the edge constant vectors via PCHYPRESetEdgeConstantVectors() or the interpolation matrix via PCHYPRESetInterpolations()");
431f2f41e48SZach Atkins     if (jac->dim) PetscCallHYPRE(HYPRE_AMSSetDimension(jac->hsolver, (HYPRE_Int)jac->dim));
4325ac14e1cSStefano Zampini     if (jac->constants[0]) {
4335ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
434a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->constants[0]->ij, (void **)(&ozz)));
435a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->constants[1]->ij, (void **)(&zoz)));
436a333fa2bSZach Atkins       if (jac->constants[2]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->constants[2]->ij, (void **)(&zzo)));
437a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_AMSSetEdgeConstantVectors(jac->hsolver, ozz, zoz, zzo));
4385ac14e1cSStefano Zampini     }
4395ac14e1cSStefano Zampini     if (jac->coords[0]) {
4405ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
4415ac14e1cSStefano Zampini       coords[0] = NULL;
4425ac14e1cSStefano Zampini       coords[1] = NULL;
4435ac14e1cSStefano Zampini       coords[2] = NULL;
444a333fa2bSZach Atkins       if (jac->coords[0]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->coords[0]->ij, (void **)(&coords[0])));
445a333fa2bSZach Atkins       if (jac->coords[1]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->coords[1]->ij, (void **)(&coords[1])));
446a333fa2bSZach Atkins       if (jac->coords[2]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->coords[2]->ij, (void **)(&coords[2])));
447a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_AMSSetCoordinateVectors(jac->hsolver, coords[0], coords[1], coords[2]));
4485ac14e1cSStefano Zampini     }
4495f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
450f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
451a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&parcsr)));
452a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_AMSSetDiscreteGradient(jac->hsolver, parcsr));
4535ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
454f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->alpha_Poisson->data;
455a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&parcsr)));
456a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_AMSSetAlphaPoissonMatrix(jac->hsolver, parcsr));
4575ac14e1cSStefano Zampini     }
4585ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
459a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_AMSSetBetaPoissonMatrix(jac->hsolver, NULL));
4605ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
461f4f49eeaSPierre Jolivet       hm = (Mat_HYPRE *)jac->beta_Poisson->data;
462a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&parcsr)));
463a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_AMSSetBetaPoissonMatrix(jac->hsolver, parcsr));
464be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
465be14dc20SKerry Key       if (jac->interior) {
466be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
467a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->interior->ij, (void **)(&interior)));
468a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_AMSSetInteriorNodes(jac->hsolver, interior));
469be14dc20SKerry Key       } else {
470be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
471be14dc20SKerry Key       }
4725ac14e1cSStefano Zampini     }
4736bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
4746bf688a0SCe Qin       PetscInt           i;
4756bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
4766bf688a0SCe Qin       if (jac->ND_PiFull) {
477f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
478a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&nd_parcsrfull)));
4796bf688a0SCe Qin       } else {
4806bf688a0SCe Qin         nd_parcsrfull = NULL;
4816bf688a0SCe Qin       }
4826bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4836bf688a0SCe Qin         if (jac->ND_Pi[i]) {
484f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
485a333fa2bSZach Atkins           PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&nd_parcsr[i])));
4866bf688a0SCe Qin         } else {
4876bf688a0SCe Qin           nd_parcsr[i] = NULL;
4886bf688a0SCe Qin         }
4896bf688a0SCe Qin       }
490a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_AMSSetInterpolations(jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]));
4916bf688a0SCe Qin     }
4924cb006feSStefano Zampini   }
493863406b8SStefano Zampini   /* special case for ADS */
494863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
4955ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
4965ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
4976bf688a0SCe 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])))) {
4986bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
4999371c9d4SSatish 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");
5005f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
5015f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
5025ac14e1cSStefano Zampini     if (jac->coords[0]) {
5035ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
5045ac14e1cSStefano Zampini       coords[0] = NULL;
5055ac14e1cSStefano Zampini       coords[1] = NULL;
5065ac14e1cSStefano Zampini       coords[2] = NULL;
507a333fa2bSZach Atkins       if (jac->coords[0]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->coords[0]->ij, (void **)(&coords[0])));
508a333fa2bSZach Atkins       if (jac->coords[1]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->coords[1]->ij, (void **)(&coords[1])));
509a333fa2bSZach Atkins       if (jac->coords[2]) PetscCallHYPRE(HYPRE_IJVectorGetObject(jac->coords[2]->ij, (void **)(&coords[2])));
510a333fa2bSZach Atkins       PetscCallHYPRE(HYPRE_ADSSetCoordinateVectors(jac->hsolver, coords[0], coords[1], coords[2]));
5115ac14e1cSStefano Zampini     }
512f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->G->data;
513a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&parcsr)));
514a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ADSSetDiscreteGradient(jac->hsolver, parcsr));
515f4f49eeaSPierre Jolivet     hm = (Mat_HYPRE *)jac->C->data;
516a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&parcsr)));
517a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ADSSetDiscreteCurl(jac->hsolver, parcsr));
5186bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
5196bf688a0SCe Qin       PetscInt           i;
5206bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
5216bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
5226bf688a0SCe Qin       if (jac->RT_PiFull) {
523f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->RT_PiFull->data;
524a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&rt_parcsrfull)));
5256bf688a0SCe Qin       } else {
5266bf688a0SCe Qin         rt_parcsrfull = NULL;
5276bf688a0SCe Qin       }
5286bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
5296bf688a0SCe Qin         if (jac->RT_Pi[i]) {
530f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->RT_Pi[i]->data;
531a333fa2bSZach Atkins           PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&rt_parcsr[i])));
5326bf688a0SCe Qin         } else {
5336bf688a0SCe Qin           rt_parcsr[i] = NULL;
5346bf688a0SCe Qin         }
5356bf688a0SCe Qin       }
5366bf688a0SCe Qin       if (jac->ND_PiFull) {
537f4f49eeaSPierre Jolivet         hm = (Mat_HYPRE *)jac->ND_PiFull->data;
538a333fa2bSZach Atkins         PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&nd_parcsrfull)));
5396bf688a0SCe Qin       } else {
5406bf688a0SCe Qin         nd_parcsrfull = NULL;
5416bf688a0SCe Qin       }
5426bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
5436bf688a0SCe Qin         if (jac->ND_Pi[i]) {
544f4f49eeaSPierre Jolivet           hm = (Mat_HYPRE *)jac->ND_Pi[i]->data;
545a333fa2bSZach Atkins           PetscCallHYPRE(HYPRE_IJMatrixGetObject(hm->ij, (void **)(&nd_parcsr[i])));
5466bf688a0SCe Qin         } else {
5476bf688a0SCe Qin           nd_parcsr[i] = NULL;
5486bf688a0SCe Qin         }
5496bf688a0SCe Qin       }
550a333fa2bSZach Atkins       PetscCallHYPRE(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]));
5516bf688a0SCe Qin     }
552863406b8SStefano Zampini   }
553a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJMatrixGetObject(hjac->ij, (void **)&hmat));
554a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJVectorGetObject(hjac->b->ij, (void **)&bv));
555a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJVectorGetObject(hjac->x->ij, (void **)&xv));
55697c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
557325a1edfSZach Atkins   PetscCallHYPRE((*jac->setup)(jac->hsolver, hmat, bv, xv));
55897c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
5593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56016d9e3a6SLisandro Dalcin }
56116d9e3a6SLisandro Dalcin 
PCApply_HYPRE(PC pc,Vec b,Vec x)562d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
563d71ae5a4SJacob Faibussowitsch {
56416d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
565f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
56616d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
56716d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
56816d9e3a6SLisandro Dalcin 
56916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5709566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
5719566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
5729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
5739566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
5749566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
575a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJMatrixGetObject(hjac->ij, (void **)&hmat));
576a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJVectorGetObject(hjac->b->ij, (void **)&jbv));
577a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJVectorGetObject(hjac->x->ij, (void **)&jxv));
5789371c9d4SSatish Balay   PetscStackCallExternalVoid(
5799371c9d4SSatish Balay     "Hypre solve", do {
5805f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
5815f80ce2aSJacob Faibussowitsch       if (hierr) {
5825f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
58385245615SPierre Jolivet         HYPRE_ClearAllErrors();
5845f80ce2aSJacob Faibussowitsch       }
5855f80ce2aSJacob Faibussowitsch     } while (0));
58616d9e3a6SLisandro Dalcin 
587a333fa2bSZach Atkins   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallHYPRE(HYPRE_AMSProjectOutGradients(jac->hsolver, jxv));
5889566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
5899566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
5903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59116d9e3a6SLisandro Dalcin }
59216d9e3a6SLisandro Dalcin 
PCMatApply_HYPRE_BoomerAMG(PC pc,Mat B,Mat X)59385245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
59485245615SPierre Jolivet {
59585245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
596f4f49eeaSPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)jac->hpmat->data;
59785245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
59885245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
59985245615SPierre Jolivet   const PetscScalar  *b;
60085245615SPierre Jolivet   PetscScalar        *x;
60185245615SPierre Jolivet   PetscInt            m, N, lda;
60285245615SPierre Jolivet   hypre_Vector       *x_local;
60385245615SPierre Jolivet   PetscMemType        type;
60485245615SPierre Jolivet 
60585245615SPierre Jolivet   PetscFunctionBegin;
60685245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
607a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJMatrixGetObject(hjac->ij, (void **)&par_matrix));
60885245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
60985245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
610f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_ParMultiVectorCreate(hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), (HYPRE_Int)N, &hb));
611f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_ParMultiVectorCreate(hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), (HYPRE_Int)N, &hx));
61285245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
61385245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
61485245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
61585245615SPierre 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);
61685245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
61785245615SPierre 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);
61885245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
619a333fa2bSZach Atkins   PetscCallHYPRE(hypre_SeqVectorSetDataOwner(x_local, 0));
62085245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
62185245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
62285245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
623a333fa2bSZach Atkins   PetscCallHYPRE(hypre_SeqVectorSetDataOwner(x_local, 0));
62485245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
625a333fa2bSZach Atkins   PetscCallHYPRE(hypre_ParVectorInitialize_v2(hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE));
626a333fa2bSZach Atkins   PetscCallHYPRE(hypre_ParVectorInitialize_v2(hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE));
62785245615SPierre Jolivet   PetscStackCallExternalVoid(
62885245615SPierre Jolivet     "Hypre solve", do {
62985245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
63085245615SPierre Jolivet       if (hierr) {
63185245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
63285245615SPierre Jolivet         HYPRE_ClearAllErrors();
63385245615SPierre Jolivet       }
63485245615SPierre Jolivet     } while (0));
635a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_ParVectorDestroy(hb));
636a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_ParVectorDestroy(hx));
63785245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
63885245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
63985245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
64085245615SPierre Jolivet }
64185245615SPierre Jolivet 
PCReset_HYPRE(PC pc)642d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
643d71ae5a4SJacob Faibussowitsch {
6448695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6458695de01SBarry Smith 
6468695de01SBarry Smith   PetscFunctionBegin;
6479566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
6489566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
6499566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
6509566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
6519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
6529566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
6539566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
6549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
6559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
6569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
6579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
6589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
6599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
6609566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
6619566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
6629566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
6639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
6649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
6659566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
666be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
6679566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
6685ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
669be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
6705ac14e1cSStefano Zampini   jac->dim                   = 0;
6713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6728695de01SBarry Smith }
6738695de01SBarry Smith 
PCDestroy_HYPRE(PC pc)674d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
675d71ae5a4SJacob Faibussowitsch {
67616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
67716d9e3a6SLisandro Dalcin 
67816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6799566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
680325a1edfSZach Atkins   if (jac->destroy) PetscCallHYPRE((*jac->destroy)(jac->hsolver));
6819566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
6829566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
6839566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
68416d9e3a6SLisandro Dalcin 
6859566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
6869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
6879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
6889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
6909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
6919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
6929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
6932e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
694be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
6959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
6969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
69742e5ec60SJeff-Hadley   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", NULL));
6989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
6999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
7002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
7013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70216d9e3a6SLisandro Dalcin }
70316d9e3a6SLisandro Dalcin 
PCSetFromOptions_HYPRE_Pilut(PC pc,PetscOptionItems PetscOptionsObject)704ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems PetscOptionsObject)
705d71ae5a4SJacob Faibussowitsch {
70616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
707ace3abfcSBarry Smith   PetscBool flag;
70816d9e3a6SLisandro Dalcin 
70916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
710d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
7119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
712f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParCSRPilutSetMaxIter(jac->hsolver, (HYPRE_Int)jac->maxiter));
7139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
714a333fa2bSZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParCSRPilutSetDropTolerance(jac->hsolver, jac->tol));
7159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
716f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParCSRPilutSetFactorRowSize(jac->hsolver, (HYPRE_Int)jac->factorrowsize));
717d0609cedSBarry Smith   PetscOptionsHeadEnd();
7183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71916d9e3a6SLisandro Dalcin }
72016d9e3a6SLisandro Dalcin 
PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)721d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
722d71ae5a4SJacob Faibussowitsch {
72316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7249f196a02SMartin Diehl   PetscBool isascii;
72516d9e3a6SLisandro Dalcin 
72616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
7279f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
7289f196a02SMartin Diehl   if (isascii) {
7299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
73016d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
73163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
73216d9e3a6SLisandro Dalcin     } else {
7339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
73416d9e3a6SLisandro Dalcin     }
73516d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
7369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
73716d9e3a6SLisandro Dalcin     } else {
7389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
73916d9e3a6SLisandro Dalcin     }
74016d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
74163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
74216d9e3a6SLisandro Dalcin     } else {
7439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
74416d9e3a6SLisandro Dalcin     }
74516d9e3a6SLisandro Dalcin   }
7463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74716d9e3a6SLisandro Dalcin }
74816d9e3a6SLisandro Dalcin 
7493c61a47dSLukas static const char *HYPREILUType[] = {
7503c61a47dSLukas   "Block-Jacobi-ILUk", "Block-Jacobi-ILUT", "", "", "", "", "", "", "", "", /* 0-9 */
7513c61a47dSLukas   "GMRES-ILUk",        "GMRES-ILUT",        "", "", "", "", "", "", "", "", /* 10-19 */
7523c61a47dSLukas   "NSH-ILUk",          "NSH-ILUT",          "", "", "", "", "", "", "", "", /* 20-29 */
7533c61a47dSLukas   "RAS-ILUk",          "RAS-ILUT",          "", "", "", "", "", "", "", "", /* 30-39 */
7543c61a47dSLukas   "ddPQ-GMRES-ILUk",   "ddPQ-GMRES-ILUT",   "", "", "", "", "", "", "", "", /* 40-49 */
7553c61a47dSLukas   "GMRES-ILU0"                                                              /* 50 */
7563c61a47dSLukas };
7573c61a47dSLukas 
7583c61a47dSLukas static const char *HYPREILUIterSetup[] = {"default", "async-in-place", "async-explicit", "sync-explicit", "semisync-explicit"};
7593c61a47dSLukas 
PCSetFromOptions_HYPRE_ILU(PC pc,PetscOptionItems PetscOptionsObject)760ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ILU(PC pc, PetscOptionItems PetscOptionsObject)
7613c61a47dSLukas {
7623c61a47dSLukas   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
7633c61a47dSLukas   PetscBool flg;
7643c61a47dSLukas   PetscInt  indx;
7653c61a47dSLukas   PetscReal tmpdbl;
7663c61a47dSLukas   PetscBool tmp_truth;
7673c61a47dSLukas 
7683c61a47dSLukas   PetscFunctionBegin;
7693c61a47dSLukas   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ILU Options");
7703c61a47dSLukas 
7713c61a47dSLukas   /* ILU: ILU Type */
7723c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
773f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetType(jac->hsolver, (HYPRE_Int)indx));
7743c61a47dSLukas 
7753c61a47dSLukas   /* ILU: ILU iterative setup type*/
7763c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_ilu_iterative_setup_type", "Set ILU iterative setup type", "None", HYPREILUIterSetup, PETSC_STATIC_ARRAY_LENGTH(HYPREILUIterSetup), HYPREILUIterSetup[0], &indx, &flg));
777f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetIterativeSetupType(jac->hsolver, (HYPRE_Int)indx));
7783c61a47dSLukas 
7793c61a47dSLukas   /* ILU: ILU iterative setup option*/
7803c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
781f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetIterativeSetupOption(jac->hsolver, (HYPRE_Int)indx));
7823c61a47dSLukas 
7833c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
7843c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
785f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetIterativeSetupMaxIter(jac->hsolver, (HYPRE_Int)indx));
7863c61a47dSLukas 
7873c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
7883c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
789a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetIterativeSetupTolerance(jac->hsolver, tmpdbl));
7903c61a47dSLukas 
7913c61a47dSLukas   /* ILU: ILU Print Level */
7923c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
793f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetPrintLevel(jac->hsolver, (HYPRE_Int)indx));
7943c61a47dSLukas 
7953c61a47dSLukas   /* ILU: Logging */
7963c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
797f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetLogging(jac->hsolver, (HYPRE_Int)indx));
7983c61a47dSLukas 
7993c61a47dSLukas   /* ILU: ILU Level */
8003c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
801f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetLevelOfFill(jac->hsolver, (HYPRE_Int)indx));
8023c61a47dSLukas 
8033c61a47dSLukas   /* ILU: ILU Max NNZ per row */
8043c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
805f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetMaxNnzPerRow(jac->hsolver, (HYPRE_Int)indx));
8063c61a47dSLukas 
8073c61a47dSLukas   /* ILU: tolerance */
8083c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_tol", "Tolerance for ILU", "None", 0, &tmpdbl, &flg));
809a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetTol(jac->hsolver, tmpdbl));
8103c61a47dSLukas 
8113c61a47dSLukas   /* ILU: maximum iteration count */
8123c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
813f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetMaxIter(jac->hsolver, (HYPRE_Int)indx));
8143c61a47dSLukas 
8153c61a47dSLukas   /* ILU: drop threshold */
8163c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_ilu_drop_threshold", "Drop threshold for ILU", "None", 0, &tmpdbl, &flg));
817a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetDropThreshold(jac->hsolver, tmpdbl));
8183c61a47dSLukas 
8193c61a47dSLukas   /* ILU: Triangular Solve */
8203c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
821a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetTriSolve(jac->hsolver, tmp_truth));
8223c61a47dSLukas 
8233c61a47dSLukas   /* ILU: Lower Jacobi iteration */
8243c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
825f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetLowerJacobiIters(jac->hsolver, (HYPRE_Int)indx));
8263c61a47dSLukas 
8273c61a47dSLukas   /* ILU: Upper Jacobi iteration */
8283c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
829f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetUpperJacobiIters(jac->hsolver, (HYPRE_Int)indx));
8303c61a47dSLukas 
8313c61a47dSLukas   /* ILU: local reordering */
8323c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
833a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_ILUSetLocalReordering(jac->hsolver, tmp_truth));
8343c61a47dSLukas 
8353c61a47dSLukas   PetscOptionsHeadEnd();
8363c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
8373c61a47dSLukas }
8383c61a47dSLukas 
PCView_HYPRE_ILU(PC pc,PetscViewer viewer)8393c61a47dSLukas static PetscErrorCode PCView_HYPRE_ILU(PC pc, PetscViewer viewer)
8403c61a47dSLukas {
8413c61a47dSLukas   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
8423c61a47dSLukas   hypre_ParILUData *ilu_data = (hypre_ParILUData *)jac->hsolver;
8439f196a02SMartin Diehl   PetscBool         isascii;
8443c61a47dSLukas   PetscInt          indx;
8453c61a47dSLukas   PetscReal         tmpdbl;
8463c61a47dSLukas   PetscReal        *tmpdbl3;
8473c61a47dSLukas 
8483c61a47dSLukas   PetscFunctionBegin;
8499f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
8509f196a02SMartin Diehl   if (isascii) {
8513c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ILU preconditioning\n"));
8523c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIluType", indx = hypre_ParILUDataIluType(ilu_data));
8533c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
8543c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLfil", indx = hypre_ParILUDataLfil(ilu_data));
8553c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
8563c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxIter", indx = hypre_ParILUDataMaxIter(ilu_data));
8573c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
8583c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataMaxRowNnz", indx = hypre_ParILUDataMaxRowNnz(ilu_data));
8593c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
8603c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTriSolve", indx = hypre_ParILUDataTriSolve(ilu_data));
8613c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
8623c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataTol", tmpdbl = hypre_ParILUDataTol(ilu_data));
8633c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", tmpdbl));
8643c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataDroptol", tmpdbl3 = hypre_ParILUDataDroptol(ilu_data));
8653c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e / %e / %e\n", tmpdbl3[0], tmpdbl3[1], tmpdbl3[2]));
8663c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataReorderingType", indx = hypre_ParILUDataReorderingType(ilu_data));
8673c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
8683c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLowerJacobiIters", indx = hypre_ParILUDataLowerJacobiIters(ilu_data));
8693c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
8703c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataUpperJacobiIters", indx = hypre_ParILUDataUpperJacobiIters(ilu_data));
8713c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
8723c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataPrintLevel", indx = hypre_ParILUDataPrintLevel(ilu_data));
8733c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
8743c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataLogging", indx = hypre_ParILUDataLogging(ilu_data));
8753c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
8763c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupType", indx = hypre_ParILUDataIterativeSetupType(ilu_data));
8773c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
8783c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupOption", indx = hypre_ParILUDataIterativeSetupOption(ilu_data));
8793c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
8803c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupMaxIter", indx = hypre_ParILUDataIterativeSetupMaxIter(ilu_data));
8813c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
8823c61a47dSLukas     PetscStackCallExternalVoid("hypre_ParILUDataIterativeSetupTolerance", tmpdbl = hypre_ParILUDataIterativeSetupTolerance(ilu_data));
8833c61a47dSLukas     PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", tmpdbl));
8843c61a47dSLukas   }
8853c61a47dSLukas   PetscFunctionReturn(PETSC_SUCCESS);
8863c61a47dSLukas }
8873c61a47dSLukas 
PCSetFromOptions_HYPRE_Euclid(PC pc,PetscOptionItems PetscOptionsObject)888ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems PetscOptionsObject)
889d71ae5a4SJacob Faibussowitsch {
890db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
8918bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
892db966c6cSHong Zhang 
893db966c6cSHong Zhang   PetscFunctionBegin;
894d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
8959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
896f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_EuclidSetLevel(jac->hsolver, (HYPRE_Int)jac->eu_level));
8978bf83915SBarry Smith 
8989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
8998bf83915SBarry Smith   if (flag) {
9008bf83915SBarry Smith     PetscMPIInt size;
9018bf83915SBarry Smith 
9029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
9037827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
904a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_EuclidSetILUT(jac->hsolver, jac->eu_droptolerance));
9058bf83915SBarry Smith   }
9068bf83915SBarry Smith 
9079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
9088bf83915SBarry Smith   if (flag) {
9098bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
910f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_EuclidSetBJ(jac->hsolver, (HYPRE_Int)jac->eu_bj));
9118bf83915SBarry Smith   }
912d0609cedSBarry Smith   PetscOptionsHeadEnd();
9133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
914db966c6cSHong Zhang }
915db966c6cSHong Zhang 
PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)916d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
917d71ae5a4SJacob Faibussowitsch {
918db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
9199f196a02SMartin Diehl   PetscBool isascii;
920db966c6cSHong Zhang 
921db966c6cSHong Zhang   PetscFunctionBegin;
9229f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
9239f196a02SMartin Diehl   if (isascii) {
9249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
925db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
92663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
927db966c6cSHong Zhang     } else {
9289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
929db966c6cSHong Zhang     }
9309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
93163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
932db966c6cSHong Zhang   }
9333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
934db966c6cSHong Zhang }
935db966c6cSHong Zhang 
PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x)936d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
937d71ae5a4SJacob Faibussowitsch {
93816d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
939f4f49eeaSPierre Jolivet   Mat_HYPRE         *hjac = (Mat_HYPRE *)jac->hpmat->data;
94016d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
94116d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
94216d9e3a6SLisandro Dalcin 
94316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9449566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
9459566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
946af221044SPierre Jolivet   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
947af221044SPierre Jolivet   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
94816d9e3a6SLisandro Dalcin 
949a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJMatrixGetObject(hjac->ij, (void **)&hmat));
950a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJVectorGetObject(hjac->b->ij, (void **)&jbv));
951a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_IJVectorGetObject(hjac->x->ij, (void **)&jxv));
95216d9e3a6SLisandro Dalcin 
9539371c9d4SSatish Balay   PetscStackCallExternalVoid(
9549371c9d4SSatish Balay     "Hypre Transpose solve", do {
9555f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
9565f80ce2aSJacob Faibussowitsch       if (hierr) {
95716d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
9585f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
95985245615SPierre Jolivet         HYPRE_ClearAllErrors();
9605f80ce2aSJacob Faibussowitsch       }
9615f80ce2aSJacob Faibussowitsch     } while (0));
96216d9e3a6SLisandro Dalcin 
9639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
9649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
9653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
96616d9e3a6SLisandro Dalcin }
96716d9e3a6SLisandro Dalcin 
PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc,const char * spgemm[])968d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
969d71ae5a4SJacob Faibussowitsch {
970db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
971db6f9c32SMark Adams 
972db6f9c32SMark Adams   PetscFunctionBegin;
973db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
974db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
975db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
976db6f9c32SMark Adams #endif
9773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
978db6f9c32SMark Adams }
979db6f9c32SMark Adams 
98016d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
9810f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
98216d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
98365de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
9843c61a47dSLukas static const char *HYPREBoomerAMGSmoothType[] = {"ILU", "Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
9859371c9d4SSatish 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"};
9869371c9d4SSatish 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"};
987d7185485SAlex Lindsay 
PCSetFromOptions_HYPRE_BoomerAMG(PC pc,PetscOptionItems PetscOptionsObject)988ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems PetscOptionsObject)
989d71ae5a4SJacob Faibussowitsch {
99016d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
99122e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
992ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
99373dcfd97SStefano Zampini   PetscReal   tmpdbl, twodbl[2];
994589dcaf0SStefano Zampini   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
99516d9e3a6SLisandro Dalcin 
99616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
997d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
9989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
99916d9e3a6SLisandro Dalcin   if (flg) {
10004336a9eeSBarry Smith     jac->cycletype = indx + 1;
1001f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleType(jac->hsolver, (HYPRE_Int)jac->cycletype));
100216d9e3a6SLisandro Dalcin   }
100352ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg, 2));
1004f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetMaxLevels(jac->hsolver, (HYPRE_Int)jac->maxlevels));
100552ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg, 1));
1006f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetMaxIter(jac->hsolver, (HYPRE_Int)jac->maxiter));
100752ce0ab5SPierre 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));
1008a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetTol(jac->hsolver, jac->tol));
100922e51d31SStefano Zampini   bs = 1;
101048a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
10119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
1012f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetNumFunctions(jac->hsolver, (HYPRE_Int)bs));
101316d9e3a6SLisandro Dalcin 
101452ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg, 0.0));
1015a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetTruncFactor(jac->hsolver, jac->truncfactor));
101616d9e3a6SLisandro Dalcin 
101752ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg, 0));
1018f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetPMaxElmts(jac->hsolver, (HYPRE_Int)jac->pmax));
10190f1074feSSatish Balay 
10209566063dSJacob 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));
1021f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetAggNumLevels(jac->hsolver, (HYPRE_Int)jac->agg_nl));
10220f1074feSSatish Balay 
102352ce0ab5SPierre 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));
1024f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetNumPaths(jac->hsolver, (HYPRE_Int)jac->agg_num_paths));
10250f1074feSSatish Balay 
102652ce0ab5SPierre Jolivet   PetscCall(PetscOptionsBoundedReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg, 0.0));
1027a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver, jac->strongthreshold));
102852ce0ab5SPierre Jolivet   PetscCall(PetscOptionsRangeReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg, 0.0, 1.0));
1029a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver, jac->maxrowsum));
103016d9e3a6SLisandro Dalcin 
103116d9e3a6SLisandro Dalcin   /* Grid sweeps */
10329566063dSJacob 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));
103316d9e3a6SLisandro Dalcin   if (flg) {
103416d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
103516d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
10360f1074feSSatish Balay     jac->gridsweeps[1] = indx;
10370f1074feSSatish Balay     /*defaults coarse to 1 */
10380f1074feSSatish Balay     jac->gridsweeps[2] = 1;
103916d9e3a6SLisandro Dalcin   }
10409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
1041f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetNodal(jac->hsolver, (HYPRE_Int)jac->nodal_coarsening));
10429566063dSJacob 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));
1043f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetNodalDiag(jac->hsolver, (HYPRE_Int)jac->nodal_coarsening_diag));
10449566063dSJacob 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));
1045f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetInterpVecVariant(jac->hsolver, (HYPRE_Int)jac->vec_interp_variant));
10469566063dSJacob 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));
1047f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetInterpVecQMax(jac->hsolver, (HYPRE_Int)jac->vec_interp_qmax));
10489566063dSJacob 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));
1049a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothInterpVectors(jac->hsolver, jac->vec_interp_smooth));
10509566063dSJacob 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));
1051f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetInterpRefine(jac->hsolver, (HYPRE_Int)jac->interp_refine));
10529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
105316d9e3a6SLisandro Dalcin   if (flg) {
1054f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver, (HYPRE_Int)indx, 1));
10550f1074feSSatish Balay     jac->gridsweeps[0] = indx;
105616d9e3a6SLisandro Dalcin   }
10579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
105816d9e3a6SLisandro Dalcin   if (flg) {
1059f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver, (HYPRE_Int)indx, 2));
10600f1074feSSatish Balay     jac->gridsweeps[1] = indx;
106116d9e3a6SLisandro Dalcin   }
10629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
106316d9e3a6SLisandro Dalcin   if (flg) {
1064f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver, (HYPRE_Int)indx, 3));
10650f1074feSSatish Balay     jac->gridsweeps[2] = indx;
106616d9e3a6SLisandro Dalcin   }
106716d9e3a6SLisandro Dalcin 
10686a251517SEike Mueller   /* Smooth type */
1069dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
10706a251517SEike Mueller   if (flg) {
10716a251517SEike Mueller     jac->smoothtype = indx;
1072f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothType(jac->hsolver, (HYPRE_Int)indx + 5));
10738131ecf7SEike Mueller     jac->smoothnumlevels = 25;
1074a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothNumLevels(jac->hsolver, 25));
10758131ecf7SEike Mueller   }
10768131ecf7SEike Mueller 
10778131ecf7SEike Mueller   /* Number of smoothing levels */
10789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
10798131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
10808131ecf7SEike Mueller     jac->smoothnumlevels = indx;
1081f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothNumLevels(jac->hsolver, (HYPRE_Int)indx));
10826a251517SEike Mueller   }
10836a251517SEike Mueller 
10843c61a47dSLukas   /* Smooth num sweeps */
10853c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_sweeps", "Set number of smoother sweeps", "None", 1, &indx, &flg));
10863c61a47dSLukas   if (flg && indx > 0) {
10873c61a47dSLukas     jac->smoothsweeps = indx;
1088f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothNumSweeps(jac->hsolver, (HYPRE_Int)indx));
10893c61a47dSLukas   }
10903c61a47dSLukas 
10913c61a47dSLukas   /* ILU: ILU Type */
10923c61a47dSLukas   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_ilu_type", "Choose ILU Type", "None", HYPREILUType, PETSC_STATIC_ARRAY_LENGTH(HYPREILUType), HYPREILUType[0], &indx, &flg));
1093f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUType(jac->hsolver, (HYPRE_Int)indx));
10943c61a47dSLukas 
10953c61a47dSLukas   /* ILU: ILU iterative setup type*/
10963c61a47dSLukas   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));
1097f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUIterSetupType(jac->hsolver, (HYPRE_Int)indx));
10983c61a47dSLukas 
10993c61a47dSLukas   /* ILU: ILU iterative setup option*/
11003c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_option", "Set ILU iterative setup option", "None", 0, &indx, &flg));
1101f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUIterSetupOption(jac->hsolver, (HYPRE_Int)indx));
11023c61a47dSLukas 
11033c61a47dSLukas   /* ILU: ILU iterative setup maxiter */
11043c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_iterative_setup_maxiter", "Set ILU iterative setup maximum iteration count", "None", 0, &indx, &flg));
1105f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUIterSetupMaxIter(jac->hsolver, (HYPRE_Int)indx));
11063c61a47dSLukas 
11073c61a47dSLukas   /* ILU: ILU iterative setup tolerance */
11083c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_iterative_setup_tolerance", "Set ILU iterative setup tolerance", "None", 0, &tmpdbl, &flg));
1109a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(hypre_BoomerAMGSetILUIterSetupTolerance(jac->hsolver, tmpdbl));
11103c61a47dSLukas 
11113c61a47dSLukas   /* ILU: ILU Print Level */
11123c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_print_level", "Set ILU print level", "None", 0, &indx, &flg));
1113f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetPrintLevel(jac->hsolver, (HYPRE_Int)indx));
11143c61a47dSLukas 
11153c61a47dSLukas   /* ILU: Logging */
11163c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_logging", "Set ILU logging level", "None", 0, &indx, &flg));
1117f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetLogging(jac->hsolver, (HYPRE_Int)indx));
11183c61a47dSLukas 
11193c61a47dSLukas   /* ILU: ILU Level */
11203c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_level", "Set ILU level", "None", 0, &indx, &flg));
1121f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILULevel(jac->hsolver, (HYPRE_Int)indx));
11223c61a47dSLukas 
11233c61a47dSLukas   /* ILU: ILU Max NNZ per row */
11243c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_max_nnz_per_row", "Set maximum NNZ per row", "None", 0, &indx, &flg));
1125f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUMaxRowNnz(jac->hsolver, (HYPRE_Int)indx));
11263c61a47dSLukas 
11273c61a47dSLukas   /* ILU: maximum iteration count */
11283c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_maxiter", "Set ILU max iterations", "None", 0, &indx, &flg));
1129f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUMaxIter(jac->hsolver, (HYPRE_Int)indx));
11303c61a47dSLukas 
11313c61a47dSLukas   /* ILU: drop threshold */
11323c61a47dSLukas   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_ilu_drop_tol", "Drop tolerance for ILU", "None", 0, &tmpdbl, &flg));
1133a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUDroptol(jac->hsolver, tmpdbl));
11343c61a47dSLukas 
11353c61a47dSLukas   /* ILU: Triangular Solve */
11363c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_tri_solve", "Enable triangular solve", "None", PETSC_FALSE, &tmp_truth, &flg));
1137a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUTriSolve(jac->hsolver, tmp_truth));
11383c61a47dSLukas 
11393c61a47dSLukas   /* ILU: Lower Jacobi iteration */
11403c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_lower_jacobi_iters", "Set lower Jacobi iteration count", "None", 0, &indx, &flg));
1141f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILULowerJacobiIters(jac->hsolver, (HYPRE_Int)indx));
11423c61a47dSLukas 
11433c61a47dSLukas   /* ILU: Upper Jacobi iteration */
11443c61a47dSLukas   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_ilu_upper_jacobi_iters", "Set upper Jacobi iteration count", "None", 0, &indx, &flg));
1145f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILUUpperJacobiIters(jac->hsolver, (HYPRE_Int)indx));
11463c61a47dSLukas 
11473c61a47dSLukas   /* ILU: local reordering */
11483c61a47dSLukas   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_ilu_local_reordering", "Enable local reordering", "None", PETSC_FALSE, &tmp_truth, &flg));
1149a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetILULocalReordering(jac->hsolver, tmp_truth));
11503c61a47dSLukas 
11511810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
11529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
11533c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11541810e44eSEike Mueller     jac->eu_level = indx;
1155f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetEuLevel(jac->hsolver, (HYPRE_Int)indx));
11561810e44eSEike Mueller   }
11571810e44eSEike Mueller 
11581810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
115973dcfd97SStefano Zampini   PetscReal droptolerance;
11609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
11613c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11621810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
1163a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetEuLevel(jac->hsolver, droptolerance));
11641810e44eSEike Mueller   }
11651810e44eSEike Mueller 
11661810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
11679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
11683c61a47dSLukas   if (flg && (jac->smoothtype == 4)) {
11691810e44eSEike Mueller     jac->eu_bj = tmp_truth;
1170f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetEuBJ(jac->hsolver, (HYPRE_Int)jac->eu_bj));
11711810e44eSEike Mueller   }
11721810e44eSEike Mueller 
117316d9e3a6SLisandro Dalcin   /* Relax type */
1174abf5c9d9SBarry Smith   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all", "Relax type for the up and down cycles", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType),
1175abf5c9d9SBarry Smith                               jac->relaxtype[0] < 0 ? "not yet set" : HYPREBoomerAMGRelaxType[jac->relaxtype[0]], &indx, &flg));
1176abf5c9d9SBarry Smith   if (flg) jac->relaxtype[0] = jac->relaxtype[1] = indx;
1177abf5c9d9SBarry Smith   PetscCall(
1178abf5c9d9SBarry Smith     PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down", "Relax type for the down cycles", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), jac->relaxtype[0] < 0 ? "not yet set" : HYPREBoomerAMGRelaxType[jac->relaxtype[0]], &indx, &flg));
1179abf5c9d9SBarry Smith   if (flg) jac->relaxtype[0] = indx;
1180abf5c9d9SBarry Smith   PetscCall(
1181abf5c9d9SBarry Smith     PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up", "Relax type for the up cycles", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), jac->relaxtype[1] < 0 ? "not yet set" : HYPREBoomerAMGRelaxType[jac->relaxtype[1]], &indx, &flg));
1182abf5c9d9SBarry Smith   if (flg) jac->relaxtype[1] = indx;
1183abf5c9d9SBarry Smith   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse", "Relax type on coarse grid", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), HYPREBoomerAMGRelaxType[jac->relaxtype[2]], &indx, &flg));
1184abf5c9d9SBarry Smith   if (flg) jac->relaxtype[2] = indx;
118516d9e3a6SLisandro Dalcin 
118616d9e3a6SLisandro Dalcin   /* Relaxation Weight */
11879566063dSJacob 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));
118816d9e3a6SLisandro Dalcin   if (flg) {
1189a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetRelaxWt(jac->hsolver, tmpdbl));
119016d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
119116d9e3a6SLisandro Dalcin   }
119216d9e3a6SLisandro Dalcin 
119316d9e3a6SLisandro Dalcin   n         = 2;
119416d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
11959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
119616d9e3a6SLisandro Dalcin   if (flg) {
11970fdf79fbSJacob 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);
119816d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1199f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetLevelRelaxWt(jac->hsolver, twodbl[0], (HYPRE_Int)indx));
120016d9e3a6SLisandro Dalcin   }
120116d9e3a6SLisandro Dalcin 
120216d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
12039566063dSJacob 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));
120416d9e3a6SLisandro Dalcin   if (flg) {
1205a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetOuterWt(jac->hsolver, tmpdbl));
120616d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
120716d9e3a6SLisandro Dalcin   }
120816d9e3a6SLisandro Dalcin 
120916d9e3a6SLisandro Dalcin   n         = 2;
121016d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
12119566063dSJacob 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));
121216d9e3a6SLisandro Dalcin   if (flg) {
12130fdf79fbSJacob 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);
121416d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
1215f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetLevelOuterWt(jac->hsolver, twodbl[0], (HYPRE_Int)indx));
121616d9e3a6SLisandro Dalcin   }
121716d9e3a6SLisandro Dalcin 
121816d9e3a6SLisandro Dalcin   /* the Relax Order */
12199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
1220ec342aa2SAlex Lindsay   if (flg) jac->relaxorder = !tmp_truth;
1221dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
122216d9e3a6SLisandro Dalcin   if (flg) {
122316d9e3a6SLisandro Dalcin     jac->measuretype = indx;
1224f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetMeasureType(jac->hsolver, (HYPRE_Int)jac->measuretype));
122516d9e3a6SLisandro Dalcin   }
1226abf5c9d9SBarry Smith   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), jac->coarsentype < 0 ? "unknown" : HYPREBoomerAMGCoarsenType[jac->coarsentype], &indx, &flg));
1227abf5c9d9SBarry Smith   if (flg) jac->coarsentype = indx;
12280f1074feSSatish Balay 
12299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
1230f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetMaxCoarseSize(jac->hsolver, (HYPRE_Int)jac->maxc));
12319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
1232f2f41e48SZach Atkins   if (flg) PetscCallHYPRE(HYPRE_BoomerAMGSetMinCoarseSize(jac->hsolver, (HYPRE_Int)jac->minc));
1233db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
1234db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
1235abf5c9d9SBarry Smith   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), jac->spgemm_type, &indx, &flg));
1236d7185485SAlex Lindsay   if (flg) PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, HYPRESpgemmTypes[indx]));
1237db6f9c32SMark Adams #endif
1238589dcaf0SStefano Zampini   /* AIR */
1239589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
12409566063dSJacob 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));
1241f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_BoomerAMGSetRestriction(jac->hsolver, (HYPRE_Int)jac->Rtype));
1242589dcaf0SStefano Zampini   if (jac->Rtype) {
124319be502cSAlexander     HYPRE_Int **grid_relax_points = hypre_TAlloc(HYPRE_Int *, 4, HYPRE_MEMORY_HOST);
124419be502cSAlexander     char       *prerelax[256];
124519be502cSAlexander     char       *postrelax[256];
124619be502cSAlexander     char        stringF[2] = "F", stringC[2] = "C", stringA[2] = "A";
124719be502cSAlexander     PetscInt    ns_down = 256, ns_up = 256;
124819be502cSAlexander     PetscBool   matchF, matchC, matchA;
124919be502cSAlexander 
1250589dcaf0SStefano 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 */
1251589dcaf0SStefano Zampini 
12529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
1253a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetStrongThresholdR(jac->hsolver, jac->Rstrongthreshold));
1254589dcaf0SStefano Zampini 
12559566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
1256a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetFilterThresholdR(jac->hsolver, jac->Rfilterthreshold));
1257589dcaf0SStefano Zampini 
12589566063dSJacob 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));
1259f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetADropTol(jac->hsolver, (HYPRE_Int)jac->Adroptol));
1260589dcaf0SStefano Zampini 
12619566063dSJacob 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));
1262f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetADropType(jac->hsolver, (HYPRE_Int)jac->Adroptype));
126319be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_prerelax", "Defines prerelax scheme", "None", prerelax, &ns_down, NULL));
126419be502cSAlexander     PetscCall(PetscOptionsStringArray("-pc_hypre_boomeramg_postrelax", "Defines postrelax scheme", "None", postrelax, &ns_up, NULL));
126519be502cSAlexander     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");
126619be502cSAlexander     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");
126719be502cSAlexander 
126819be502cSAlexander     grid_relax_points[0]    = NULL;
126919be502cSAlexander     grid_relax_points[1]    = hypre_TAlloc(HYPRE_Int, ns_down, HYPRE_MEMORY_HOST);
127019be502cSAlexander     grid_relax_points[2]    = hypre_TAlloc(HYPRE_Int, ns_up, HYPRE_MEMORY_HOST);
127119be502cSAlexander     grid_relax_points[3]    = hypre_TAlloc(HYPRE_Int, jac->gridsweeps[2], HYPRE_MEMORY_HOST);
127219be502cSAlexander     grid_relax_points[3][0] = 0;
127319be502cSAlexander 
127419be502cSAlexander     // set down relax scheme
127519be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) {
127619be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringF, &matchF));
127719be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringC, &matchC));
127819be502cSAlexander       PetscCall(PetscStrcasecmp(prerelax[i], stringA, &matchA));
127919be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_prerelax are C, F, and A");
128019be502cSAlexander       if (matchF) grid_relax_points[1][i] = -1;
128119be502cSAlexander       else if (matchC) grid_relax_points[1][i] = 1;
128219be502cSAlexander       else if (matchA) grid_relax_points[1][i] = 0;
128319be502cSAlexander     }
128419be502cSAlexander 
128519be502cSAlexander     // set up relax scheme
128619be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) {
128719be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringF, &matchF));
128819be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringC, &matchC));
128919be502cSAlexander       PetscCall(PetscStrcasecmp(postrelax[i], stringA, &matchA));
129019be502cSAlexander       PetscCheck(matchF || matchC || matchA, PetscObjectComm((PetscObject)jac), PETSC_ERR_ARG_WRONG, "Valid argument options for -pc_hypre_boomeramg_postrelax are C, F, and A");
129119be502cSAlexander       if (matchF) grid_relax_points[2][i] = -1;
129219be502cSAlexander       else if (matchC) grid_relax_points[2][i] = 1;
129319be502cSAlexander       else if (matchA) grid_relax_points[2][i] = 0;
129419be502cSAlexander     }
129519be502cSAlexander 
129619be502cSAlexander     // set coarse relax scheme
129719be502cSAlexander     for (PetscInt i = 0; i < jac->gridsweeps[2]; i++) grid_relax_points[3][i] = 0;
129819be502cSAlexander 
129919be502cSAlexander     // Pass relax schemes to hypre
1300a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetGridRelaxPoints(jac->hsolver, grid_relax_points));
130119be502cSAlexander 
130219be502cSAlexander     // cleanup memory
130319be502cSAlexander     for (PetscInt i = 0; i < ns_down; i++) PetscCall(PetscFree(prerelax[i]));
130419be502cSAlexander     for (PetscInt i = 0; i < ns_up; i++) PetscCall(PetscFree(postrelax[i]));
1305589dcaf0SStefano Zampini   }
1306589dcaf0SStefano Zampini #endif
1307589dcaf0SStefano Zampini 
1308ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
130963a3b9bcSJacob 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);
1310ecae95adSPierre Jolivet #endif
1311ecae95adSPierre Jolivet 
1312abf5c9d9SBarry Smith   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), jac->interptype < 0 ? "unknown" : HYPREBoomerAMGInterpType[jac->interptype], &indx, &flg));
1313589dcaf0SStefano Zampini   if (flg) jac->interptype = indx;
13140f1074feSSatish Balay 
13159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
131616d9e3a6SLisandro Dalcin   if (flg) {
1317b96a4a96SBarry Smith     level = 3;
13189566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
13192fa5cd67SKarl Rupp 
1320b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1321f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetPrintLevel(jac->hsolver, (HYPRE_Int)level));
13222ae77aedSBarry Smith   }
13232ae77aedSBarry Smith 
13249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
13252ae77aedSBarry Smith   if (flg) {
1326b96a4a96SBarry Smith     level = 3;
13279566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
13282fa5cd67SKarl Rupp 
1329b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1330f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetDebugFlag(jac->hsolver, (HYPRE_Int)level));
133116d9e3a6SLisandro Dalcin   }
13328f87f92bSBarry Smith 
13339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
13348f87f92bSBarry Smith   if (flg && tmp_truth) {
13358f87f92bSBarry Smith     PetscInt tmp_int;
1336f2f41e48SZach Atkins     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", (HYPRE_Int)jac->nodal_relax_levels, &tmp_int, &flg));
13378f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1338a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothType(jac->hsolver, 6));
1339a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetDomainType(jac->hsolver, 1));
1340a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetOverlap(jac->hsolver, 0));
1341f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSmoothNumLevels(jac->hsolver, (HYPRE_Int)jac->nodal_relax_levels));
13428f87f92bSBarry Smith   }
13438f87f92bSBarry Smith 
1344abf5c9d9SBarry Smith   PetscCall(PetscOptionsBool3("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1345589dcaf0SStefano Zampini 
1346589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1347dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1348589dcaf0SStefano Zampini   if (flg) {
1349589dcaf0SStefano Zampini     jac->symt = indx;
1350f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGSetSym(jac->hsolver, (HYPRE_Int)jac->symt));
1351589dcaf0SStefano Zampini   }
1352589dcaf0SStefano Zampini 
1353d0609cedSBarry Smith   PetscOptionsHeadEnd();
13543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135516d9e3a6SLisandro Dalcin }
135616d9e3a6SLisandro Dalcin 
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)1357d71ae5a4SJacob 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)
1358d71ae5a4SJacob Faibussowitsch {
135916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13602cf14000SStefano Zampini   HYPRE_Int oits;
136116d9e3a6SLisandro Dalcin 
136216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13639566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1364f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_BoomerAMGSetMaxIter(jac->hsolver, (HYPRE_Int)(its * jac->maxiter)));
1365a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_BoomerAMGSetTol(jac->hsolver, rtol));
136616d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
13679566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
136816d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1369a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_BoomerAMGGetNumIterations(jac->hsolver, &oits));
13704d0a8057SBarry Smith   *outits = oits;
13714d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
13724d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1373a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_BoomerAMGSetTol(jac->hsolver, jac->tol));
1374f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_BoomerAMGSetMaxIter(jac->hsolver, (HYPRE_Int)jac->maxiter));
13753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
137616d9e3a6SLisandro Dalcin }
137716d9e3a6SLisandro Dalcin 
PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)1378d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1379d71ae5a4SJacob Faibussowitsch {
138016d9e3a6SLisandro Dalcin   PC_HYPRE         *jac      = (PC_HYPRE *)pc->data;
13813c61a47dSLukas   hypre_ParAMGData *amg_data = (hypre_ParAMGData *)jac->hsolver;
13829f196a02SMartin Diehl   PetscBool         isascii;
13833c61a47dSLukas   PetscInt          indx;
13843c61a47dSLukas   PetscReal         val;
138516d9e3a6SLisandro Dalcin 
138616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
13879f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
13889f196a02SMartin Diehl   if (isascii) {
13899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
13909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
139163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
139263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
13939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
13949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
13959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
139663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
139748a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
139863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
139963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
14000f1074feSSatish Balay 
14019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
140216d9e3a6SLisandro Dalcin 
140363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
140463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
140563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
140616d9e3a6SLisandro Dalcin 
1407abf5c9d9SBarry Smith     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", jac->relaxtype[0] < 0 ? "not yet set" : HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
1408abf5c9d9SBarry Smith     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", jac->relaxtype[1] < 0 ? "not yet set" : HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
14099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
141016d9e3a6SLisandro Dalcin 
14119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
14129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
141316d9e3a6SLisandro Dalcin 
141419be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum size of coarsest grid %" PetscInt_FMT "\n", jac->maxc));
141519be502cSAlexander     PetscCall(PetscViewerASCIIPrintf(viewer, "    Minimum size of coarsest grid %" PetscInt_FMT "\n", jac->minc));
141619be502cSAlexander 
1417abf5c9d9SBarry Smith     if (jac->relaxorder == PETSC_DECIDE) {
1418abf5c9d9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "    CF-relaxation option not yet determined\n"));
1419abf5c9d9SBarry Smith     } else if (jac->relaxorder) {
14209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
142116d9e3a6SLisandro Dalcin     } else {
14229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
142316d9e3a6SLisandro Dalcin     }
14246a251517SEike Mueller     if (jac->smoothtype != -1) {
14259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
142663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
14273c61a47dSLukas       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num sweeps    %" PetscInt_FMT "\n", jac->smoothsweeps));
14283c61a47dSLukas       if (jac->smoothtype == 0) {
14293c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUType", indx = hypre_ParAMGDataILUType(amg_data));
14303c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU type              %s (%" PetscInt_FMT ")\n", HYPREILUType[indx], indx));
14313c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULevel", indx = hypre_ParAMGDataILULevel(amg_data));
14323c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU level             %" PetscInt_FMT "\n", indx));
14333c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxIter", indx = hypre_ParAMGDataILUMaxIter(amg_data));
14343c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max iterations    %" PetscInt_FMT "\n", indx));
14353c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUMaxRowNnz", indx = hypre_ParAMGDataILUMaxRowNnz(amg_data));
14363c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU max NNZ per row   %" PetscInt_FMT "\n", indx));
14373c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUTriSolve", indx = hypre_ParAMGDataILUTriSolve(amg_data));
14383c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU triangular solve  %" PetscInt_FMT "\n", indx));
14393c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataTol", val = hypre_ParAMGDataTol(amg_data));
14403c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU tolerance         %e\n", val));
14413c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUDroptol", val = hypre_ParAMGDataILUDroptol(amg_data));
14423c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU drop tolerance    %e\n", val));
14433c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULocalReordering", indx = hypre_ParAMGDataILULocalReordering(amg_data));
14443c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU local reordering  %" PetscInt_FMT "\n", indx));
14453c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILULowerJacobiIters", indx = hypre_ParAMGDataILULowerJacobiIters(amg_data));
14463c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU lower Jacobi iterations  %" PetscInt_FMT "\n", indx));
14473c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUUpperJacobiIters", indx = hypre_ParAMGDataILUUpperJacobiIters(amg_data));
14483c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU upper Jacobi iterations  %" PetscInt_FMT "\n", indx));
14493c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataPrintLevel", indx = hypre_ParAMGDataPrintLevel(amg_data));
14503c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU print level      %" PetscInt_FMT "\n", indx));
14513c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataLogging", indx = hypre_ParAMGDataLogging(amg_data));
14523c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU logging level    %" PetscInt_FMT "\n", indx));
14533c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupType", indx = hypre_ParAMGDataILUIterSetupType(amg_data));
14543c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup type           %s (%" PetscInt_FMT ")\n", HYPREILUIterSetup[indx], indx));
14553c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupOption", indx = hypre_ParAMGDataILUIterSetupOption(amg_data));
14563c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup option         %" PetscInt_FMT "\n", indx));
14573c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupMaxIter", indx = hypre_ParAMGDataILUIterSetupMaxIter(amg_data));
14583c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup max iterations %" PetscInt_FMT "\n", indx));
14593c61a47dSLukas         PetscStackCallExternalVoid("hypre_ParAMGDataILUIterSetupTolerance", val = hypre_ParAMGDataILUIterSetupTolerance(amg_data));
14603c61a47dSLukas         PetscCall(PetscViewerASCIIPrintf(viewer, "    ILU iterative setup tolerance      %e\n", val));
14613c61a47dSLukas       }
14627e352d70SEike Mueller     } else {
14639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
14641810e44eSEike Mueller     }
14651810e44eSEike Mueller     if (jac->smoothtype == 3) {
146663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
14679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
146863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
14696a251517SEike Mueller     }
14709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
1471abf5c9d9SBarry Smith     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", jac->coarsentype < 0 ? "not yet set" : HYPREBoomerAMGCoarsenType[jac->coarsentype]));
1472abf5c9d9SBarry Smith     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? (jac->interptype < 0 ? "not yet set" : HYPREBoomerAMGInterpType[jac->interptype]) : "1pt"));
147348a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
14745272c319SBarry Smith     if (jac->vec_interp_variant) {
147563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
147663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
14779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
14788f87f92bSBarry Smith     }
147948a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1480db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
14819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
14822d6c3ceeSStefano Zampini #else
14832d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1484db6f9c32SMark Adams #endif
1485589dcaf0SStefano Zampini     /* AIR */
1486589dcaf0SStefano Zampini     if (jac->Rtype) {
148763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
14889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
14899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
14909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
149163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1492589dcaf0SStefano Zampini     }
149316d9e3a6SLisandro Dalcin   }
14943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
149516d9e3a6SLisandro Dalcin }
149616d9e3a6SLisandro Dalcin 
PCSetFromOptions_HYPRE_ParaSails(PC pc,PetscOptionItems PetscOptionsObject)1497ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems PetscOptionsObject)
1498d71ae5a4SJacob Faibussowitsch {
149916d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
15004ddd07fcSJed Brown   PetscInt    indx;
1501ace3abfcSBarry Smith   PetscBool   flag;
150216d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
150316d9e3a6SLisandro Dalcin 
150416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1505d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
15069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
15079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1508f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParaSailsSetParams(jac->hsolver, jac->threshold, (HYPRE_Int)jac->nlevels));
150916d9e3a6SLisandro Dalcin 
15109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1511a333fa2bSZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParaSailsSetFilter(jac->hsolver, jac->filter));
151216d9e3a6SLisandro Dalcin 
15139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1514f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParaSailsSetLoadbal(jac->hsolver, (HYPRE_Int)jac->loadbal));
151516d9e3a6SLisandro Dalcin 
15169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1517f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParaSailsSetLogging(jac->hsolver, (HYPRE_Int)jac->logging));
151816d9e3a6SLisandro Dalcin 
15199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1520f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ParaSailsSetReuse(jac->hsolver, (HYPRE_Int)jac->ruse));
152116d9e3a6SLisandro Dalcin 
1522dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
152316d9e3a6SLisandro Dalcin   if (flag) {
152416d9e3a6SLisandro Dalcin     jac->symt = indx;
1525f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetSym(jac->hsolver, (HYPRE_Int)jac->symt));
152616d9e3a6SLisandro Dalcin   }
152716d9e3a6SLisandro Dalcin 
1528d0609cedSBarry Smith   PetscOptionsHeadEnd();
15293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
153016d9e3a6SLisandro Dalcin }
153116d9e3a6SLisandro Dalcin 
PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)1532d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1533d71ae5a4SJacob Faibussowitsch {
153416d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
15359f196a02SMartin Diehl   PetscBool   isascii;
1536feb237baSPierre Jolivet   const char *symt = 0;
153716d9e3a6SLisandro Dalcin 
153816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
15399f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
15409f196a02SMartin Diehl   if (isascii) {
15419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
154263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
15439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
15449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
15459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
15469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
15479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
15482fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
15492fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
15502fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
155163a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
15529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
155316d9e3a6SLisandro Dalcin   }
15543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
155516d9e3a6SLisandro Dalcin }
1556f1580f4eSBarry Smith 
PCSetFromOptions_HYPRE_AMS(PC pc,PetscOptionItems PetscOptionsObject)1557ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems PetscOptionsObject)
1558d71ae5a4SJacob Faibussowitsch {
15594cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15604cb006feSStefano Zampini   PetscInt  n;
15614cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
15624cb006feSStefano Zampini 
15634cb006feSStefano Zampini   PetscFunctionBegin;
1564d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
15659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1566f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_AMSSetPrintLevel(jac->hsolver, (HYPRE_Int)jac->as_print));
15679566063dSJacob 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));
1568f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_AMSSetMaxIter(jac->hsolver, (HYPRE_Int)jac->as_max_iter));
15699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1570f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_AMSSetCycleType(jac->hsolver, (HYPRE_Int)jac->ams_cycle_type));
15719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1572a333fa2bSZach Atkins   if (flag) PetscCallHYPRE(HYPRE_AMSSetTol(jac->hsolver, jac->as_tol));
15739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
15749566063dSJacob 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));
15759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
15769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
1577f2f41e48SZach Atkins   if (flag || flag2 || flag3 || flag4) PetscCallHYPRE(HYPRE_AMSSetSmoothingOptions(jac->hsolver, (HYPRE_Int)jac->as_relax_type, (HYPRE_Int)jac->as_relax_times, jac->as_relax_weight, jac->as_omega));
15789566063dSJacob 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));
15794cb006feSStefano Zampini   n = 5;
15809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
15814cb006feSStefano Zampini   if (flag || flag2) {
1582f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetAlphaAMGOptions(jac->hsolver, (HYPRE_Int)jac->as_amg_alpha_opts[0],            /* AMG coarsen type */
1583f2f41e48SZach Atkins                                                (HYPRE_Int)jac->as_amg_alpha_opts[1],                          /* AMG agg_levels */
1584f2f41e48SZach Atkins                                                (HYPRE_Int)jac->as_amg_alpha_opts[2],                          /* AMG relax_type */
1585f2f41e48SZach Atkins                                                jac->as_amg_alpha_theta, (HYPRE_Int)jac->as_amg_alpha_opts[3], /* AMG interp_type */
1586f2f41e48SZach Atkins                                                (HYPRE_Int)jac->as_amg_alpha_opts[4]));                        /* AMG Pmax */
15874cb006feSStefano Zampini   }
15889566063dSJacob 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));
15894cb006feSStefano Zampini   n = 5;
15909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
15914cb006feSStefano Zampini   if (flag || flag2) {
1592f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetBetaAMGOptions(jac->hsolver, (HYPRE_Int)jac->as_amg_beta_opts[0],           /* AMG coarsen type */
1593f2f41e48SZach Atkins                                               (HYPRE_Int)jac->as_amg_beta_opts[1],                         /* AMG agg_levels */
1594f2f41e48SZach Atkins                                               (HYPRE_Int)jac->as_amg_beta_opts[2],                         /* AMG relax_type */
1595f2f41e48SZach Atkins                                               jac->as_amg_beta_theta, (HYPRE_Int)jac->as_amg_beta_opts[3], /* AMG interp_type */
1596f2f41e48SZach Atkins                                               (HYPRE_Int)jac->as_amg_beta_opts[4]));                       /* AMG Pmax */
15974cb006feSStefano Zampini   }
15989566063dSJacob 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));
159923df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1600f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetProjectionFrequency(jac->hsolver, (HYPRE_Int)jac->ams_proj_freq));
160123df4f25SStefano Zampini   }
1602d0609cedSBarry Smith   PetscOptionsHeadEnd();
16033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16044cb006feSStefano Zampini }
16054cb006feSStefano Zampini 
PCView_HYPRE_AMS(PC pc,PetscViewer viewer)1606d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1607d71ae5a4SJacob Faibussowitsch {
16084cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16099f196a02SMartin Diehl   PetscBool isascii;
16104cb006feSStefano Zampini 
16114cb006feSStefano Zampini   PetscFunctionBegin;
16129f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
16139f196a02SMartin Diehl   if (isascii) {
16149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
161563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
161663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
161763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
161863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
161963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
162063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
162163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
16224cb006feSStefano Zampini     if (jac->alpha_Poisson) {
16239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
16244cb006feSStefano Zampini     } else {
16259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
16264cb006feSStefano Zampini     }
162763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
162863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
162963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
163063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
163163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
163263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
16334cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
16344cb006feSStefano Zampini       if (jac->beta_Poisson) {
16359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
16364cb006feSStefano Zampini       } else {
16379566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
16384cb006feSStefano Zampini       }
163963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
164063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
164163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
164263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
164363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
164463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
164548a46eb9SPierre 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));
164623df4f25SStefano Zampini     } else {
16479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
16484cb006feSStefano Zampini     }
16494cb006feSStefano Zampini   }
16503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16514cb006feSStefano Zampini }
16524cb006feSStefano Zampini 
PCSetFromOptions_HYPRE_ADS(PC pc,PetscOptionItems PetscOptionsObject)1653ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems PetscOptionsObject)
1654d71ae5a4SJacob Faibussowitsch {
1655863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1656863406b8SStefano Zampini   PetscInt  n;
1657863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1658863406b8SStefano Zampini 
1659863406b8SStefano Zampini   PetscFunctionBegin;
1660d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
16619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1662f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ADSSetPrintLevel(jac->hsolver, (HYPRE_Int)jac->as_print));
16639566063dSJacob 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));
1664f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ADSSetMaxIter(jac->hsolver, (HYPRE_Int)jac->as_max_iter));
16659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1666f2f41e48SZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ADSSetCycleType(jac->hsolver, (HYPRE_Int)jac->ads_cycle_type));
16679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1668a333fa2bSZach Atkins   if (flag) PetscCallHYPRE(HYPRE_ADSSetTol(jac->hsolver, jac->as_tol));
16699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
16709566063dSJacob 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));
16719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
16729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
1673f2f41e48SZach Atkins   if (flag || flag2 || flag3 || flag4) PetscCallHYPRE(HYPRE_ADSSetSmoothingOptions(jac->hsolver, (HYPRE_Int)jac->as_relax_type, (HYPRE_Int)jac->as_relax_times, jac->as_relax_weight, jac->as_omega));
16749566063dSJacob 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));
1675863406b8SStefano Zampini   n = 5;
16769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
16779566063dSJacob 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));
1678863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1679f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetAMSOptions(jac->hsolver, (HYPRE_Int)jac->ams_cycle_type,                  /* AMS cycle type */
1680f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[0],                          /* AMG coarsen type */
1681f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[1],                          /* AMG agg_levels */
1682f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[2],                          /* AMG relax_type */
1683f2f41e48SZach Atkins                                           jac->as_amg_alpha_theta, (HYPRE_Int)jac->as_amg_alpha_opts[3], /* AMG interp_type */
1684f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[4]));                        /* AMG Pmax */
1685863406b8SStefano Zampini   }
16869566063dSJacob 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));
1687863406b8SStefano Zampini   n = 5;
16889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1689863406b8SStefano Zampini   if (flag || flag2) {
1690f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetAMGOptions(jac->hsolver, (HYPRE_Int)jac->as_amg_beta_opts[0],           /* AMG coarsen type */
1691f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_beta_opts[1],                         /* AMG agg_levels */
1692f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_beta_opts[2],                         /* AMG relax_type */
1693f2f41e48SZach Atkins                                           jac->as_amg_beta_theta, (HYPRE_Int)jac->as_amg_beta_opts[3], /* AMG interp_type */
1694f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_beta_opts[4]));                       /* AMG Pmax */
1695863406b8SStefano Zampini   }
1696d0609cedSBarry Smith   PetscOptionsHeadEnd();
16973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1698863406b8SStefano Zampini }
1699863406b8SStefano Zampini 
PCView_HYPRE_ADS(PC pc,PetscViewer viewer)1700d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1701d71ae5a4SJacob Faibussowitsch {
1702863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17039f196a02SMartin Diehl   PetscBool isascii;
1704863406b8SStefano Zampini 
1705863406b8SStefano Zampini   PetscFunctionBegin;
17069f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
17079f196a02SMartin Diehl   if (isascii) {
17089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
170963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
171063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
171163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
171263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
171363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
171463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
171563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
17169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
171763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
171863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
171963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
172063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
172163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
172263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
172363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
17249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
172563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
172663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
172763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
172863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
172963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
173063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1731863406b8SStefano Zampini   }
17323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1733863406b8SStefano Zampini }
1734863406b8SStefano Zampini 
PCHYPRESetDiscreteGradient_HYPRE(PC pc,Mat G)1735d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1736d71ae5a4SJacob Faibussowitsch {
17374cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17385ac14e1cSStefano Zampini   PetscBool ishypre;
17394cb006feSStefano Zampini 
17404cb006feSStefano Zampini   PetscFunctionBegin;
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
17425ac14e1cSStefano Zampini   if (ishypre) {
17439566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
17449566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17455ac14e1cSStefano Zampini     jac->G = G;
17465ac14e1cSStefano Zampini   } else {
17479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
17489566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
17495ac14e1cSStefano Zampini   }
17503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17514cb006feSStefano Zampini }
17524cb006feSStefano Zampini 
17534cb006feSStefano Zampini /*@
1754c3466c22SBarry Smith   PCHYPRESetDiscreteGradient - Set the discrete gradient matrix for `PCHYPRE` type of AMS or ADS
17554cb006feSStefano Zampini 
1756c3339decSBarry Smith   Collective
17574cb006feSStefano Zampini 
17584cb006feSStefano Zampini   Input Parameters:
17594cb006feSStefano Zampini + pc - the preconditioning context
17604cb006feSStefano Zampini - G  - the discrete gradient
17614cb006feSStefano Zampini 
17624cb006feSStefano Zampini   Level: intermediate
17634cb006feSStefano Zampini 
176495452b02SPatrick Sanan   Notes:
1765c3466c22SBarry Smith   `G` should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1766147403d9SBarry Smith 
1767c3466c22SBarry Smith   Each row of `G` has 2 nonzeros, with column indexes being the global indexes of edge's endpoints: matrix entries are +1 and -1 depending on edge orientation
17684cb006feSStefano Zampini 
1769c3466c22SBarry Smith   Developer Note:
1770f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1771f1580f4eSBarry Smith 
1772562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
17734cb006feSStefano Zampini @*/
PCHYPRESetDiscreteGradient(PC pc,Mat G)1774d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1775d71ae5a4SJacob Faibussowitsch {
17764cb006feSStefano Zampini   PetscFunctionBegin;
17774cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17784cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
17794cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1780cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
17813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17824cb006feSStefano Zampini }
17834cb006feSStefano Zampini 
PCHYPRESetDiscreteCurl_HYPRE(PC pc,Mat C)1784d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1785d71ae5a4SJacob Faibussowitsch {
1786863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17875ac14e1cSStefano Zampini   PetscBool ishypre;
1788863406b8SStefano Zampini 
1789863406b8SStefano Zampini   PetscFunctionBegin;
17909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
17915ac14e1cSStefano Zampini   if (ishypre) {
17929566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
17939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
17945ac14e1cSStefano Zampini     jac->C = C;
17955ac14e1cSStefano Zampini   } else {
17969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
17979566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
17985ac14e1cSStefano Zampini   }
17993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1800863406b8SStefano Zampini }
1801863406b8SStefano Zampini 
1802863406b8SStefano Zampini /*@
1803c3466c22SBarry Smith   PCHYPRESetDiscreteCurl - Set the discrete curl matrix for `PCHYPRE` type of ADS
1804863406b8SStefano Zampini 
1805c3339decSBarry Smith   Collective
1806863406b8SStefano Zampini 
1807863406b8SStefano Zampini   Input Parameters:
1808863406b8SStefano Zampini + pc - the preconditioning context
1809863406b8SStefano Zampini - C  - the discrete curl
1810863406b8SStefano Zampini 
1811863406b8SStefano Zampini   Level: intermediate
1812863406b8SStefano Zampini 
181395452b02SPatrick Sanan   Notes:
1814c3466c22SBarry Smith   `C` should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1815147403d9SBarry Smith 
1816c3466c22SBarry Smith   Each row of `C` has as many nonzeros as the number of edges of a face, with column indexes being the global indexes of the corresponding edge.
1817c3466c22SBarry Smith   Matrix entries are +1 and -1 depending on edge orientation with respect to the face orientation
1818863406b8SStefano Zampini 
1819feefa0e1SJacob Faibussowitsch   Developer Notes:
1820f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1821f1580f4eSBarry Smith 
1822c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of ADS it should be called `PCHYPREADSSetDiscreteCurl()`
1823f1580f4eSBarry Smith 
1824562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1825863406b8SStefano Zampini @*/
PCHYPRESetDiscreteCurl(PC pc,Mat C)1826d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1827d71ae5a4SJacob Faibussowitsch {
1828863406b8SStefano Zampini   PetscFunctionBegin;
1829863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1830863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1831863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1832cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
18333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1834863406b8SStefano Zampini }
1835863406b8SStefano Zampini 
PCHYPRESetInterpolations_HYPRE(PC pc,PetscInt dim,Mat RT_PiFull,Mat RT_Pi[],Mat ND_PiFull,Mat ND_Pi[])1836d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1837d71ae5a4SJacob Faibussowitsch {
18386bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18396bf688a0SCe Qin   PetscBool ishypre;
18406bf688a0SCe Qin   PetscInt  i;
18416bf688a0SCe Qin 
18424d86920dSPierre Jolivet   PetscFunctionBegin;
18439566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
18449566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
18456bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
18469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
18479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
18486bf688a0SCe Qin   }
18496bf688a0SCe Qin 
18506bf688a0SCe Qin   jac->dim = dim;
18516bf688a0SCe Qin   if (RT_PiFull) {
18529566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
18536bf688a0SCe Qin     if (ishypre) {
18549566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
18556bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
18566bf688a0SCe Qin     } else {
18579566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
18586bf688a0SCe Qin     }
18596bf688a0SCe Qin   }
18606bf688a0SCe Qin   if (RT_Pi) {
18616bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18626bf688a0SCe Qin       if (RT_Pi[i]) {
18639566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
18646bf688a0SCe Qin         if (ishypre) {
18659566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
18666bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
18676bf688a0SCe Qin         } else {
18689566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
18696bf688a0SCe Qin         }
18706bf688a0SCe Qin       }
18716bf688a0SCe Qin     }
18726bf688a0SCe Qin   }
18736bf688a0SCe Qin   if (ND_PiFull) {
18749566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
18756bf688a0SCe Qin     if (ishypre) {
18769566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
18776bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
18786bf688a0SCe Qin     } else {
18799566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
18806bf688a0SCe Qin     }
18816bf688a0SCe Qin   }
18826bf688a0SCe Qin   if (ND_Pi) {
18836bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
18846bf688a0SCe Qin       if (ND_Pi[i]) {
18859566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
18866bf688a0SCe Qin         if (ishypre) {
18879566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
18886bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
18896bf688a0SCe Qin         } else {
18909566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
18916bf688a0SCe Qin         }
18926bf688a0SCe Qin       }
18936bf688a0SCe Qin     }
18946bf688a0SCe Qin   }
18953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18966bf688a0SCe Qin }
18976bf688a0SCe Qin 
18986bf688a0SCe Qin /*@
1899c3466c22SBarry Smith   PCHYPRESetInterpolations - Set the interpolation matrices for `PCHYPRE` type of AMS or ADS
19006bf688a0SCe Qin 
1901c3339decSBarry Smith   Collective
19026bf688a0SCe Qin 
19036bf688a0SCe Qin   Input Parameters:
19046bf688a0SCe Qin + pc        - the preconditioning context
19052fe279fdSBarry Smith . dim       - the dimension of the problem, only used in AMS
19062fe279fdSBarry Smith . RT_PiFull - Raviart-Thomas interpolation matrix
19072fe279fdSBarry Smith . RT_Pi     - x/y/z component of Raviart-Thomas interpolation matrix
19082fe279fdSBarry Smith . ND_PiFull - Nedelec interpolation matrix
19096bf688a0SCe Qin - ND_Pi     - x/y/z component of Nedelec interpolation matrix
19106bf688a0SCe Qin 
1911f1580f4eSBarry Smith   Level: intermediate
1912f1580f4eSBarry Smith 
191395452b02SPatrick Sanan   Notes:
1914c3466c22SBarry Smith   For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to `NULL`.
1915147403d9SBarry Smith 
19166bf688a0SCe Qin   For ADS, both type of interpolation matrices are needed.
1917147403d9SBarry Smith 
1918c3466c22SBarry Smith   Developer Note:
1919f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
19206bf688a0SCe Qin 
1921562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`
19226bf688a0SCe Qin @*/
PCHYPRESetInterpolations(PC pc,PetscInt dim,Mat RT_PiFull,Mat RT_Pi[],Mat ND_PiFull,Mat ND_Pi[])1923d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1924d71ae5a4SJacob Faibussowitsch {
19256bf688a0SCe Qin   PetscInt i;
19266bf688a0SCe Qin 
19276bf688a0SCe Qin   PetscFunctionBegin;
19286bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
19296bf688a0SCe Qin   if (RT_PiFull) {
19306bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
19316bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
19326bf688a0SCe Qin   }
19336bf688a0SCe Qin   if (RT_Pi) {
19344f572ea9SToby Isaac     PetscAssertPointer(RT_Pi, 4);
19356bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19366bf688a0SCe Qin       if (RT_Pi[i]) {
19376bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
19386bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
19396bf688a0SCe Qin       }
19406bf688a0SCe Qin     }
19416bf688a0SCe Qin   }
19426bf688a0SCe Qin   if (ND_PiFull) {
19436bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
19446bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
19456bf688a0SCe Qin   }
19466bf688a0SCe Qin   if (ND_Pi) {
19474f572ea9SToby Isaac     PetscAssertPointer(ND_Pi, 6);
19486bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
19496bf688a0SCe Qin       if (ND_Pi[i]) {
19506bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
19516bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
19526bf688a0SCe Qin       }
19536bf688a0SCe Qin     }
19546bf688a0SCe Qin   }
1955cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
19563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19576bf688a0SCe Qin }
19586bf688a0SCe Qin 
PCHYPRESetPoissonMatrix_HYPRE(PC pc,Mat A,PetscBool isalpha)1959d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1960d71ae5a4SJacob Faibussowitsch {
19614cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
19625ac14e1cSStefano Zampini   PetscBool ishypre;
19634cb006feSStefano Zampini 
19644cb006feSStefano Zampini   PetscFunctionBegin;
19659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
19665ac14e1cSStefano Zampini   if (ishypre) {
19675ac14e1cSStefano Zampini     if (isalpha) {
19689566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
19699566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
19705ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
19715ac14e1cSStefano Zampini     } else {
19725ac14e1cSStefano Zampini       if (A) {
19739566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
19745ac14e1cSStefano Zampini       } else {
19755ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
19765ac14e1cSStefano Zampini       }
19779566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
19785ac14e1cSStefano Zampini       jac->beta_Poisson = A;
19795ac14e1cSStefano Zampini     }
19805ac14e1cSStefano Zampini   } else {
19815ac14e1cSStefano Zampini     if (isalpha) {
19829566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
19839566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
19845ac14e1cSStefano Zampini     } else {
19855ac14e1cSStefano Zampini       if (A) {
19869566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
19879566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
19885ac14e1cSStefano Zampini       } else {
19899566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
19905ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
19915ac14e1cSStefano Zampini       }
19925ac14e1cSStefano Zampini     }
19935ac14e1cSStefano Zampini   }
19943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19954cb006feSStefano Zampini }
19964cb006feSStefano Zampini 
19974cb006feSStefano Zampini /*@
1998c3466c22SBarry Smith   PCHYPRESetAlphaPoissonMatrix - Set the vector Poisson matrix for `PCHYPRE` of type AMS
19994cb006feSStefano Zampini 
2000c3339decSBarry Smith   Collective
20014cb006feSStefano Zampini 
20024cb006feSStefano Zampini   Input Parameters:
20034cb006feSStefano Zampini + pc - the preconditioning context
20044cb006feSStefano Zampini - A  - the matrix
20054cb006feSStefano Zampini 
20064cb006feSStefano Zampini   Level: intermediate
20074cb006feSStefano Zampini 
2008f1580f4eSBarry Smith   Note:
2009c3466c22SBarry Smith   `A` should be obtained by discretizing the vector valued Poisson problem with linear finite elements
20104cb006feSStefano Zampini 
2011feefa0e1SJacob Faibussowitsch   Developer Notes:
2012f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2013f1580f4eSBarry Smith 
2014c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of AMS it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
2015f1580f4eSBarry Smith 
2016562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
20174cb006feSStefano Zampini @*/
PCHYPRESetAlphaPoissonMatrix(PC pc,Mat A)2018d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
2019d71ae5a4SJacob Faibussowitsch {
20204cb006feSStefano Zampini   PetscFunctionBegin;
20214cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20224cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20234cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
2024cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
20253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20264cb006feSStefano Zampini }
20274cb006feSStefano Zampini 
20284cb006feSStefano Zampini /*@
2029c3466c22SBarry Smith   PCHYPRESetBetaPoissonMatrix - Set the Poisson matrix for `PCHYPRE` of type AMS
20304cb006feSStefano Zampini 
2031c3339decSBarry Smith   Collective
20324cb006feSStefano Zampini 
20334cb006feSStefano Zampini   Input Parameters:
20344cb006feSStefano Zampini + pc - the preconditioning context
2035c3466c22SBarry Smith - A  - the matrix, or `NULL` to turn it off
20364cb006feSStefano Zampini 
20374cb006feSStefano Zampini   Level: intermediate
20384cb006feSStefano Zampini 
2039f1580f4eSBarry Smith   Note:
2040c3466c22SBarry Smith   `A` should be obtained by discretizing the Poisson problem with linear finite elements.
20414cb006feSStefano Zampini 
2042feefa0e1SJacob Faibussowitsch   Developer Notes:
2043f1580f4eSBarry Smith   This automatically converts the matrix to `MATHYPRE` if it is not already of that type
2044f1580f4eSBarry Smith 
2045c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of AMS it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
2046f1580f4eSBarry Smith 
2047562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
20484cb006feSStefano Zampini @*/
PCHYPRESetBetaPoissonMatrix(PC pc,Mat A)2049d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
2050d71ae5a4SJacob Faibussowitsch {
20514cb006feSStefano Zampini   PetscFunctionBegin;
20524cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
20534cb006feSStefano Zampini   if (A) {
20544cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
20554cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
20564cb006feSStefano Zampini   }
2057cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
20583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20594cb006feSStefano Zampini }
20604cb006feSStefano Zampini 
PCHYPRESetEdgeConstantVectors_HYPRE(PC pc,Vec ozz,Vec zoz,Vec zzo)2061d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
2062d71ae5a4SJacob Faibussowitsch {
20634cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
20644cb006feSStefano Zampini 
20654cb006feSStefano Zampini   PetscFunctionBegin;
20664cb006feSStefano Zampini   /* throw away any vector if already set */
20679566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
20689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
20699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
20709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
20719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
20729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
20739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
20745ac14e1cSStefano Zampini   jac->dim = 2;
20754cb006feSStefano Zampini   if (zzo) {
20769566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
20779566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
20785ac14e1cSStefano Zampini     jac->dim++;
20794cb006feSStefano Zampini   }
20803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20814cb006feSStefano Zampini }
20824cb006feSStefano Zampini 
20834cb006feSStefano Zampini /*@
2084c3466c22SBarry Smith   PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type AMS
20854cb006feSStefano Zampini 
2086c3339decSBarry Smith   Collective
20874cb006feSStefano Zampini 
20884cb006feSStefano Zampini   Input Parameters:
20894cb006feSStefano Zampini + pc  - the preconditioning context
20902fe279fdSBarry Smith . ozz - vector representing (1,0,0) (or (1,0) in 2D)
20912fe279fdSBarry Smith . zoz - vector representing (0,1,0) (or (0,1) in 2D)
20924cb006feSStefano Zampini - zzo - vector representing (0,0,1) (use NULL in 2D)
20934cb006feSStefano Zampini 
20944cb006feSStefano Zampini   Level: intermediate
20954cb006feSStefano Zampini 
2096c3466c22SBarry Smith   Developer Note:
2097c3466c22SBarry Smith   If this is only for  `PCHYPRE` type of AMS it should be called `PCHYPREAMSSetEdgeConstantVectors()`
2098f1580f4eSBarry Smith 
2099562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
21004cb006feSStefano Zampini @*/
PCHYPRESetEdgeConstantVectors(PC pc,Vec ozz,Vec zoz,Vec zzo)2101d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
2102d71ae5a4SJacob Faibussowitsch {
21034cb006feSStefano Zampini   PetscFunctionBegin;
21044cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
21054cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
21064cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
21074cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
21084cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
21094cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
21104cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
2111cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
21123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21134cb006feSStefano Zampini }
21144cb006feSStefano Zampini 
PCHYPREAMSSetInteriorNodes_HYPRE(PC pc,Vec interior)2115d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
2116d71ae5a4SJacob Faibussowitsch {
2117be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2118be14dc20SKerry Key 
2119be14dc20SKerry Key   PetscFunctionBegin;
2120be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
2121be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
2122be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
2123be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
21243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2125be14dc20SKerry Key }
2126be14dc20SKerry Key 
2127be14dc20SKerry Key /*@
2128c3466c22SBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type AMS
2129be14dc20SKerry Key 
2130c3339decSBarry Smith   Collective
2131be14dc20SKerry Key 
2132be14dc20SKerry Key   Input Parameters:
2133be14dc20SKerry Key + pc       - the preconditioning context
2134be14dc20SKerry Key - interior - vector. node is interior if its entry in the array is 1.0.
2135be14dc20SKerry Key 
2136be14dc20SKerry Key   Level: intermediate
2137be14dc20SKerry Key 
2138be14dc20SKerry Key   Note:
2139f1580f4eSBarry Smith   This calls `HYPRE_AMSSetInteriorNodes()`
2140f1580f4eSBarry Smith 
2141562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
2142be14dc20SKerry Key @*/
PCHYPREAMSSetInteriorNodes(PC pc,Vec interior)2143d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
2144d71ae5a4SJacob Faibussowitsch {
2145be14dc20SKerry Key   PetscFunctionBegin;
2146be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2147be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
2148be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
2149be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
21503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2151be14dc20SKerry Key }
2152be14dc20SKerry Key 
PCSetCoordinates_HYPRE(PC pc,PetscInt dim,PetscInt nloc,PetscReal * coords)2153d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2154d71ae5a4SJacob Faibussowitsch {
21554cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
21564cb006feSStefano Zampini   Vec       tv;
21574cb006feSStefano Zampini   PetscInt  i;
21584cb006feSStefano Zampini 
21594cb006feSStefano Zampini   PetscFunctionBegin;
21604cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
21619566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
21629566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
21639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
21645ac14e1cSStefano Zampini   jac->dim = dim;
21655ac14e1cSStefano Zampini 
21664cb006feSStefano Zampini   /* compute IJ vector for coordinates */
21679566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
21689566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
21699566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
21704cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
21714cb006feSStefano Zampini     PetscScalar *array;
21724cb006feSStefano Zampini     PetscInt     j;
21734cb006feSStefano Zampini 
21749566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
21759566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
21766ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
21779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
21789566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
21794cb006feSStefano Zampini   }
21809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
21813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21824cb006feSStefano Zampini }
21834cb006feSStefano Zampini 
PCHYPREGetType_HYPRE(PC pc,const char * name[])2184d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
2185d71ae5a4SJacob Faibussowitsch {
218616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
218716d9e3a6SLisandro Dalcin 
218816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
218916d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
21903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219116d9e3a6SLisandro Dalcin }
219216d9e3a6SLisandro Dalcin 
PCHYPRESetType_HYPRE(PC pc,const char name[])2193d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
2194d71ae5a4SJacob Faibussowitsch {
219516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
2196ace3abfcSBarry Smith   PetscBool flag;
219716d9e3a6SLisandro Dalcin 
219816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
219916d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
22009566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
2201d7185485SAlex Lindsay     if (flag) PetscFunctionReturn(PETSC_SUCCESS);
220216d9e3a6SLisandro Dalcin   }
220316d9e3a6SLisandro Dalcin 
2204d7185485SAlex Lindsay   PetscCall(PCReset_HYPRE(pc));
2205d7185485SAlex Lindsay   PetscCall(PetscFree(jac->hypre_type));
2206d7185485SAlex Lindsay   PetscCall(PetscStrallocpy(name, &jac->hypre_type));
2207d7185485SAlex Lindsay 
220816d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
220916d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
221016d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
221116d9e3a6SLisandro Dalcin 
22123c61a47dSLukas   PetscCall(PetscStrcmp("ilu", jac->hypre_type, &flag));
22133c61a47dSLukas   if (flag) {
22143c61a47dSLukas     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2215a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ILUCreate(&jac->hsolver));
22163c61a47dSLukas     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ILU;
22173c61a47dSLukas     pc->ops->view           = PCView_HYPRE_ILU;
22183c61a47dSLukas     jac->destroy            = HYPRE_ILUDestroy;
22193c61a47dSLukas     jac->setup              = HYPRE_ILUSetup;
22203c61a47dSLukas     jac->solve              = HYPRE_ILUSolve;
22213c61a47dSLukas     jac->factorrowsize      = PETSC_DEFAULT;
22223c61a47dSLukas     PetscFunctionReturn(PETSC_SUCCESS);
22233c61a47dSLukas   }
22243c61a47dSLukas 
22259566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
222616d9e3a6SLisandro Dalcin   if (flag) {
22279566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2228a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ParCSRPilutCreate(jac->comm_hypre, &jac->hsolver));
222916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
223016d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
223116d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
223216d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
223316d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
223416d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
22353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
223616d9e3a6SLisandro Dalcin   }
22379566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
2238db966c6cSHong Zhang   if (flag) {
22394e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
22407de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
22418bf83915SBarry Smith #endif
22429566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2243a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_EuclidCreate(jac->comm_hypre, &jac->hsolver));
2244db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
2245db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
2246db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
2247db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
2248db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
2249db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
2250db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
22513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2252db966c6cSHong Zhang   }
22539566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
225416d9e3a6SLisandro Dalcin   if (flag) {
22559566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
2256a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsCreate(jac->comm_hypre, &jac->hsolver));
225716d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
225816d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
225916d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
226016d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
226116d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
226216d9e3a6SLisandro Dalcin     /* initialize */
226316d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
22648966356dSPierre Jolivet     jac->threshold = .1;
226516d9e3a6SLisandro Dalcin     jac->filter    = .1;
226616d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
22672fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
22682fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
22692fa5cd67SKarl Rupp 
227016d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
227116d9e3a6SLisandro Dalcin     jac->symt = 0;
2272f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetParams(jac->hsolver, jac->threshold, (HYPRE_Int)jac->nlevels));
2273a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetFilter(jac->hsolver, jac->filter));
2274f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetLoadbal(jac->hsolver, (HYPRE_Int)jac->loadbal));
2275f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetLogging(jac->hsolver, (HYPRE_Int)jac->logging));
2276f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetReuse(jac->hsolver, (HYPRE_Int)jac->ruse));
2277f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ParaSailsSetSym(jac->hsolver, (HYPRE_Int)jac->symt));
22783ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
227916d9e3a6SLisandro Dalcin   }
22809566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
228116d9e3a6SLisandro Dalcin   if (flag) {
2282a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_BoomerAMGCreate(&jac->hsolver));
228316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
228416d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
228516d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
228616d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
228785245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
22889566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
22899566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
229042e5ec60SJeff-Hadley     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetCFMarkers_C", PCHYPREGetCFMarkers_BoomerAMG));
229116d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
229216d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
229316d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
229416d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
229516d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
229616d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
229716d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
229816d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
22998f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
230016d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
230116d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
230216d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
230316d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
23040f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
23056a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
2306b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
23071810e44eSEike Mueller     jac->eu_level                                                = 0;
23081810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
23091810e44eSEike Mueller     jac->eu_bj                                                   = 0;
231016d9e3a6SLisandro Dalcin     jac->relaxweight                                             = 1.0;
231116d9e3a6SLisandro Dalcin     jac->outerrelaxweight                                        = 1.0;
2312589dcaf0SStefano Zampini     jac->Rtype                                                   = 0;
2313589dcaf0SStefano Zampini     jac->Rstrongthreshold                                        = 0.25;
2314589dcaf0SStefano Zampini     jac->Rfilterthreshold                                        = 0.0;
2315589dcaf0SStefano Zampini     jac->Adroptype                                               = -1;
2316589dcaf0SStefano Zampini     jac->Adroptol                                                = 0.0;
23170f1074feSSatish Balay     jac->agg_nl                                                  = 0;
23180f1074feSSatish Balay     jac->pmax                                                    = 0;
23190f1074feSSatish Balay     jac->truncfactor                                             = 0.0;
23200f1074feSSatish Balay     jac->agg_num_paths                                           = 1;
2321589dcaf0SStefano Zampini     jac->maxc                                                    = 9;
2322589dcaf0SStefano Zampini     jac->minc                                                    = 1;
232322e51d31SStefano Zampini     jac->nodal_coarsening                                        = 0;
232422e51d31SStefano Zampini     jac->nodal_coarsening_diag                                   = 0;
232522e51d31SStefano Zampini     jac->vec_interp_variant                                      = 0;
232622e51d31SStefano Zampini     jac->vec_interp_qmax                                         = 0;
232722e51d31SStefano Zampini     jac->vec_interp_smooth                                       = PETSC_FALSE;
232822e51d31SStefano Zampini     jac->interp_refine                                           = 0;
23298f87f92bSBarry Smith     jac->nodal_relax                                             = PETSC_FALSE;
23308f87f92bSBarry Smith     jac->nodal_relax_levels                                      = 1;
23316ea7df73SStefano Zampini     jac->rap2                                                    = 0;
2332abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, relaxtype[2], 9); /* G.E. */
2333abf5c9d9SBarry Smith 
2334abf5c9d9SBarry Smith     /*
2335abf5c9d9SBarry Smith       Initialize the following parameters with invalid value so we can recognize user input that sets the parameter.
2336abf5c9d9SBarry Smith       If there is no user input they are overwritten in PCSetUp_HYPRE() depending on if the matrix is on the CPU or the GPU
2337abf5c9d9SBarry Smith     */
2338abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, relaxorder, PETSC_DECIDE);
2339abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, coarsentype, PETSC_DECIDE);
2340abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, interptype, PETSC_DECIDE);
2341abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, relaxtype[0], PETSC_DECIDE);
2342abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, relaxtype[1], PETSC_DECIDE);
2343abf5c9d9SBarry Smith #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
2344abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, spgemm_type, "not yet set");
2345abf5c9d9SBarry Smith #endif
2346abf5c9d9SBarry Smith #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2347abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, keeptranspose, PETSC_BOOL3_UNKNOWN);
2348abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, mod_rap2, PETSC_DECIDE);
2349abf5c9d9SBarry Smith #endif
2350abf5c9d9SBarry Smith     PetscObjectParameterSetDefault(jac, agg_interptype, PETSC_DECIDE);
23513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
235216d9e3a6SLisandro Dalcin   }
23539566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
23544cb006feSStefano Zampini   if (flag) {
2355a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_AMSCreate(&jac->hsolver));
23564cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
23574cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
23584cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
23594cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
23604cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
23614cb006feSStefano Zampini     jac->coords[0]          = NULL;
23624cb006feSStefano Zampini     jac->coords[1]          = NULL;
23634cb006feSStefano Zampini     jac->coords[2]          = NULL;
2364be14dc20SKerry Key     jac->interior           = NULL;
23654cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2366863406b8SStefano Zampini     jac->as_print       = 0;
2367863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2368863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
23694cb006feSStefano Zampini     jac->ams_cycle_type = 13;
23704cb006feSStefano Zampini     /* Smoothing options */
2371863406b8SStefano Zampini     jac->as_relax_type   = 2;
2372863406b8SStefano Zampini     jac->as_relax_times  = 1;
2373863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2374863406b8SStefano Zampini     jac->as_omega        = 1.0;
23754cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2376863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2377863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
23780bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2379863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2380863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2381863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
23824cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2383863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2384863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
23850bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2386863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2387863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2388863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2389f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetPrintLevel(jac->hsolver, (HYPRE_Int)jac->as_print));
2390f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetMaxIter(jac->hsolver, (HYPRE_Int)jac->as_max_iter));
2391f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetCycleType(jac->hsolver, (HYPRE_Int)jac->ams_cycle_type));
2392a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_AMSSetTol(jac->hsolver, jac->as_tol));
2393f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetSmoothingOptions(jac->hsolver, (HYPRE_Int)jac->as_relax_type, (HYPRE_Int)jac->as_relax_times, jac->as_relax_weight, jac->as_omega));
2394f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetAlphaAMGOptions(jac->hsolver, (HYPRE_Int)jac->as_amg_alpha_opts[0],            /* AMG coarsen type */
2395f2f41e48SZach Atkins                                                (HYPRE_Int)jac->as_amg_alpha_opts[1],                          /* AMG agg_levels */
2396f2f41e48SZach Atkins                                                (HYPRE_Int)jac->as_amg_alpha_opts[2],                          /* AMG relax_type */
2397f2f41e48SZach Atkins                                                jac->as_amg_alpha_theta, (HYPRE_Int)jac->as_amg_alpha_opts[3], /* AMG interp_type */
2398f2f41e48SZach Atkins                                                (HYPRE_Int)jac->as_amg_alpha_opts[4]));                        /* AMG Pmax */
2399f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_AMSSetBetaAMGOptions(jac->hsolver, (HYPRE_Int)jac->as_amg_beta_opts[0],              /* AMG coarsen type */
2400f2f41e48SZach Atkins                                               (HYPRE_Int)jac->as_amg_beta_opts[1],                            /* AMG agg_levels */
2401f2f41e48SZach Atkins                                               (HYPRE_Int)jac->as_amg_beta_opts[2],                            /* AMG relax_type */
2402f2f41e48SZach Atkins                                               jac->as_amg_beta_theta, (HYPRE_Int)jac->as_amg_beta_opts[3],    /* AMG interp_type */
2403f2f41e48SZach Atkins                                               (HYPRE_Int)jac->as_amg_beta_opts[4]));                          /* AMG Pmax */
240423df4f25SStefano Zampini     /* Zero conductivity */
240523df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
240623df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
24073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
24084cb006feSStefano Zampini   }
24099566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2410863406b8SStefano Zampini   if (flag) {
2411a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ADSCreate(&jac->hsolver));
2412863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2413863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2414863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2415863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2416863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2417863406b8SStefano Zampini     jac->coords[0]          = NULL;
2418863406b8SStefano Zampini     jac->coords[1]          = NULL;
2419863406b8SStefano Zampini     jac->coords[2]          = NULL;
2420863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2421863406b8SStefano Zampini     jac->as_print       = 0;
2422863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2423863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2424863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2425863406b8SStefano Zampini     /* Smoothing options */
2426863406b8SStefano Zampini     jac->as_relax_type   = 2;
2427863406b8SStefano Zampini     jac->as_relax_times  = 1;
2428863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2429863406b8SStefano Zampini     jac->as_omega        = 1.0;
2430863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2431863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2432863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2433863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2434863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2435863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2436863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2437863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2438863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2439863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2440863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2441863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2442863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2443863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2444863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2445f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetPrintLevel(jac->hsolver, (HYPRE_Int)jac->as_print));
2446f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetMaxIter(jac->hsolver, (HYPRE_Int)jac->as_max_iter));
2447f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetCycleType(jac->hsolver, (HYPRE_Int)jac->ams_cycle_type));
2448a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_ADSSetTol(jac->hsolver, jac->as_tol));
2449f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetSmoothingOptions(jac->hsolver, (HYPRE_Int)jac->as_relax_type, (HYPRE_Int)jac->as_relax_times, jac->as_relax_weight, jac->as_omega));
2450f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetAMSOptions(jac->hsolver, (HYPRE_Int)jac->ams_cycle_type,                  /* AMG coarsen type */
2451f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[0],                          /* AMG coarsen type */
2452f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[1],                          /* AMG agg_levels */
2453f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[2],                          /* AMG relax_type */
2454f2f41e48SZach Atkins                                           jac->as_amg_alpha_theta, (HYPRE_Int)jac->as_amg_alpha_opts[3], /* AMG interp_type */
2455f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_alpha_opts[4]));                        /* AMG Pmax */
2456f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_ADSSetAMGOptions(jac->hsolver, (HYPRE_Int)jac->as_amg_beta_opts[0],             /* AMG coarsen type */
2457f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_beta_opts[1],                           /* AMG agg_levels */
2458f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_beta_opts[2],                           /* AMG relax_type */
2459f2f41e48SZach Atkins                                           jac->as_amg_beta_theta, (HYPRE_Int)jac->as_amg_beta_opts[3],   /* AMG interp_type */
2460f2f41e48SZach Atkins                                           (HYPRE_Int)jac->as_amg_beta_opts[4]));                         /* AMG Pmax */
24613ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2462863406b8SStefano Zampini   }
24639566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
24642fa5cd67SKarl Rupp 
24650298fd71SBarry Smith   jac->hypre_type = NULL;
2466b06c524fSNuno Nobre   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, ilu, pilut, parasails, boomeramg, ams, ads", name);
246716d9e3a6SLisandro Dalcin }
246816d9e3a6SLisandro Dalcin 
246916d9e3a6SLisandro Dalcin /*
247016d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
247116d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
247216d9e3a6SLisandro Dalcin */
PCSetFromOptions_HYPRE(PC pc,PetscOptionItems PetscOptionsObject)2473ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems PetscOptionsObject)
2474d71ae5a4SJacob Faibussowitsch {
24754ddd07fcSJed Brown   PetscInt    indx;
24763c61a47dSLukas   const char *type[] = {"ilu", "euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2477ace3abfcSBarry Smith   PetscBool   flg;
2478d7185485SAlex Lindsay   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
247916d9e3a6SLisandro Dalcin 
248016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2481d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2482dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
2483d7185485SAlex Lindsay   if (flg) PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
2484d7185485SAlex Lindsay   /*
2485d7185485SAlex Lindsay     Set the type if it was never set.
2486d7185485SAlex Lindsay   */
2487d7185485SAlex Lindsay   if (!jac->hypre_type) PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
2488dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2489d0609cedSBarry Smith   PetscOptionsHeadEnd();
24903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
249116d9e3a6SLisandro Dalcin }
249216d9e3a6SLisandro Dalcin 
2493cc4c1da9SBarry Smith /*@
249416d9e3a6SLisandro Dalcin   PCHYPRESetType - Sets which hypre preconditioner you wish to use
249516d9e3a6SLisandro Dalcin 
249616d9e3a6SLisandro Dalcin   Input Parameters:
249716d9e3a6SLisandro Dalcin + pc   - the preconditioner context
2498c3466c22SBarry Smith - name - either euclid, ilu, pilut, parasails, boomeramg, ams, or ads
249916d9e3a6SLisandro Dalcin 
2500f1580f4eSBarry Smith   Options Database Key:
2501c3466c22SBarry Smith . pc_hypre_type - One of euclid, ilu, pilut, parasails, boomeramg, ams, or ads
250216d9e3a6SLisandro Dalcin 
250316d9e3a6SLisandro Dalcin   Level: intermediate
250416d9e3a6SLisandro Dalcin 
2505562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
250616d9e3a6SLisandro Dalcin @*/
PCHYPRESetType(PC pc,const char name[])2507d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2508d71ae5a4SJacob Faibussowitsch {
250916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25100700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25114f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2512cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
25133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
251416d9e3a6SLisandro Dalcin }
251516d9e3a6SLisandro Dalcin 
251642e5ec60SJeff-Hadley /*@C
251742e5ec60SJeff-Hadley   PCHYPREGetCFMarkers - Gets CF marker arrays for all levels (except the finest level)
251842e5ec60SJeff-Hadley 
251942e5ec60SJeff-Hadley   Logically Collective
252042e5ec60SJeff-Hadley 
252142e5ec60SJeff-Hadley   Input Parameter:
252242e5ec60SJeff-Hadley . pc - the preconditioner context
252342e5ec60SJeff-Hadley 
252442e5ec60SJeff-Hadley   Output Parameters:
252542e5ec60SJeff-Hadley + n_per_level - the number of nodes per level (size of `num_levels`)
252642e5ec60SJeff-Hadley - CFMarkers   - the Coarse/Fine Boolean arrays (size of `num_levels` - 1)
252742e5ec60SJeff-Hadley 
2528c3466c22SBarry Smith   Level: advanced
2529c3466c22SBarry Smith 
253042e5ec60SJeff-Hadley   Note:
253142e5ec60SJeff-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.
253242e5ec60SJeff-Hadley 
253342e5ec60SJeff-Hadley .seealso: [](ch_ksp), `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
253442e5ec60SJeff-Hadley @*/
PCHYPREGetCFMarkers(PC pc,PetscInt * n_per_level[],PetscBT * CFMarkers[])253542e5ec60SJeff-Hadley PetscErrorCode PCHYPREGetCFMarkers(PC pc, PetscInt *n_per_level[], PetscBT *CFMarkers[])
253642e5ec60SJeff-Hadley {
253742e5ec60SJeff-Hadley   PetscFunctionBegin;
253842e5ec60SJeff-Hadley   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
253942e5ec60SJeff-Hadley   PetscAssertPointer(n_per_level, 2);
254042e5ec60SJeff-Hadley   PetscAssertPointer(CFMarkers, 3);
254142e5ec60SJeff-Hadley   PetscUseMethod(pc, "PCHYPREGetCFMarkers_C", (PC, PetscInt *[], PetscBT *[]), (pc, n_per_level, CFMarkers));
254242e5ec60SJeff-Hadley   PetscFunctionReturn(PETSC_SUCCESS);
254342e5ec60SJeff-Hadley }
254442e5ec60SJeff-Hadley 
2545cc4c1da9SBarry Smith /*@
254616d9e3a6SLisandro Dalcin   PCHYPREGetType - Gets which hypre preconditioner you are using
254716d9e3a6SLisandro Dalcin 
254816d9e3a6SLisandro Dalcin   Input Parameter:
254916d9e3a6SLisandro Dalcin . pc - the preconditioner context
255016d9e3a6SLisandro Dalcin 
255116d9e3a6SLisandro Dalcin   Output Parameter:
2552c3466c22SBarry Smith . name - either euclid, ilu, pilut, parasails, boomeramg, ams, or ads
255316d9e3a6SLisandro Dalcin 
255416d9e3a6SLisandro Dalcin   Level: intermediate
255516d9e3a6SLisandro Dalcin 
2556562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
255716d9e3a6SLisandro Dalcin @*/
PCHYPREGetType(PC pc,const char * name[])2558d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2559d71ae5a4SJacob Faibussowitsch {
256016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
25610700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
25624f572ea9SToby Isaac   PetscAssertPointer(name, 2);
2563cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
25643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256516d9e3a6SLisandro Dalcin }
256616d9e3a6SLisandro Dalcin 
2567cc4c1da9SBarry Smith /*@
2568c3466c22SBarry Smith   PCMGGalerkinSetMatProductAlgorithm - Set type of sparse matrix-matrix product for hypre's BoomerAMG to use on GPUs
2569db6f9c32SMark Adams 
2570c3339decSBarry Smith   Logically Collective
2571db6f9c32SMark Adams 
2572db6f9c32SMark Adams   Input Parameters:
2573db6f9c32SMark Adams + pc   - the hypre context
2574feefa0e1SJacob Faibussowitsch - name - one of 'cusparse', 'hypre'
2575db6f9c32SMark Adams 
2576db6f9c32SMark Adams   Options Database Key:
2577c3466c22SBarry Smith . -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of sparse matrix-matrix product to use in hypre
2578db6f9c32SMark Adams 
2579db6f9c32SMark Adams   Level: intermediate
2580db6f9c32SMark Adams 
2581c3466c22SBarry Smith   Developer Note:
2582f1580f4eSBarry Smith   How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2583db6f9c32SMark Adams 
2584562efe2eSBarry Smith .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2585db6f9c32SMark Adams @*/
PCMGGalerkinSetMatProductAlgorithm(PC pc,const char name[])2586d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2587d71ae5a4SJacob Faibussowitsch {
2588db6f9c32SMark Adams   PetscFunctionBegin;
2589db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2590cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
25913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2592db6f9c32SMark Adams }
2593db6f9c32SMark Adams 
2594cc4c1da9SBarry Smith /*@
2595c3466c22SBarry Smith   PCMGGalerkinGetMatProductAlgorithm - Get type of sparse matrix-matrix product for hypre's BoomerAMG to use on GPUs
2596db6f9c32SMark Adams 
2597db6f9c32SMark Adams   Not Collective
2598db6f9c32SMark Adams 
2599db6f9c32SMark Adams   Input Parameter:
2600db6f9c32SMark Adams . pc - the multigrid context
2601db6f9c32SMark Adams 
2602db6f9c32SMark Adams   Output Parameter:
2603db6f9c32SMark Adams . name - one of 'cusparse', 'hypre'
2604db6f9c32SMark Adams 
2605db6f9c32SMark Adams   Level: intermediate
2606db6f9c32SMark Adams 
2607a94f484eSPierre Jolivet .seealso: [](ch_ksp), `PCHYPRE`, `PCMGGalerkinSetMatProductAlgorithm()`
2608db6f9c32SMark Adams @*/
PCMGGalerkinGetMatProductAlgorithm(PC pc,const char * name[])2609d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2610d71ae5a4SJacob Faibussowitsch {
2611db6f9c32SMark Adams   PetscFunctionBegin;
2612db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2613cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
26143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2615db6f9c32SMark Adams }
2616db6f9c32SMark Adams 
261716d9e3a6SLisandro Dalcin /*MC
2618f1580f4eSBarry Smith   PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
261916d9e3a6SLisandro Dalcin 
262016d9e3a6SLisandro Dalcin   Options Database Keys:
2621b5a865d8SNuno Nobre +   -pc_hypre_type                           - One of `euclid`, `ilu`, `pilut`, `parasails`, `boomeramg`, `ams`, or `ads`
2622c3466c22SBarry Smith . -pc_hypre_boomeramg_nodal_coarsen <n>      - where `n` is from 1 to 6 (see `HYPRE_BoomerAMGSetNodal()`)
2623c3466c22SBarry Smith . -pc_hypre_boomeramg_vec_interp_variant <v> - where `v` is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
26247cbeddf0SNuno Nobre - Many others - run with `-pc_type hypre` `-pc_hypre_type XXX` `-help` to see options for the XXX preconditioner
262516d9e3a6SLisandro Dalcin 
262616d9e3a6SLisandro Dalcin   Level: intermediate
262716d9e3a6SLisandro Dalcin 
262895452b02SPatrick Sanan   Notes:
2629e1ded407SBarry Smith   Apart from `-pc_hypre_type` (for which there is `PCHYPRESetType()`),
263016d9e3a6SLisandro Dalcin   the many hypre options can ONLY be set via the options database (e.g. the command line
263149567fc5SPierre Jolivet   or with `PetscOptionsSetValue()`, there are no functions to set them)
263216d9e3a6SLisandro Dalcin 
2633e1ded407SBarry Smith   The options `-pc_hypre_boomeramg_max_iter` and `-pc_hypre_boomeramg_tol` refer to the number of iterations
2634e1ded407SBarry Smith   (V-cycles) and tolerance that boomerAMG does EACH time it is called. So for example, if
2635e1ded407SBarry Smith   `-pc_hypre_boomeramg_max_iter` is set to 2 then 2-V-cycles are being used to define the preconditioner
2636e1ded407SBarry Smith   (`-pc_hypre_boomeramg_tol` should be set to 0.0 - the default - to strictly use a fixed number of
2637e1ded407SBarry Smith   iterations per hypre call). `-ksp_max_it` and `-ksp_rtol` STILL determine the total number of iterations
2638e1ded407SBarry Smith   and tolerance for the Krylov solver. For example, if `-pc_hypre_boomeramg_max_iter` is 2 and `-ksp_max_it` is 10
2639c3466c22SBarry Smith   then AT MOST twenty V-cycles of BoomerAMG will be used.
264016d9e3a6SLisandro Dalcin 
2641e1ded407SBarry Smith   Note that the option `-pc_hypre_boomeramg_relax_type_all` defaults to symmetric relaxation
26420f1074feSSatish Balay   (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2643e1ded407SBarry Smith   Otherwise, you may want to use `-pc_hypre_boomeramg_relax_type_all SOR/Jacobi`.
264416d9e3a6SLisandro Dalcin 
2645c3466c22SBarry Smith   If you provide a near null space to your matrix with `MatSetNearNullSpace()` it is ignored by hypre's BoomerAMG UNLESS you also use
2646e1ded407SBarry Smith   the following two options: `-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>`
26470b1a5bd9SEric Chamberland 
2648f1580f4eSBarry Smith   See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2649f1580f4eSBarry Smith 
2650e1ded407SBarry Smith   For `PCHYPRE` type of `ams` or `ads` auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2651f1580f4eSBarry Smith   `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
265249567fc5SPierre Jolivet   `PCHYPREAMSSetInteriorNodes()`
2653f1580f4eSBarry Smith 
2654e1ded407SBarry 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
2655e1ded407SBarry Smith   since it is usually slower, one should use a `KSPType` of `KSPRICHARDSON`
2656e1ded407SBarry Smith   (or equivalently `-ksp_type richardson`) to achieve this. Using `KSPPREONLY` will not work since it only applies a single cycle of multigrid.
2657e1ded407SBarry Smith 
26588fc55d51SJunchao Zhang   PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems.
26598fc55d51SJunchao Zhang 
26608fc55d51SJunchao Zhang   hypre supports performance logging via the `Caliper` library.  With `--download-hypre --download-caliper`, hypre will be automatically configured with the support.
26618fc55d51SJunchao Zhang 
26628fc55d51SJunchao Zhang   Enabling Caliper logging requires setting the `CALI_CONFIG` environment variable before running your hypre code. For example,
26638fc55d51SJunchao Zhang 
26648fc55d51SJunchao Zhang   .vb
26658fc55d51SJunchao Zhang     export CALI_CONFIG=runtime-report,max_column_width=200,calc.inclusive,mpi-report,output=stdout
26668fc55d51SJunchao Zhang   .ve
26678fc55d51SJunchao Zhang 
26688fc55d51SJunchao Zhang   Then run a hypre code, and you will see profiling results on stdout. See https://software.llnl.gov/Caliper/#guides for more options.
26699e5bc791SBarry Smith 
2670ead8c081SBarry Smith   GPU Notes:
2671ead8c081SBarry Smith   To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2672f1580f4eSBarry Smith   Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2673ead8c081SBarry Smith 
2674ead8c081SBarry Smith   To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2675f1580f4eSBarry Smith   Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2676ead8c081SBarry Smith 
2677562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2678f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2679f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
268016d9e3a6SLisandro Dalcin M*/
268116d9e3a6SLisandro Dalcin 
PCCreate_HYPRE(PC pc)2682d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2683d71ae5a4SJacob Faibussowitsch {
268416d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
268516d9e3a6SLisandro Dalcin 
268616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
26874dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
26882fa5cd67SKarl Rupp 
268916d9e3a6SLisandro Dalcin   pc->data                = jac;
26908695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
269116d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
269216d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
269316d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
269416d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
2695d7185485SAlex Lindsay   jac->hypre_type         = NULL;
269616d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
26979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
26989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
26999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
27009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
27019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
27029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
27039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2704be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
27059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
27069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
27079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
27086ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
27096ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
27109566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
27116ea7df73SStefano Zampini   #endif
27126ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
27139566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
27146ea7df73SStefano Zampini   #endif
27156ea7df73SStefano Zampini #endif
2716*5482091fSJunchao Zhang   PetscCall(PetscHYPREInitialize());
27173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
271816d9e3a6SLisandro Dalcin }
2719ebc551c0SBarry Smith 
2720ebc551c0SBarry Smith typedef struct {
272168326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2722f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
27239e5bc791SBarry Smith 
27249e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
27254ddd07fcSJed Brown   PetscInt  its;
272673dcfd97SStefano Zampini   PetscReal tol;
27274ddd07fcSJed Brown   PetscInt  relax_type;
27284ddd07fcSJed Brown   PetscInt  rap_type;
27294ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
27304ddd07fcSJed Brown   PetscInt  max_levels;
27310be8cd64Sftrigaux   PetscInt  skip_relax;
27320be8cd64Sftrigaux   PetscBool print_statistics;
2733ebc551c0SBarry Smith } PC_PFMG;
2734ebc551c0SBarry Smith 
PCDestroy_PFMG(PC pc)2735ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_PFMG(PC pc)
2736d71ae5a4SJacob Faibussowitsch {
2737f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2738ebc551c0SBarry Smith 
2739ebc551c0SBarry Smith   PetscFunctionBegin;
2740a333fa2bSZach Atkins   if (ex->hsolver) PetscCallHYPRE(HYPRE_StructPFMGDestroy(ex->hsolver));
27419566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
27429566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
27433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2744ebc551c0SBarry Smith }
2745ebc551c0SBarry Smith 
27469e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
27479e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
27489e5bc791SBarry Smith 
PCView_PFMG(PC pc,PetscViewer viewer)2749ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2750d71ae5a4SJacob Faibussowitsch {
27519f196a02SMartin Diehl   PetscBool isascii;
2752f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2753ebc551c0SBarry Smith 
2754ebc551c0SBarry Smith   PetscFunctionBegin;
27559f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
27569f196a02SMartin Diehl   if (isascii) {
27579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
275863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
27619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
276263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
276363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
27640be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
27659e5bc791SBarry Smith   }
27663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2767ebc551c0SBarry Smith }
2768ebc551c0SBarry Smith 
PCSetFromOptions_PFMG(PC pc,PetscOptionItems PetscOptionsObject)2769ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems PetscOptionsObject)
2770d71ae5a4SJacob Faibussowitsch {
2771f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2772ebc551c0SBarry Smith 
2773ebc551c0SBarry Smith   PetscFunctionBegin;
2774d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
27750be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
27769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2777f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetMaxIter(ex->hsolver, (HYPRE_Int)ex->its));
27789566063dSJacob 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));
2779f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetNumPreRelax(ex->hsolver, (HYPRE_Int)ex->num_pre_relax));
27809566063dSJacob 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));
2781f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetNumPostRelax(ex->hsolver, (HYPRE_Int)ex->num_post_relax));
27829e5bc791SBarry Smith 
27839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2784f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetMaxLevels(ex->hsolver, (HYPRE_Int)ex->max_levels));
27853b46a515SGlenn Hammond 
27869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2787a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetTol(ex->hsolver, ex->tol));
2788dd39110bSPierre 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));
2789f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetRelaxType(ex->hsolver, (HYPRE_Int)ex->relax_type));
2790dd39110bSPierre 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));
2791f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetRAPType(ex->hsolver, (HYPRE_Int)ex->rap_type));
27920be8cd64Sftrigaux   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));
2793f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetSkipRelax(ex->hsolver, (HYPRE_Int)ex->skip_relax));
2794d0609cedSBarry Smith   PetscOptionsHeadEnd();
27953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2796ebc551c0SBarry Smith }
2797ebc551c0SBarry Smith 
PCApply_PFMG(PC pc,Vec x,Vec y)2798ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2799d71ae5a4SJacob Faibussowitsch {
2800f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2801d9ca1df4SBarry Smith   PetscScalar       *yy;
2802d9ca1df4SBarry Smith   const PetscScalar *xx;
28034ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
28042cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2805f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
2806f91d8e95SBarry Smith 
2807f91d8e95SBarry Smith   PetscFunctionBegin;
28089566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28099566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28102cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2811f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2812f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2813f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
28142cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
28152cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
28162cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
28172cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
28182cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
28192cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2820f91d8e95SBarry Smith 
2821f91d8e95SBarry Smith   /* copy x values over to hypre */
2822a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetConstantValues(mx->hb, 0.0));
28239566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2824a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetBoxValues(mx->hb, hlower, hupper, (HYPRE_Complex *)xx));
28259566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2826a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(mx->hb));
2827a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSolve(ex->hsolver, mx->hmat, mx->hb, mx->hx));
2828f91d8e95SBarry Smith 
2829f91d8e95SBarry Smith   /* copy solution values back to PETSc */
28309566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2831a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorGetBoxValues(mx->hx, hlower, hupper, (HYPRE_Complex *)yy));
28329566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
28333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2834f91d8e95SBarry Smith }
2835f91d8e95SBarry Smith 
PCApplyRichardson_PFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt * outits,PCRichardsonConvergedReason * reason)2836d71ae5a4SJacob 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)
2837d71ae5a4SJacob Faibussowitsch {
28389e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
28392cf14000SStefano Zampini   HYPRE_Int oits;
28409e5bc791SBarry Smith 
28419e5bc791SBarry Smith   PetscFunctionBegin;
28429566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2843f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetMaxIter(jac->hsolver, (HYPRE_Int)(its * jac->its)));
2844a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetTol(jac->hsolver, rtol));
28459e5bc791SBarry Smith 
28469566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2847a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGGetNumIterations(jac->hsolver, &oits));
28489e5bc791SBarry Smith   *outits = oits;
28499e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
28509e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2851a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetTol(jac->hsolver, jac->tol));
2852f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetMaxIter(jac->hsolver, (HYPRE_Int)jac->its));
28533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28549e5bc791SBarry Smith }
28559e5bc791SBarry Smith 
PCSetUp_PFMG(PC pc)2856ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_PFMG(PC pc)
2857d71ae5a4SJacob Faibussowitsch {
28583a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
2859f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
2860ace3abfcSBarry Smith   PetscBool        flg;
28613a32d3dbSGlenn Hammond 
28623a32d3dbSGlenn Hammond   PetscFunctionBegin;
28639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
286428b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
28653a32d3dbSGlenn Hammond 
28663a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2867a333fa2bSZach Atkins   if (ex->hsolver) PetscCallHYPRE(HYPRE_StructPFMGDestroy(ex->hsolver));
2868a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGCreate(ex->hcomm, &ex->hsolver));
28690be8cd64Sftrigaux 
28700be8cd64Sftrigaux   // Print Hypre statistics about the solve process
2871a333fa2bSZach Atkins   if (ex->print_statistics) PetscCallHYPRE(HYPRE_StructPFMGSetPrintLevel(ex->hsolver, 3));
28720be8cd64Sftrigaux 
28730be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
2874f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetMaxIter(ex->hsolver, (HYPRE_Int)ex->its));
2875f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetNumPreRelax(ex->hsolver, (HYPRE_Int)ex->num_pre_relax));
2876f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetNumPostRelax(ex->hsolver, (HYPRE_Int)ex->num_post_relax));
2877f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetMaxLevels(ex->hsolver, (HYPRE_Int)ex->max_levels));
2878a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetTol(ex->hsolver, ex->tol));
2879f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetRelaxType(ex->hsolver, (HYPRE_Int)ex->relax_type));
2880f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetRAPType(ex->hsolver, (HYPRE_Int)ex->rap_type));
28810be8cd64Sftrigaux 
2882a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetup(ex->hsolver, mx->hmat, mx->hb, mx->hx));
2883a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGSetZeroGuess(ex->hsolver));
28843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28853a32d3dbSGlenn Hammond }
28863a32d3dbSGlenn Hammond 
2887ebc551c0SBarry Smith /*MC
2888ebc551c0SBarry Smith   PCPFMG - the hypre PFMG multigrid solver
2889ebc551c0SBarry Smith 
2890f1580f4eSBarry Smith   Options Database Keys:
289167b8a455SSatish Balay + -pc_pfmg_its <its>              - number of iterations of PFMG to use as preconditioner
289267b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps>  - number of smoothing steps before coarse grid solve
289367b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
289467b8a455SSatish Balay . -pc_pfmg_tol <tol>              - tolerance of PFMG
28959e5bc791SBarry 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
28960be8cd64Sftrigaux . -pc_pfmg_rap_type               - type of coarse matrix generation, one of Galerkin,non-Galerkin
2897f1580f4eSBarry Smith - -pc_pfmg_skip_relax             - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2898f1580f4eSBarry Smith                                     when the underlying problem is isotropic, one of 0,1
2899f1580f4eSBarry Smith 
2900f1580f4eSBarry Smith   Level: advanced
2901f91d8e95SBarry Smith 
290295452b02SPatrick Sanan   Notes:
290395452b02SPatrick Sanan   This is for CELL-centered descretizations
29049e5bc791SBarry Smith 
2905f1580f4eSBarry Smith   See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
29069e5bc791SBarry Smith 
2907f1580f4eSBarry Smith   See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2908f1580f4eSBarry Smith 
2909f1580f4eSBarry Smith   This must be used with the `MATHYPRESTRUCT` matrix type.
2910f1580f4eSBarry Smith 
2911f1580f4eSBarry Smith   This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2912f1580f4eSBarry Smith 
2913562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2914ebc551c0SBarry Smith M*/
2915ebc551c0SBarry Smith 
PCCreate_PFMG(PC pc)2916d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2917d71ae5a4SJacob Faibussowitsch {
2918ebc551c0SBarry Smith   PC_PFMG *ex;
2919ebc551c0SBarry Smith 
2920ebc551c0SBarry Smith   PetscFunctionBegin;
29219371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
292268326731SBarry Smith   pc->data = ex;
2923ebc551c0SBarry Smith 
29249e5bc791SBarry Smith   ex->its              = 1;
29259e5bc791SBarry Smith   ex->tol              = 1.e-8;
29269e5bc791SBarry Smith   ex->relax_type       = 1;
29279e5bc791SBarry Smith   ex->rap_type         = 0;
29289e5bc791SBarry Smith   ex->num_pre_relax    = 1;
29299e5bc791SBarry Smith   ex->num_post_relax   = 1;
29303b46a515SGlenn Hammond   ex->max_levels       = 0;
29310be8cd64Sftrigaux   ex->skip_relax       = 0;
29320be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
29339e5bc791SBarry Smith 
2934ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2935ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2936ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2937f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
29389e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
293968326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
29402fa5cd67SKarl Rupp 
29419566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2942*5482091fSJunchao Zhang   PetscCall(PetscHYPREInitialize());
2943a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructPFMGCreate(ex->hcomm, &ex->hsolver));
29443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2945ebc551c0SBarry Smith }
2946d851a50bSGlenn Hammond 
2947d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2948d851a50bSGlenn Hammond typedef struct {
2949d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2950d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2951d851a50bSGlenn Hammond 
2952d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
29534ddd07fcSJed Brown   PetscInt  its;
295473dcfd97SStefano Zampini   PetscReal tol;
29554ddd07fcSJed Brown   PetscInt  relax_type;
29564ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
2957d851a50bSGlenn Hammond } PC_SysPFMG;
2958d851a50bSGlenn Hammond 
PCDestroy_SysPFMG(PC pc)2959ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SysPFMG(PC pc)
2960d71ae5a4SJacob Faibussowitsch {
2961d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2962d851a50bSGlenn Hammond 
2963d851a50bSGlenn Hammond   PetscFunctionBegin;
2964a333fa2bSZach Atkins   if (ex->ss_solver) PetscCallHYPRE(HYPRE_SStructSysPFMGDestroy(ex->ss_solver));
29659566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29669566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
29673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2968d851a50bSGlenn Hammond }
2969d851a50bSGlenn Hammond 
2970d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2971d851a50bSGlenn Hammond 
PCView_SysPFMG(PC pc,PetscViewer viewer)2972ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2973d71ae5a4SJacob Faibussowitsch {
29749f196a02SMartin Diehl   PetscBool   isascii;
2975d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2976d851a50bSGlenn Hammond 
2977d851a50bSGlenn Hammond   PetscFunctionBegin;
29789f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
29799f196a02SMartin Diehl   if (isascii) {
29809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
298163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
29829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
29839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
298463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2985d851a50bSGlenn Hammond   }
29863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2987d851a50bSGlenn Hammond }
2988d851a50bSGlenn Hammond 
PCSetFromOptions_SysPFMG(PC pc,PetscOptionItems PetscOptionsObject)2989ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems PetscOptionsObject)
2990d71ae5a4SJacob Faibussowitsch {
2991d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2992ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2993d851a50bSGlenn Hammond 
2994d851a50bSGlenn Hammond   PetscFunctionBegin;
2995d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
29969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
2997a333fa2bSZach Atkins   if (flg) PetscCallHYPRE(HYPRE_SStructSysPFMGSetPrintLevel(ex->ss_solver, 3));
29989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2999f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetMaxIter(ex->ss_solver, (HYPRE_Int)ex->its));
30009566063dSJacob 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));
3001f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetNumPreRelax(ex->ss_solver, (HYPRE_Int)ex->num_pre_relax));
30029566063dSJacob 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));
3003f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetNumPostRelax(ex->ss_solver, (HYPRE_Int)ex->num_post_relax));
3004d851a50bSGlenn Hammond 
30059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
3006a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetTol(ex->ss_solver, ex->tol));
3007dd39110bSPierre 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));
3008f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetRelaxType(ex->ss_solver, (HYPRE_Int)ex->relax_type));
3009d0609cedSBarry Smith   PetscOptionsHeadEnd();
30103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3011d851a50bSGlenn Hammond }
3012d851a50bSGlenn Hammond 
PCApply_SysPFMG(PC pc,Vec x,Vec y)3013ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
3014d71ae5a4SJacob Faibussowitsch {
3015d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
3016d9ca1df4SBarry Smith   PetscScalar       *yy;
3017d9ca1df4SBarry Smith   const PetscScalar *xx;
30184ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
30192cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
3020f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)pc->pmat->data;
30214ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
30224ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
3023f2f41e48SZach Atkins   HYPRE_Int          part     = 0;
30244ddd07fcSJed Brown   PetscInt           size;
30254ddd07fcSJed Brown   PetscInt           i;
3026d851a50bSGlenn Hammond 
3027d851a50bSGlenn Hammond   PetscFunctionBegin;
30289566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
30299566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
30302cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
3031d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
3032d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
3033d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
30342cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
30352cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
30362cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
30372cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
30382cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
30392cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
3040d851a50bSGlenn Hammond 
3041d851a50bSGlenn Hammond   size = 1;
30422fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
30432fa5cd67SKarl Rupp 
3044d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
3045d851a50bSGlenn Hammond   if (ordering) {
3046a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorSetConstantValues(mx->ss_b, 0.0));
30479566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3048f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorSetBoxValues(mx->ss_b, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(xx + (size * i))));
30499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3050a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorAssemble(mx->ss_b));
3051a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixMatvec(1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x));
3052a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructSysPFMGSolve(ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x));
3053d851a50bSGlenn Hammond 
3054d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30559566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3056f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorGetBoxValues(mx->ss_x, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(yy + (size * i))));
30579566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
3058a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
3059d851a50bSGlenn Hammond     PetscScalar *z;
30604ddd07fcSJed Brown     PetscInt     j, k;
3061d851a50bSGlenn Hammond 
30629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
3063a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorSetConstantValues(mx->ss_b, 0.0));
30649566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
3065d851a50bSGlenn Hammond 
3066d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
3067d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3068d851a50bSGlenn Hammond       k = i * nvars;
30692fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
3070d851a50bSGlenn Hammond     }
3071f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorSetBoxValues(mx->ss_b, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(z + (size * i))));
30729566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
3073a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorAssemble(mx->ss_b));
3074a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructSysPFMGSolve(ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x));
3075d851a50bSGlenn Hammond 
3076d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
30779566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
3078f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorGetBoxValues(mx->ss_x, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(z + (size * i))));
3079d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
3080d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
3081d851a50bSGlenn Hammond       k = i * nvars;
30822fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
3083d851a50bSGlenn Hammond     }
30849566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
30859566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
3086d851a50bSGlenn Hammond   }
30873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3088d851a50bSGlenn Hammond }
3089d851a50bSGlenn Hammond 
PCApplyRichardson_SysPFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt * outits,PCRichardsonConvergedReason * reason)3090d71ae5a4SJacob 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)
3091d71ae5a4SJacob Faibussowitsch {
3092d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
30932cf14000SStefano Zampini   HYPRE_Int   oits;
3094d851a50bSGlenn Hammond 
3095d851a50bSGlenn Hammond   PetscFunctionBegin;
30969566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
3097f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetMaxIter(jac->ss_solver, (HYPRE_Int)(its * jac->its)));
3098a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetTol(jac->ss_solver, rtol));
30999566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
3100a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGGetNumIterations(jac->ss_solver, &oits));
3101d851a50bSGlenn Hammond   *outits = oits;
3102d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
3103d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
3104a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetTol(jac->ss_solver, jac->tol));
3105f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetMaxIter(jac->ss_solver, (HYPRE_Int)jac->its));
31063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3107d851a50bSGlenn Hammond }
3108d851a50bSGlenn Hammond 
PCSetUp_SysPFMG(PC pc)3109ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SysPFMG(PC pc)
3110d71ae5a4SJacob Faibussowitsch {
3111d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
3112f4f49eeaSPierre Jolivet   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)pc->pmat->data;
3113ace3abfcSBarry Smith   PetscBool         flg;
3114d851a50bSGlenn Hammond 
3115d851a50bSGlenn Hammond   PetscFunctionBegin;
31169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
311728b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
3118d851a50bSGlenn Hammond 
3119d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
3120a333fa2bSZach Atkins   if (ex->ss_solver) PetscCallHYPRE(HYPRE_SStructSysPFMGDestroy(ex->ss_solver));
3121a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGCreate(ex->hcomm, &ex->ss_solver));
3122a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetZeroGuess(ex->ss_solver));
3123a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGSetup(ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x));
31243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3125d851a50bSGlenn Hammond }
3126d851a50bSGlenn Hammond 
3127d851a50bSGlenn Hammond /*MC
3128f1580f4eSBarry Smith    PCSYSPFMG - the hypre SysPFMG multigrid solver
3129d851a50bSGlenn Hammond 
3130d851a50bSGlenn Hammond    Level: advanced
3131d851a50bSGlenn Hammond 
3132f1580f4eSBarry Smith    Options Database Keys:
313367b8a455SSatish Balay + -pc_syspfmg_its <its>                                           - number of iterations of SysPFMG to use as preconditioner
313467b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps>                               - number of smoothing steps before coarse grid
313567b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps>                              - number of smoothing steps after coarse grid
313667b8a455SSatish Balay . -pc_syspfmg_tol <tol>                                           - tolerance of SysPFMG
313767b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
3138d851a50bSGlenn Hammond 
313995452b02SPatrick Sanan    Notes:
3140f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
3141f1580f4eSBarry Smith 
3142f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
3143f1580f4eSBarry Smith 
314495452b02SPatrick Sanan    This is for CELL-centered descretizations
3145d851a50bSGlenn Hammond 
3146f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
3147d851a50bSGlenn Hammond 
3148f1580f4eSBarry 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`.
3149f1580f4eSBarry Smith 
3150562efe2eSBarry Smith .seealso: [](ch_ksp), `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
3151d851a50bSGlenn Hammond M*/
3152d851a50bSGlenn Hammond 
PCCreate_SysPFMG(PC pc)3153d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
3154d71ae5a4SJacob Faibussowitsch {
3155d851a50bSGlenn Hammond   PC_SysPFMG *ex;
3156d851a50bSGlenn Hammond 
3157d851a50bSGlenn Hammond   PetscFunctionBegin;
31589371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
3159d851a50bSGlenn Hammond   pc->data = ex;
3160d851a50bSGlenn Hammond 
3161d851a50bSGlenn Hammond   ex->its            = 1;
3162d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
3163d851a50bSGlenn Hammond   ex->relax_type     = 1;
3164d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
3165d851a50bSGlenn Hammond   ex->num_post_relax = 1;
3166d851a50bSGlenn Hammond 
3167d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
3168d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
3169d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
3170d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
3171d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
3172d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
31732fa5cd67SKarl Rupp 
31749566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3175*5482091fSJunchao Zhang   PetscCall(PetscHYPREInitialize());
3176a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructSysPFMGCreate(ex->hcomm, &ex->ss_solver));
31773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3178d851a50bSGlenn Hammond }
31791c188c59Sftrigaux 
3180f1580f4eSBarry Smith /* PC SMG */
31811c188c59Sftrigaux typedef struct {
31821c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
31831c188c59Sftrigaux   HYPRE_StructSolver hsolver;
31841c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
318573dcfd97SStefano Zampini   PetscReal          tol;
31861c188c59Sftrigaux   PetscBool          print_statistics;
31871c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
31881c188c59Sftrigaux } PC_SMG;
31891c188c59Sftrigaux 
PCDestroy_SMG(PC pc)3190ba38deedSJacob Faibussowitsch static PetscErrorCode PCDestroy_SMG(PC pc)
3191d71ae5a4SJacob Faibussowitsch {
31921c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
31931c188c59Sftrigaux 
31941c188c59Sftrigaux   PetscFunctionBegin;
3195a333fa2bSZach Atkins   if (ex->hsolver) PetscCallHYPRE(HYPRE_StructSMGDestroy(ex->hsolver));
31961c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
31971c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
31983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31991c188c59Sftrigaux }
32001c188c59Sftrigaux 
PCView_SMG(PC pc,PetscViewer viewer)3201ba38deedSJacob Faibussowitsch static PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
3202d71ae5a4SJacob Faibussowitsch {
32039f196a02SMartin Diehl   PetscBool isascii;
32041c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
32051c188c59Sftrigaux 
32061c188c59Sftrigaux   PetscFunctionBegin;
32079f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
32089f196a02SMartin Diehl   if (isascii) {
32091c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
32101c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
32111c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
32121c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
32131c188c59Sftrigaux   }
32143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32151c188c59Sftrigaux }
32161c188c59Sftrigaux 
PCSetFromOptions_SMG(PC pc,PetscOptionItems PetscOptionsObject)3217ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems PetscOptionsObject)
3218d71ae5a4SJacob Faibussowitsch {
32191c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
32201c188c59Sftrigaux 
32211c188c59Sftrigaux   PetscFunctionBegin;
32221c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
32231c188c59Sftrigaux 
32241c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
32251c188c59Sftrigaux   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));
32261c188c59Sftrigaux   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));
32271c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
32281c188c59Sftrigaux 
32291c188c59Sftrigaux   PetscOptionsHeadEnd();
32303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32311c188c59Sftrigaux }
32321c188c59Sftrigaux 
PCApply_SMG(PC pc,Vec x,Vec y)3233ba38deedSJacob Faibussowitsch static PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
3234d71ae5a4SJacob Faibussowitsch {
32351c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
32361c188c59Sftrigaux   PetscScalar       *yy;
32371c188c59Sftrigaux   const PetscScalar *xx;
32381c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
32391c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
3240f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)pc->pmat->data;
32411c188c59Sftrigaux 
32421c188c59Sftrigaux   PetscFunctionBegin;
32431c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
32441c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
32451c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
32461c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
32471c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
32481c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
32491c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
32501c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
32511c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
32521c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
32531c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
32541c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
32551c188c59Sftrigaux 
32561c188c59Sftrigaux   /* copy x values over to hypre */
3257a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetConstantValues(mx->hb, 0.0));
32581c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
3259a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetBoxValues(mx->hb, hlower, hupper, (HYPRE_Complex *)xx));
32601c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
3261a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(mx->hb));
3262a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSolve(ex->hsolver, mx->hmat, mx->hb, mx->hx));
32631c188c59Sftrigaux 
32641c188c59Sftrigaux   /* copy solution values back to PETSc */
32651c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
3266a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorGetBoxValues(mx->hx, hlower, hupper, (HYPRE_Complex *)yy));
32671c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
32683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32691c188c59Sftrigaux }
32701c188c59Sftrigaux 
PCApplyRichardson_SMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt * outits,PCRichardsonConvergedReason * reason)3271d71ae5a4SJacob 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)
3272d71ae5a4SJacob Faibussowitsch {
32731c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
32741c188c59Sftrigaux   HYPRE_Int oits;
32751c188c59Sftrigaux 
32761c188c59Sftrigaux   PetscFunctionBegin;
32771c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
3278f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetMaxIter(jac->hsolver, (HYPRE_Int)(its * jac->its)));
3279a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetTol(jac->hsolver, rtol));
32801c188c59Sftrigaux 
32811c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
3282a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGGetNumIterations(jac->hsolver, &oits));
32831c188c59Sftrigaux   *outits = oits;
32841c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
32851c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
3286a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetTol(jac->hsolver, jac->tol));
3287f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetMaxIter(jac->hsolver, (HYPRE_Int)jac->its));
32883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32891c188c59Sftrigaux }
32901c188c59Sftrigaux 
PCSetUp_SMG(PC pc)3291ba38deedSJacob Faibussowitsch static PetscErrorCode PCSetUp_SMG(PC pc)
3292d71ae5a4SJacob Faibussowitsch {
32931c188c59Sftrigaux   PetscInt         i, dim;
32941c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
3295f4f49eeaSPierre Jolivet   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)pc->pmat->data;
32961c188c59Sftrigaux   PetscBool        flg;
32971c188c59Sftrigaux   DMBoundaryType   p[3];
32981c188c59Sftrigaux   PetscInt         M[3];
32991c188c59Sftrigaux 
33001c188c59Sftrigaux   PetscFunctionBegin;
33011c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
33021c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
33031c188c59Sftrigaux 
33041c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
33051c188c59Sftrigaux   // Check if power of 2 in periodic directions
33061c188c59Sftrigaux   for (i = 0; i < dim; i++) {
3307966bd95aSPierre Jolivet     PetscCheck((M[i] & (M[i] - 1)) == 0 || p[i] != DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "With SMG, the number of points in a periodic direction must be a power of 2, but is here %" PetscInt_FMT ".", M[i]);
33081c188c59Sftrigaux   }
33091c188c59Sftrigaux 
33101c188c59Sftrigaux   /* create the hypre solver object and set its information */
3311a333fa2bSZach Atkins   if (ex->hsolver) PetscCallHYPRE(HYPRE_StructSMGDestroy(ex->hsolver));
3312a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGCreate(ex->hcomm, &ex->hsolver));
33131c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
3314f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetMaxIter(ex->hsolver, (HYPRE_Int)ex->its));
3315f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetNumPreRelax(ex->hsolver, (HYPRE_Int)ex->num_pre_relax));
3316f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetNumPostRelax(ex->hsolver, (HYPRE_Int)ex->num_post_relax));
3317a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetTol(ex->hsolver, ex->tol));
33181c188c59Sftrigaux 
3319a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetup(ex->hsolver, mx->hmat, mx->hb, mx->hx));
3320a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGSetZeroGuess(ex->hsolver));
33213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33221c188c59Sftrigaux }
33231c188c59Sftrigaux 
33241c188c59Sftrigaux /*MC
33255cb80ecdSBarry Smith   PCSMG - the hypre (structured grid) SMG multigrid solver
33261c188c59Sftrigaux 
33271c188c59Sftrigaux   Level: advanced
33281c188c59Sftrigaux 
3329f1580f4eSBarry Smith   Options Database Keys:
33305cb80ecdSBarry Smith + -pc_smg_its <its>              - number of iterations of SMG to use as preconditioner
33315cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps>  - number of smoothing steps before coarse grid
33325cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
33335cb80ecdSBarry Smith - -pc_smg_tol <tol>              - tolerance of SMG
33341c188c59Sftrigaux 
33351c188c59Sftrigaux   Notes:
33361c188c59Sftrigaux   This is for CELL-centered descretizations
33371c188c59Sftrigaux 
33385cb80ecdSBarry Smith   This must be used with the `MATHYPRESTRUCT` `MatType`.
33391c188c59Sftrigaux 
3340f1580f4eSBarry 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`.
3341f1580f4eSBarry Smith 
3342f1580f4eSBarry Smith   See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
3343f1580f4eSBarry Smith 
3344f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
33451c188c59Sftrigaux M*/
33461c188c59Sftrigaux 
PCCreate_SMG(PC pc)3347d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
3348d71ae5a4SJacob Faibussowitsch {
33491c188c59Sftrigaux   PC_SMG *ex;
33501c188c59Sftrigaux 
33511c188c59Sftrigaux   PetscFunctionBegin;
33529371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
33531c188c59Sftrigaux   pc->data = ex;
33541c188c59Sftrigaux 
33551c188c59Sftrigaux   ex->its            = 1;
33561c188c59Sftrigaux   ex->tol            = 1.e-8;
33571c188c59Sftrigaux   ex->num_pre_relax  = 1;
33581c188c59Sftrigaux   ex->num_post_relax = 1;
33591c188c59Sftrigaux 
33601c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
33611c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
33621c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
33631c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
33641c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
33651c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
33661c188c59Sftrigaux 
33671c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3368*5482091fSJunchao Zhang   PetscCall(PetscHYPREInitialize());
3369a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructSMGCreate(ex->hcomm, &ex->hsolver));
33703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33711c188c59Sftrigaux }
3372