xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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  = "
229371c9d4SSatish Balay                                     "{\\url{https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods}}\n}\n";
231f817a21SBarry Smith 
2416d9e3a6SLisandro Dalcin /*
2516d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
2616d9e3a6SLisandro Dalcin */
2716d9e3a6SLisandro Dalcin typedef struct {
2816d9e3a6SLisandro Dalcin   HYPRE_Solver hsolver;
2949a781f5SStefano Zampini   Mat          hpmat; /* MatHYPRE */
3016d9e3a6SLisandro Dalcin 
314ddd07fcSJed Brown   HYPRE_Int (*destroy)(HYPRE_Solver);
324ddd07fcSJed Brown   HYPRE_Int (*solve)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
334ddd07fcSJed Brown   HYPRE_Int (*setup)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
3416d9e3a6SLisandro Dalcin 
3516d9e3a6SLisandro Dalcin   MPI_Comm comm_hypre;
3616d9e3a6SLisandro Dalcin   char    *hypre_type;
3716d9e3a6SLisandro Dalcin 
3816d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
394ddd07fcSJed Brown   PetscInt  maxiter;
4039accc25SStefano Zampini   PetscReal tol;
4116d9e3a6SLisandro Dalcin 
4216d9e3a6SLisandro Dalcin   /* options for Pilut */
434ddd07fcSJed Brown   PetscInt factorrowsize;
4416d9e3a6SLisandro Dalcin 
4516d9e3a6SLisandro Dalcin   /* options for ParaSails */
464ddd07fcSJed Brown   PetscInt  nlevels;
478966356dSPierre Jolivet   PetscReal threshold;
4839accc25SStefano Zampini   PetscReal filter;
4939accc25SStefano Zampini   PetscReal loadbal;
504ddd07fcSJed Brown   PetscInt  logging;
514ddd07fcSJed Brown   PetscInt  ruse;
524ddd07fcSJed Brown   PetscInt  symt;
5316d9e3a6SLisandro Dalcin 
5422b6d1caSBarry Smith   /* options for BoomerAMG */
55ace3abfcSBarry Smith   PetscBool printstatistics;
5616d9e3a6SLisandro Dalcin 
5716d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
584ddd07fcSJed Brown   PetscInt  cycletype;
594ddd07fcSJed Brown   PetscInt  maxlevels;
6039accc25SStefano Zampini   PetscReal strongthreshold;
6139accc25SStefano Zampini   PetscReal maxrowsum;
624ddd07fcSJed Brown   PetscInt  gridsweeps[3];
634ddd07fcSJed Brown   PetscInt  coarsentype;
644ddd07fcSJed Brown   PetscInt  measuretype;
656a251517SEike Mueller   PetscInt  smoothtype;
668131ecf7SEike Mueller   PetscInt  smoothnumlevels;
67ec64516dSEike Mueller   PetscInt  eu_level;         /* Number of levels for ILU(k) in Euclid */
6839accc25SStefano Zampini   PetscReal eu_droptolerance; /* Drop tolerance for ILU(k) in Euclid */
69ec64516dSEike Mueller   PetscInt  eu_bj;            /* Defines use of Block Jacobi ILU in Euclid */
704ddd07fcSJed Brown   PetscInt  relaxtype[3];
7139accc25SStefano Zampini   PetscReal relaxweight;
7239accc25SStefano Zampini   PetscReal outerrelaxweight;
734ddd07fcSJed Brown   PetscInt  relaxorder;
7439accc25SStefano Zampini   PetscReal truncfactor;
75ace3abfcSBarry Smith   PetscBool applyrichardson;
764ddd07fcSJed Brown   PetscInt  pmax;
774ddd07fcSJed Brown   PetscInt  interptype;
78589dcaf0SStefano Zampini   PetscInt  maxc;
79589dcaf0SStefano Zampini   PetscInt  minc;
80db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
81db6f9c32SMark Adams   char *spgemm_type; // this is a global hypre parameter but is closely associated with BoomerAMG
82db6f9c32SMark Adams #endif
836ea7df73SStefano Zampini   /* GPU */
846ea7df73SStefano Zampini   PetscBool keeptranspose;
856ea7df73SStefano Zampini   PetscInt  rap2;
866ea7df73SStefano Zampini   PetscInt  mod_rap2;
876ea7df73SStefano Zampini 
88589dcaf0SStefano Zampini   /* AIR */
89589dcaf0SStefano Zampini   PetscInt  Rtype;
90589dcaf0SStefano Zampini   PetscReal Rstrongthreshold;
91589dcaf0SStefano Zampini   PetscReal Rfilterthreshold;
92589dcaf0SStefano Zampini   PetscInt  Adroptype;
93589dcaf0SStefano Zampini   PetscReal Adroptol;
94589dcaf0SStefano Zampini 
954ddd07fcSJed Brown   PetscInt  agg_nl;
966ea7df73SStefano Zampini   PetscInt  agg_interptype;
974ddd07fcSJed Brown   PetscInt  agg_num_paths;
98ace3abfcSBarry Smith   PetscBool nodal_relax;
994ddd07fcSJed Brown   PetscInt  nodal_relax_levels;
1004cb006feSStefano Zampini 
1015272c319SBarry Smith   PetscInt  nodal_coarsening;
10222e51d31SStefano Zampini   PetscInt  nodal_coarsening_diag;
1035272c319SBarry Smith   PetscInt  vec_interp_variant;
10422e51d31SStefano Zampini   PetscInt  vec_interp_qmax;
10522e51d31SStefano Zampini   PetscBool vec_interp_smooth;
10622e51d31SStefano Zampini   PetscInt  interp_refine;
10722e51d31SStefano Zampini 
1086ea7df73SStefano Zampini   /* NearNullSpace support */
1096ea7df73SStefano Zampini   VecHYPRE_IJVector *hmnull;
1106ea7df73SStefano Zampini   HYPRE_ParVector   *phmnull;
1115272c319SBarry Smith   PetscInt           n_hmnull;
1125272c319SBarry Smith   Vec                hmnull_constant;
1135272c319SBarry Smith 
114863406b8SStefano Zampini   /* options for AS (Auxiliary Space preconditioners) */
115863406b8SStefano Zampini   PetscInt  as_print;
116863406b8SStefano Zampini   PetscInt  as_max_iter;
117863406b8SStefano Zampini   PetscReal as_tol;
118863406b8SStefano Zampini   PetscInt  as_relax_type;
119863406b8SStefano Zampini   PetscInt  as_relax_times;
120863406b8SStefano Zampini   PetscReal as_relax_weight;
121863406b8SStefano Zampini   PetscReal as_omega;
122863406b8SStefano 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) */
123863406b8SStefano Zampini   PetscReal as_amg_alpha_theta;   /* AMG strength for vector Poisson (AMS) or Curl problem (ADS) */
124863406b8SStefano 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) */
125863406b8SStefano Zampini   PetscReal as_amg_beta_theta;    /* AMG strength for scalar Poisson (AMS) or vector Poisson (ADS)  */
1264cb006feSStefano Zampini   PetscInt  ams_cycle_type;
127863406b8SStefano Zampini   PetscInt  ads_cycle_type;
1284cb006feSStefano Zampini 
1294cb006feSStefano Zampini   /* additional data */
1305ac14e1cSStefano Zampini   Mat G;             /* MatHYPRE */
1315ac14e1cSStefano Zampini   Mat C;             /* MatHYPRE */
1325ac14e1cSStefano Zampini   Mat alpha_Poisson; /* MatHYPRE */
1335ac14e1cSStefano Zampini   Mat beta_Poisson;  /* MatHYPRE */
1345ac14e1cSStefano Zampini 
1355ac14e1cSStefano Zampini   /* extra information for AMS */
1365ac14e1cSStefano Zampini   PetscInt          dim; /* geometrical dimension */
1376ea7df73SStefano Zampini   VecHYPRE_IJVector coords[3];
1386ea7df73SStefano Zampini   VecHYPRE_IJVector constants[3];
139be14dc20SKerry Key   VecHYPRE_IJVector interior;
1406bf688a0SCe Qin   Mat               RT_PiFull, RT_Pi[3];
1416bf688a0SCe Qin   Mat               ND_PiFull, ND_Pi[3];
1424cb006feSStefano Zampini   PetscBool         ams_beta_is_zero;
14323df4f25SStefano Zampini   PetscBool         ams_beta_is_zero_part;
14423df4f25SStefano Zampini   PetscInt          ams_proj_freq;
14516d9e3a6SLisandro Dalcin } PC_HYPRE;
14616d9e3a6SLisandro Dalcin 
1479371c9d4SSatish Balay PetscErrorCode PCHYPREGetSolver(PC pc, HYPRE_Solver *hsolver) {
148d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
149d2128fa2SBarry Smith 
150d2128fa2SBarry Smith   PetscFunctionBegin;
151d2128fa2SBarry Smith   *hsolver = jac->hsolver;
152d2128fa2SBarry Smith   PetscFunctionReturn(0);
153d2128fa2SBarry Smith }
15416d9e3a6SLisandro Dalcin 
155fd2dd295SFande Kong /*
1568a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1578a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1588a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
159fd2dd295SFande Kong */
1609371c9d4SSatish Balay static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[]) {
1618a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1628a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1638a2c336bSFande Kong   PetscInt             num_levels, l;
1648a2c336bSFande Kong   Mat                 *mattmp;
1658a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1668a2c336bSFande Kong 
1678a2c336bSFande Kong   PetscFunctionBegin;
1689566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1695f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1708a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1728a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1738a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1749566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1758a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1768a2c336bSFande Kong     A_array[l] = NULL;
1778a2c336bSFande Kong   }
1788a2c336bSFande Kong   *nlevels   = num_levels;
1798a2c336bSFande Kong   *operators = mattmp;
1808a2c336bSFande Kong   PetscFunctionReturn(0);
1818a2c336bSFande Kong }
1828a2c336bSFande Kong 
183fd2dd295SFande Kong /*
1848a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1858a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1868a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
187fd2dd295SFande Kong */
1889371c9d4SSatish Balay static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[]) {
1898a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1908a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1918a2c336bSFande Kong   PetscInt             num_levels, l;
1928a2c336bSFande Kong   Mat                 *mattmp;
1938a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1948a2c336bSFande Kong 
1958a2c336bSFande Kong   PetscFunctionBegin;
1969566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1975f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1988a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
2008a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
2018a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
2029566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
2038a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2048a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2058a2c336bSFande Kong   }
2068a2c336bSFande Kong   *nlevels        = num_levels;
2078a2c336bSFande Kong   *interpolations = mattmp;
2088a2c336bSFande Kong   PetscFunctionReturn(0);
2098a2c336bSFande Kong }
2108a2c336bSFande Kong 
211ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
2129371c9d4SSatish Balay static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc) {
213ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
214ce6a8a0dSJed Brown   PetscInt  i;
215ce6a8a0dSJed Brown 
2169d678128SJed Brown   PetscFunctionBegin;
217*48a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2189566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2199566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2219d678128SJed Brown   jac->n_hmnull = 0;
222ce6a8a0dSJed Brown   PetscFunctionReturn(0);
223ce6a8a0dSJed Brown }
224ce6a8a0dSJed Brown 
2259371c9d4SSatish Balay static PetscErrorCode PCSetUp_HYPRE(PC pc) {
22616d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
22749a781f5SStefano Zampini   Mat_HYPRE         *hjac;
22816d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
22916d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
23049a781f5SStefano Zampini   PetscBool          ishypre;
23116d9e3a6SLisandro Dalcin 
23216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
233*48a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2345f5c5b43SBarry Smith 
2359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
23649a781f5SStefano Zampini   if (!ishypre) {
2379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
2389566063dSJacob Faibussowitsch     PetscCall(MatConvert(pc->pmat, MATHYPRE, MAT_INITIAL_MATRIX, &jac->hpmat));
2399566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)jac->hpmat));
24049a781f5SStefano Zampini   } else {
2419566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
24349a781f5SStefano Zampini     jac->hpmat = pc->pmat;
24416d9e3a6SLisandro Dalcin   }
2456ea7df73SStefano Zampini   /* allow debug */
2469566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
24749a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2485f5c5b43SBarry Smith 
24916d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25016d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2515272c319SBarry Smith     MatNullSpace mnull;
2525272c319SBarry Smith     PetscBool    has_const;
25349a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2545272c319SBarry Smith     const Vec   *vecs;
2555272c319SBarry Smith 
2569566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
257792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2589566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2595272c319SBarry Smith     if (mnull) {
2609566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2619566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2629566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2645272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2659566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2669566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
267792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2685272c319SBarry Smith       }
2695272c319SBarry Smith       if (has_const) {
2709566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2719566063dSJacob Faibussowitsch         PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)jac->hmnull_constant));
2729566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2739566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2749566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2759566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
276792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2775272c319SBarry Smith         nvec++;
2785272c319SBarry Smith       }
279792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2805272c319SBarry Smith       jac->n_hmnull = nvec;
2815272c319SBarry Smith     }
2824cb006feSStefano Zampini   }
283863406b8SStefano Zampini 
2844cb006feSStefano Zampini   /* special case for AMS */
2854cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2865ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2875ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2886bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
2896bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the edge constant vectors via PCHYPRESetEdgeConstantVectors() or the interpolation matrix via PCHYPRESetInterpolations");
2906bf688a0SCe Qin     }
291*48a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2925ac14e1cSStefano Zampini     if (jac->constants[0]) {
2935ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
294792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
295792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
296*48a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
297792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
2985ac14e1cSStefano Zampini     }
2995ac14e1cSStefano Zampini     if (jac->coords[0]) {
3005ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3015ac14e1cSStefano Zampini       coords[0] = NULL;
3025ac14e1cSStefano Zampini       coords[1] = NULL;
3035ac14e1cSStefano Zampini       coords[2] = NULL;
304792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
305792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
306792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
307792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3085ac14e1cSStefano Zampini     }
3095f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3105ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
311792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
312792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3135ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3145ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
315792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
316792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3175ac14e1cSStefano Zampini     }
3185ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
319792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3205ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3215ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
323792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
324be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
325be14dc20SKerry Key       if (jac->interior) {
326be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
327be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
328be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
329be14dc20SKerry Key       } else {
330be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
331be14dc20SKerry Key       }
3325ac14e1cSStefano Zampini     }
3336bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3346bf688a0SCe Qin       PetscInt           i;
3356bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3366bf688a0SCe Qin       if (jac->ND_PiFull) {
3376bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
338792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3396bf688a0SCe Qin       } else {
3406bf688a0SCe Qin         nd_parcsrfull = NULL;
3416bf688a0SCe Qin       }
3426bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3436bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3446bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
345792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3466bf688a0SCe Qin         } else {
3476bf688a0SCe Qin           nd_parcsr[i] = NULL;
3486bf688a0SCe Qin         }
3496bf688a0SCe Qin       }
350792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3516bf688a0SCe Qin     }
3524cb006feSStefano Zampini   }
353863406b8SStefano Zampini   /* special case for ADS */
354863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3555ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3565ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3576bf688a0SCe 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])))) {
3586bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3599371c9d4SSatish 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");
3605f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3615f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3625ac14e1cSStefano Zampini     if (jac->coords[0]) {
3635ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3645ac14e1cSStefano Zampini       coords[0] = NULL;
3655ac14e1cSStefano Zampini       coords[1] = NULL;
3665ac14e1cSStefano Zampini       coords[2] = NULL;
367792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
368792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
369792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
370792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3715ac14e1cSStefano Zampini     }
3725ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
373792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
374792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3755ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
376792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
377792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3786bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3796bf688a0SCe Qin       PetscInt           i;
3806bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3816bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3826bf688a0SCe Qin       if (jac->RT_PiFull) {
3836bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
384792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3856bf688a0SCe Qin       } else {
3866bf688a0SCe Qin         rt_parcsrfull = NULL;
3876bf688a0SCe Qin       }
3886bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3896bf688a0SCe Qin         if (jac->RT_Pi[i]) {
3906bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
391792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3926bf688a0SCe Qin         } else {
3936bf688a0SCe Qin           rt_parcsr[i] = NULL;
3946bf688a0SCe Qin         }
3956bf688a0SCe Qin       }
3966bf688a0SCe Qin       if (jac->ND_PiFull) {
3976bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
398792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3996bf688a0SCe Qin       } else {
4006bf688a0SCe Qin         nd_parcsrfull = NULL;
4016bf688a0SCe Qin       }
4026bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4036bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4046bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
405792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4066bf688a0SCe Qin         } else {
4076bf688a0SCe Qin           nd_parcsr[i] = NULL;
4086bf688a0SCe Qin         }
4096bf688a0SCe Qin       }
410792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetInterpolations, jac->hsolver, rt_parcsrfull, rt_parcsr[0], rt_parcsr[1], rt_parcsr[2], nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
4116bf688a0SCe Qin     }
412863406b8SStefano Zampini   }
413792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
414792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
415792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
416792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
41716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
41816d9e3a6SLisandro Dalcin }
41916d9e3a6SLisandro Dalcin 
4209371c9d4SSatish Balay static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x) {
42116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
42249a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
42316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
42416d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
42516d9e3a6SLisandro Dalcin 
42616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4279566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4289566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4299566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4309566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4319566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
432792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
433792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
434792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4359371c9d4SSatish Balay   PetscStackCallExternalVoid(
4369371c9d4SSatish Balay     "Hypre solve", do {
4375f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4385f80ce2aSJacob Faibussowitsch       if (hierr) {
4395f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
4405f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
4415f80ce2aSJacob Faibussowitsch       }
4425f80ce2aSJacob Faibussowitsch     } while (0));
44316d9e3a6SLisandro Dalcin 
444*48a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4459566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4469566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
44716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
44816d9e3a6SLisandro Dalcin }
44916d9e3a6SLisandro Dalcin 
4509371c9d4SSatish Balay static PetscErrorCode PCReset_HYPRE(PC pc) {
4518695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
4528695de01SBarry Smith 
4538695de01SBarry Smith   PetscFunctionBegin;
4549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
4559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
4569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
4579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
4589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
4599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
4609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
4619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
4629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
4639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
4649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
4659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
4669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
4679566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
4689566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
4699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
4709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
4719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
4729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
473be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
4749566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
4755ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
476be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
4775ac14e1cSStefano Zampini   jac->dim                   = 0;
4788695de01SBarry Smith   PetscFunctionReturn(0);
4798695de01SBarry Smith }
4808695de01SBarry Smith 
4819371c9d4SSatish Balay static PetscErrorCode PCDestroy_HYPRE(PC pc) {
48216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
48316d9e3a6SLisandro Dalcin 
48416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4859566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
486792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
4879566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
488db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
4899566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
490db6f9c32SMark Adams #endif
4919566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
4929566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
49316d9e3a6SLisandro Dalcin 
4949566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
4959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
4969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
4979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
4989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
4999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5022e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
503be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5082e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
50916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
51016d9e3a6SLisandro Dalcin }
51116d9e3a6SLisandro Dalcin 
51216d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
5139371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject) {
51416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
515ace3abfcSBarry Smith   PetscBool flag;
51616d9e3a6SLisandro Dalcin 
51716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
518d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
520792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
522792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
524792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
525d0609cedSBarry Smith   PetscOptionsHeadEnd();
52616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
52716d9e3a6SLisandro Dalcin }
52816d9e3a6SLisandro Dalcin 
5299371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer) {
53016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
531ace3abfcSBarry Smith   PetscBool iascii;
53216d9e3a6SLisandro Dalcin 
53316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
53516d9e3a6SLisandro Dalcin   if (iascii) {
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
53716d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
53863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
53916d9e3a6SLisandro Dalcin     } else {
5409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
54116d9e3a6SLisandro Dalcin     }
54216d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
5439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
54416d9e3a6SLisandro Dalcin     } else {
5459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
54616d9e3a6SLisandro Dalcin     }
54716d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
54863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
54916d9e3a6SLisandro Dalcin     } else {
5509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
55116d9e3a6SLisandro Dalcin     }
55216d9e3a6SLisandro Dalcin   }
55316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
55416d9e3a6SLisandro Dalcin }
55516d9e3a6SLisandro Dalcin 
55616d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
5579371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject) {
558db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5598bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
560db966c6cSHong Zhang 
561db966c6cSHong Zhang   PetscFunctionBegin;
562d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
5639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
564792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
5658bf83915SBarry Smith 
5669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
5678bf83915SBarry Smith   if (flag) {
5688bf83915SBarry Smith     PetscMPIInt size;
5698bf83915SBarry Smith 
5709566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
5717827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
572792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
5738bf83915SBarry Smith   }
5748bf83915SBarry Smith 
5759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
5768bf83915SBarry Smith   if (flag) {
5778bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
578792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
5798bf83915SBarry Smith   }
580d0609cedSBarry Smith   PetscOptionsHeadEnd();
581db966c6cSHong Zhang   PetscFunctionReturn(0);
582db966c6cSHong Zhang }
583db966c6cSHong Zhang 
5849371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer) {
585db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
586db966c6cSHong Zhang   PetscBool iascii;
587db966c6cSHong Zhang 
588db966c6cSHong Zhang   PetscFunctionBegin;
5899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
590db966c6cSHong Zhang   if (iascii) {
5919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
592db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
59363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
594db966c6cSHong Zhang     } else {
5959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
596db966c6cSHong Zhang     }
5979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
59863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
599db966c6cSHong Zhang   }
600db966c6cSHong Zhang   PetscFunctionReturn(0);
601db966c6cSHong Zhang }
602db966c6cSHong Zhang 
603db966c6cSHong Zhang /* --------------------------------------------------------------------------------------------*/
60416d9e3a6SLisandro Dalcin 
6059371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x) {
60616d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
60749a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
60816d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
60916d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
61016d9e3a6SLisandro Dalcin 
61116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6129566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6139566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6149566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6159566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
61616d9e3a6SLisandro Dalcin 
617792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
618792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
619792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
62016d9e3a6SLisandro Dalcin 
6219371c9d4SSatish Balay   PetscStackCallExternalVoid(
6229371c9d4SSatish Balay     "Hypre Transpose solve", do {
6235f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6245f80ce2aSJacob Faibussowitsch       if (hierr) {
62516d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6265f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
6275f80ce2aSJacob Faibussowitsch         hypre__global_error = 0;
6285f80ce2aSJacob Faibussowitsch       }
6295f80ce2aSJacob Faibussowitsch     } while (0));
63016d9e3a6SLisandro Dalcin 
6319566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6329566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
63316d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
63416d9e3a6SLisandro Dalcin }
63516d9e3a6SLisandro Dalcin 
6369371c9d4SSatish Balay static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[]) {
637db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
638db6f9c32SMark Adams   PetscBool flag;
639db6f9c32SMark Adams 
640db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
641db6f9c32SMark Adams   PetscFunctionBegin;
642db6f9c32SMark Adams   if (jac->spgemm_type) {
6439566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
64428b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
645db6f9c32SMark Adams     PetscFunctionReturn(0);
646db6f9c32SMark Adams   } else {
6479566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
648db6f9c32SMark Adams   }
6499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
650db6f9c32SMark Adams   if (flag) {
651792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
652db6f9c32SMark Adams     PetscFunctionReturn(0);
653db6f9c32SMark Adams   }
6549566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
655db6f9c32SMark Adams   if (flag) {
656792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
657db6f9c32SMark Adams     PetscFunctionReturn(0);
658db6f9c32SMark Adams   }
659db6f9c32SMark Adams   jac->spgemm_type = NULL;
66098921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEM type %s; Choices are cusparse, hypre", name);
661db6f9c32SMark Adams #endif
662db6f9c32SMark Adams }
663db6f9c32SMark Adams 
6649371c9d4SSatish Balay static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[]) {
665db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
666db6f9c32SMark Adams 
667db6f9c32SMark Adams   PetscFunctionBegin;
668db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
669db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
670db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
671db6f9c32SMark Adams #endif
672db6f9c32SMark Adams   PetscFunctionReturn(0);
673db6f9c32SMark Adams }
674db6f9c32SMark Adams 
67516d9e3a6SLisandro Dalcin static const char    *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
6760f1074feSSatish Balay static const char    *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
67716d9e3a6SLisandro Dalcin static const char    *HYPREBoomerAMGMeasureType[] = {"local", "global"};
67865de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
6796a251517SEike Mueller static const char    *HYPREBoomerAMGSmoothType[]  = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
6809371c9d4SSatish 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"};
6819371c9d4SSatish 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"};
6829371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject) {
68316d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
68422e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
685ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
68616d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
687589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
688db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
68916d9e3a6SLisandro Dalcin 
69016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
691d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
6929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
69316d9e3a6SLisandro Dalcin   if (flg) {
6944336a9eeSBarry Smith     jac->cycletype = indx + 1;
695792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
69616d9e3a6SLisandro Dalcin   }
6979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
69816d9e3a6SLisandro Dalcin   if (flg) {
69963a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
700792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
70116d9e3a6SLisandro Dalcin   }
7029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
70316d9e3a6SLisandro Dalcin   if (flg) {
70463a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
705792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
70616d9e3a6SLisandro Dalcin   }
7079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_tol", "Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)", "None", jac->tol, &jac->tol, &flg));
70816d9e3a6SLisandro Dalcin   if (flg) {
70908401ef6SPierre Jolivet     PetscCheck(jac->tol >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Tolerance %g must be greater than or equal to zero", (double)jac->tol);
710792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
71116d9e3a6SLisandro Dalcin   }
71222e51d31SStefano Zampini   bs = 1;
713*48a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
715*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
71616d9e3a6SLisandro Dalcin 
7179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
71816d9e3a6SLisandro Dalcin   if (flg) {
71908401ef6SPierre Jolivet     PetscCheck(jac->truncfactor >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Truncation factor %g must be great than or equal zero", (double)jac->truncfactor);
720792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
72116d9e3a6SLisandro Dalcin   }
72216d9e3a6SLisandro Dalcin 
7239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7240f1074feSSatish Balay   if (flg) {
72563a3b9bcSJacob Faibussowitsch     PetscCheck(jac->pmax >= 0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "P_max %" PetscInt_FMT " must be greater than or equal to zero", jac->pmax);
726792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7270f1074feSSatish Balay   }
7280f1074feSSatish Balay 
7299566063dSJacob 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));
730792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7310f1074feSSatish Balay 
7329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_agg_num_paths", "Number of paths for aggressive coarsening", "None", jac->agg_num_paths, &jac->agg_num_paths, &flg));
7330f1074feSSatish Balay   if (flg) {
73463a3b9bcSJacob Faibussowitsch     PetscCheck(jac->agg_num_paths >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of paths %" PetscInt_FMT " must be greater than or equal to 1", jac->agg_num_paths);
735792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7360f1074feSSatish Balay   }
7370f1074feSSatish Balay 
7389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
73916d9e3a6SLisandro Dalcin   if (flg) {
74008401ef6SPierre Jolivet     PetscCheck(jac->strongthreshold >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Strong threshold %g must be great than or equal zero", (double)jac->strongthreshold);
741792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
74216d9e3a6SLisandro Dalcin   }
7439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
74416d9e3a6SLisandro Dalcin   if (flg) {
74508401ef6SPierre Jolivet     PetscCheck(jac->maxrowsum >= 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Maximum row sum %g must be greater than zero", (double)jac->maxrowsum);
74608401ef6SPierre Jolivet     PetscCheck(jac->maxrowsum <= 1.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Maximum row sum %g must be less than or equal one", (double)jac->maxrowsum);
747792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
74816d9e3a6SLisandro Dalcin   }
74916d9e3a6SLisandro Dalcin 
75016d9e3a6SLisandro Dalcin   /* Grid sweeps */
7519566063dSJacob 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));
75216d9e3a6SLisandro Dalcin   if (flg) {
753792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
75416d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
75516d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
7560f1074feSSatish Balay     jac->gridsweeps[1] = indx;
7570f1074feSSatish Balay     /*defaults coarse to 1 */
7580f1074feSSatish Balay     jac->gridsweeps[2] = 1;
75916d9e3a6SLisandro Dalcin   }
7609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
761*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
7629566063dSJacob 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));
763*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
7649566063dSJacob 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));
765*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
7669566063dSJacob 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));
767*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
7689566063dSJacob 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));
769*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
7709566063dSJacob 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));
771*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
7729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
77316d9e3a6SLisandro Dalcin   if (flg) {
774792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
7750f1074feSSatish Balay     jac->gridsweeps[0] = indx;
77616d9e3a6SLisandro Dalcin   }
7779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
77816d9e3a6SLisandro Dalcin   if (flg) {
779792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
7800f1074feSSatish Balay     jac->gridsweeps[1] = indx;
78116d9e3a6SLisandro Dalcin   }
7829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
78316d9e3a6SLisandro Dalcin   if (flg) {
784792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
7850f1074feSSatish Balay     jac->gridsweeps[2] = indx;
78616d9e3a6SLisandro Dalcin   }
78716d9e3a6SLisandro Dalcin 
7886a251517SEike Mueller   /* Smooth type */
789dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
7906a251517SEike Mueller   if (flg) {
7916a251517SEike Mueller     jac->smoothtype = indx;
792792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
7938131ecf7SEike Mueller     jac->smoothnumlevels = 25;
794792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
7958131ecf7SEike Mueller   }
7968131ecf7SEike Mueller 
7978131ecf7SEike Mueller   /* Number of smoothing levels */
7989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
7998131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8008131ecf7SEike Mueller     jac->smoothnumlevels = indx;
801792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8026a251517SEike Mueller   }
8036a251517SEike Mueller 
8041810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8061810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8071810e44eSEike Mueller     jac->eu_level = indx;
808792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8091810e44eSEike Mueller   }
8101810e44eSEike Mueller 
8111810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8121810e44eSEike Mueller   double droptolerance;
8139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8141810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8151810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
816792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8171810e44eSEike Mueller   }
8181810e44eSEike Mueller 
8191810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8211810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8221810e44eSEike Mueller     jac->eu_bj = tmp_truth;
823792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8241810e44eSEike Mueller   }
8251810e44eSEike Mueller 
82616d9e3a6SLisandro Dalcin   /* Relax type */
827dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all", "Relax type for the up and down cycles", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), HYPREBoomerAMGRelaxType[6], &indx, &flg));
82816d9e3a6SLisandro Dalcin   if (flg) {
8290f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
830792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8310f1074feSSatish Balay     /* by default, coarse type set to 9 */
8320f1074feSSatish Balay     jac->relaxtype[2] = 9;
833792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
83416d9e3a6SLisandro Dalcin   }
835dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down", "Relax type for the down cycles", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), HYPREBoomerAMGRelaxType[6], &indx, &flg));
83616d9e3a6SLisandro Dalcin   if (flg) {
83716d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
838792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
83916d9e3a6SLisandro Dalcin   }
840dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up", "Relax type for the up cycles", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), HYPREBoomerAMGRelaxType[6], &indx, &flg));
84116d9e3a6SLisandro Dalcin   if (flg) {
8420f1074feSSatish Balay     jac->relaxtype[1] = indx;
843792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
84416d9e3a6SLisandro Dalcin   }
845dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse", "Relax type on coarse grid", "None", HYPREBoomerAMGRelaxType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGRelaxType), HYPREBoomerAMGRelaxType[9], &indx, &flg));
84616d9e3a6SLisandro Dalcin   if (flg) {
8470f1074feSSatish Balay     jac->relaxtype[2] = indx;
848792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
84916d9e3a6SLisandro Dalcin   }
85016d9e3a6SLisandro Dalcin 
85116d9e3a6SLisandro Dalcin   /* Relaxation Weight */
8529566063dSJacob 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));
85316d9e3a6SLisandro Dalcin   if (flg) {
854792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
85516d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
85616d9e3a6SLisandro Dalcin   }
85716d9e3a6SLisandro Dalcin 
85816d9e3a6SLisandro Dalcin   n         = 2;
85916d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
86116d9e3a6SLisandro Dalcin   if (flg) {
86216d9e3a6SLisandro Dalcin     if (n == 2) {
86316d9e3a6SLisandro Dalcin       indx = (int)PetscAbsReal(twodbl[1]);
864792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
86563a3b9bcSJacob Faibussowitsch     } else SETERRQ(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);
86616d9e3a6SLisandro Dalcin   }
86716d9e3a6SLisandro Dalcin 
86816d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
8699566063dSJacob 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));
87016d9e3a6SLisandro Dalcin   if (flg) {
871792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
87216d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
87316d9e3a6SLisandro Dalcin   }
87416d9e3a6SLisandro Dalcin 
87516d9e3a6SLisandro Dalcin   n         = 2;
87616d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
8779566063dSJacob 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));
87816d9e3a6SLisandro Dalcin   if (flg) {
87916d9e3a6SLisandro Dalcin     if (n == 2) {
88016d9e3a6SLisandro Dalcin       indx = (int)PetscAbsReal(twodbl[1]);
881792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
88263a3b9bcSJacob Faibussowitsch     } else SETERRQ(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);
88316d9e3a6SLisandro Dalcin   }
88416d9e3a6SLisandro Dalcin 
88516d9e3a6SLisandro Dalcin   /* the Relax Order */
8869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
88716d9e3a6SLisandro Dalcin 
8888afaa268SBarry Smith   if (flg && tmp_truth) {
88916d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
890792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
89116d9e3a6SLisandro Dalcin   }
892dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
89316d9e3a6SLisandro Dalcin   if (flg) {
89416d9e3a6SLisandro Dalcin     jac->measuretype = indx;
895792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
89616d9e3a6SLisandro Dalcin   }
8970f1074feSSatish Balay   /* update list length 3/07 */
898dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
89916d9e3a6SLisandro Dalcin   if (flg) {
90016d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
901792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
90216d9e3a6SLisandro Dalcin   }
9030f1074feSSatish Balay 
9049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
905*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
907*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
908db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
909db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
910dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_mg_galerkin_mat_product_algorithm", "Type of SpGEMM to use in hypre (only for now)", "PCMGGalerkinSetMatProductAlgorithm", PCHYPRESpgemmTypes, PETSC_STATIC_ARRAY_LENGTH(PCHYPRESpgemmTypes), PCHYPRESpgemmTypes[0], &indx, &flg));
911db6f9c32SMark Adams   if (!flg) indx = 0;
9129566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
913db6f9c32SMark Adams #endif
914589dcaf0SStefano Zampini   /* AIR */
915589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9169566063dSJacob 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));
917792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
918589dcaf0SStefano Zampini   if (jac->Rtype) {
919589dcaf0SStefano 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 */
920589dcaf0SStefano Zampini 
9219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
922792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
923589dcaf0SStefano Zampini 
9249566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
925792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
926589dcaf0SStefano Zampini 
9279566063dSJacob 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));
928792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
929589dcaf0SStefano Zampini 
9309566063dSJacob 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));
931792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
932589dcaf0SStefano Zampini   }
933589dcaf0SStefano Zampini #endif
934589dcaf0SStefano Zampini 
935ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
93663a3b9bcSJacob 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);
937ecae95adSPierre Jolivet #endif
938ecae95adSPierre Jolivet 
9390f1074feSSatish Balay   /* new 3/07 */
940dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
941589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
942589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
943792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
9440f1074feSSatish Balay   }
9450f1074feSSatish Balay 
9469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
94716d9e3a6SLisandro Dalcin   if (flg) {
948b96a4a96SBarry Smith     level = 3;
9499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
9502fa5cd67SKarl Rupp 
951b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
9532ae77aedSBarry Smith   }
9542ae77aedSBarry Smith 
9559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
9562ae77aedSBarry Smith   if (flg) {
957b96a4a96SBarry Smith     level = 3;
9589566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
9592fa5cd67SKarl Rupp 
960b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
961792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
96216d9e3a6SLisandro Dalcin   }
9638f87f92bSBarry Smith 
9649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
9658f87f92bSBarry Smith   if (flg && tmp_truth) {
9668f87f92bSBarry Smith     PetscInt tmp_int;
9679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
9688f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
969792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
970792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
971792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
972792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
9738f87f92bSBarry Smith   }
9748f87f92bSBarry Smith 
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
976792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
977589dcaf0SStefano Zampini 
978589dcaf0SStefano Zampini   /* options for ParaSails solvers */
979dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
980589dcaf0SStefano Zampini   if (flg) {
981589dcaf0SStefano Zampini     jac->symt = indx;
982792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
983589dcaf0SStefano Zampini   }
984589dcaf0SStefano Zampini 
985d0609cedSBarry Smith   PetscOptionsHeadEnd();
98616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
98716d9e3a6SLisandro Dalcin }
98816d9e3a6SLisandro Dalcin 
9899371c9d4SSatish Balay 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) {
99016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
9912cf14000SStefano Zampini   HYPRE_Int oits;
99216d9e3a6SLisandro Dalcin 
99316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
9949566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
995792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
996792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
99716d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
9989566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
99916d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1000792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10014d0a8057SBarry Smith   *outits = oits;
10024d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10034d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1004792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1005792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
100616d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
100716d9e3a6SLisandro Dalcin }
100816d9e3a6SLisandro Dalcin 
10099371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer) {
101016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1011ace3abfcSBarry Smith   PetscBool iascii;
101216d9e3a6SLisandro Dalcin 
101316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
101516d9e3a6SLisandro Dalcin   if (iascii) {
10169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
101863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
101963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
102363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
1024*48a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
102563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
102663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
10270f1074feSSatish Balay 
10289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
102916d9e3a6SLisandro Dalcin 
103063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
103163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
103263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
103316d9e3a6SLisandro Dalcin 
10349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
10359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
10369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
103716d9e3a6SLisandro Dalcin 
10389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
10399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
104016d9e3a6SLisandro Dalcin 
104116d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
10429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
104316d9e3a6SLisandro Dalcin     } else {
10449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
104516d9e3a6SLisandro Dalcin     }
10466a251517SEike Mueller     if (jac->smoothtype != -1) {
10479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
104863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
10497e352d70SEike Mueller     } else {
10509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
10511810e44eSEike Mueller     }
10521810e44eSEike Mueller     if (jac->smoothtype == 3) {
105363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
10549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
105563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
10566a251517SEike Mueller     }
10579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
10589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
10599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
1060*48a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
10615272c319SBarry Smith     if (jac->vec_interp_variant) {
106263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
106363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
10649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
10658f87f92bSBarry Smith     }
1066*48a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1067db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
10689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
1069db6f9c32SMark Adams #endif
1070589dcaf0SStefano Zampini     /* AIR */
1071589dcaf0SStefano Zampini     if (jac->Rtype) {
107263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
10739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
10749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
10759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
107663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1077589dcaf0SStefano Zampini     }
107816d9e3a6SLisandro Dalcin   }
107916d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
108016d9e3a6SLisandro Dalcin }
108116d9e3a6SLisandro Dalcin 
108216d9e3a6SLisandro Dalcin /* --------------------------------------------------------------------------------------------*/
10839371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject) {
108416d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
10854ddd07fcSJed Brown   PetscInt    indx;
1086ace3abfcSBarry Smith   PetscBool   flag;
108716d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
108816d9e3a6SLisandro Dalcin 
108916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1090d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
10919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
10929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1093792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
109416d9e3a6SLisandro Dalcin 
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1096792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
109716d9e3a6SLisandro Dalcin 
10989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1099792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
110016d9e3a6SLisandro Dalcin 
11019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1102792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
110316d9e3a6SLisandro Dalcin 
11049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1105792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
110616d9e3a6SLisandro Dalcin 
1107dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
110816d9e3a6SLisandro Dalcin   if (flag) {
110916d9e3a6SLisandro Dalcin     jac->symt = indx;
1110792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
111116d9e3a6SLisandro Dalcin   }
111216d9e3a6SLisandro Dalcin 
1113d0609cedSBarry Smith   PetscOptionsHeadEnd();
111416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
111516d9e3a6SLisandro Dalcin }
111616d9e3a6SLisandro Dalcin 
11179371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer) {
111816d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1119ace3abfcSBarry Smith   PetscBool   iascii;
1120feb237baSPierre Jolivet   const char *symt = 0;
112116d9e3a6SLisandro Dalcin 
112216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
112416d9e3a6SLisandro Dalcin   if (iascii) {
11259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
112663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
11279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
11289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
11299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
11309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
11319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
11322fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
11332fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
11342fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
113563a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
11369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
113716d9e3a6SLisandro Dalcin   }
113816d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
113916d9e3a6SLisandro Dalcin }
11404cb006feSStefano Zampini /* --------------------------------------------------------------------------------------------*/
11419371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject) {
11424cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11434cb006feSStefano Zampini   PetscInt  n;
11444cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
11454cb006feSStefano Zampini 
11464cb006feSStefano Zampini   PetscFunctionBegin;
1147d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
11489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1149792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
11509566063dSJacob 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));
1151792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
11529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1153792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1155792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
11569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
11579566063dSJacob 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));
11589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
11599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
1160*48a46eb9SPierre Jolivet   if (flag || flag2 || flag3 || flag4) PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
11619566063dSJacob 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));
11624cb006feSStefano Zampini   n = 5;
11639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
11644cb006feSStefano Zampini   if (flag || flag2) {
1165792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1166863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1167863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
11689371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1169a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
11704cb006feSStefano Zampini   }
11719566063dSJacob 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));
11724cb006feSStefano Zampini   n = 5;
11739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
11744cb006feSStefano Zampini   if (flag || flag2) {
1175792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1176863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1177863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
11789371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1179a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
11804cb006feSStefano Zampini   }
11819566063dSJacob 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));
118223df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1183792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
118423df4f25SStefano Zampini   }
1185d0609cedSBarry Smith   PetscOptionsHeadEnd();
11864cb006feSStefano Zampini   PetscFunctionReturn(0);
11874cb006feSStefano Zampini }
11884cb006feSStefano Zampini 
11899371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer) {
11904cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
11914cb006feSStefano Zampini   PetscBool iascii;
11924cb006feSStefano Zampini 
11934cb006feSStefano Zampini   PetscFunctionBegin;
11949566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
11954cb006feSStefano Zampini   if (iascii) {
11969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
119763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
119863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
119963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
120063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
120163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
120263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
120363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12044cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12064cb006feSStefano Zampini     } else {
12079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12084cb006feSStefano Zampini     }
120963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
121063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
121163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
121263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
121363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
121463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12154cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12164cb006feSStefano Zampini       if (jac->beta_Poisson) {
12179566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
12184cb006feSStefano Zampini       } else {
12199566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
12204cb006feSStefano Zampini       }
122163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
122263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
122363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
122463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
122563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
122663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
1227*48a46eb9SPierre 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));
122823df4f25SStefano Zampini     } else {
12299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
12304cb006feSStefano Zampini     }
12314cb006feSStefano Zampini   }
12324cb006feSStefano Zampini   PetscFunctionReturn(0);
12334cb006feSStefano Zampini }
12344cb006feSStefano Zampini 
12359371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject) {
1236863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1237863406b8SStefano Zampini   PetscInt  n;
1238863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1239863406b8SStefano Zampini 
1240863406b8SStefano Zampini   PetscFunctionBegin;
1241d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
12429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1243792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
12449566063dSJacob 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));
1245792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
12469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1247792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
12489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1249792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
12509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12519566063dSJacob 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));
12529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
1254*48a46eb9SPierre Jolivet   if (flag || flag2 || flag3 || flag4) PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
12559566063dSJacob 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));
1256863406b8SStefano Zampini   n = 5;
12579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
12589566063dSJacob 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));
1259863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1260792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1261863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1262863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1263863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
12649371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1265a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1266863406b8SStefano Zampini   }
12679566063dSJacob 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));
1268863406b8SStefano Zampini   n = 5;
12699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1270863406b8SStefano Zampini   if (flag || flag2) {
1271792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1272863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1273863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
12749371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1275a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1276863406b8SStefano Zampini   }
1277d0609cedSBarry Smith   PetscOptionsHeadEnd();
1278863406b8SStefano Zampini   PetscFunctionReturn(0);
1279863406b8SStefano Zampini }
1280863406b8SStefano Zampini 
12819371c9d4SSatish Balay static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer) {
1282863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1283863406b8SStefano Zampini   PetscBool iascii;
1284863406b8SStefano Zampini 
1285863406b8SStefano Zampini   PetscFunctionBegin;
12869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1287863406b8SStefano Zampini   if (iascii) {
12889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
128963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
129063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
129163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
129263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
129363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
129463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
129563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
129763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
129863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
129963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
130063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
130163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
130263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
130363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
130563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
130663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
130763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
130863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
130963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
131063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1311863406b8SStefano Zampini   }
1312863406b8SStefano Zampini   PetscFunctionReturn(0);
1313863406b8SStefano Zampini }
1314863406b8SStefano Zampini 
13159371c9d4SSatish Balay static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G) {
13164cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13175ac14e1cSStefano Zampini   PetscBool ishypre;
13184cb006feSStefano Zampini 
13194cb006feSStefano Zampini   PetscFunctionBegin;
13209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
13215ac14e1cSStefano Zampini   if (ishypre) {
13229566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
13239566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13245ac14e1cSStefano Zampini     jac->G = G;
13255ac14e1cSStefano Zampini   } else {
13269566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13279566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
13285ac14e1cSStefano Zampini   }
13294cb006feSStefano Zampini   PetscFunctionReturn(0);
13304cb006feSStefano Zampini }
13314cb006feSStefano Zampini 
13324cb006feSStefano Zampini /*@
13334cb006feSStefano Zampini  PCHYPRESetDiscreteGradient - Set discrete gradient matrix
13344cb006feSStefano Zampini 
13354cb006feSStefano Zampini    Collective on PC
13364cb006feSStefano Zampini 
13374cb006feSStefano Zampini    Input Parameters:
13384cb006feSStefano Zampini +  pc - the preconditioning context
13394cb006feSStefano Zampini -  G - the discrete gradient
13404cb006feSStefano Zampini 
13414cb006feSStefano Zampini    Level: intermediate
13424cb006feSStefano Zampini 
134395452b02SPatrick Sanan    Notes:
134495452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1345147403d9SBarry Smith 
1346863406b8SStefano Zampini     Each row of G has 2 nonzeros, with column indexes being the global indexes of edge's endpoints: matrix entries are +1 and -1 depending on edge orientation
13474cb006feSStefano Zampini 
1348db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteCurl()`
13494cb006feSStefano Zampini @*/
13509371c9d4SSatish Balay PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G) {
13514cb006feSStefano Zampini   PetscFunctionBegin;
13524cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
13534cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
13544cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1355cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
13564cb006feSStefano Zampini   PetscFunctionReturn(0);
13574cb006feSStefano Zampini }
13584cb006feSStefano Zampini 
13599371c9d4SSatish Balay static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C) {
1360863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13615ac14e1cSStefano Zampini   PetscBool ishypre;
1362863406b8SStefano Zampini 
1363863406b8SStefano Zampini   PetscFunctionBegin;
13649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
13655ac14e1cSStefano Zampini   if (ishypre) {
13669566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
13679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13685ac14e1cSStefano Zampini     jac->C = C;
13695ac14e1cSStefano Zampini   } else {
13709566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
13719566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
13725ac14e1cSStefano Zampini   }
1373863406b8SStefano Zampini   PetscFunctionReturn(0);
1374863406b8SStefano Zampini }
1375863406b8SStefano Zampini 
1376863406b8SStefano Zampini /*@
1377863406b8SStefano Zampini  PCHYPRESetDiscreteCurl - Set discrete curl matrix
1378863406b8SStefano Zampini 
1379863406b8SStefano Zampini    Collective on PC
1380863406b8SStefano Zampini 
1381863406b8SStefano Zampini    Input Parameters:
1382863406b8SStefano Zampini +  pc - the preconditioning context
1383863406b8SStefano Zampini -  C - the discrete curl
1384863406b8SStefano Zampini 
1385863406b8SStefano Zampini    Level: intermediate
1386863406b8SStefano Zampini 
138795452b02SPatrick Sanan    Notes:
138895452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1389147403d9SBarry Smith 
1390863406b8SStefano Zampini     Each row of G has as many nonzeros as the number of edges of a face, with column indexes being the global indexes of the corresponding edge: matrix entries are +1 and -1 depending on edge orientation with respect to the face orientation
1391863406b8SStefano Zampini 
1392db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteGradient()`
1393863406b8SStefano Zampini @*/
13949371c9d4SSatish Balay PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C) {
1395863406b8SStefano Zampini   PetscFunctionBegin;
1396863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1397863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1398863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1399cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
1400863406b8SStefano Zampini   PetscFunctionReturn(0);
1401863406b8SStefano Zampini }
1402863406b8SStefano Zampini 
14039371c9d4SSatish Balay static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[]) {
14046bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14056bf688a0SCe Qin   PetscBool ishypre;
14066bf688a0SCe Qin   PetscInt  i;
14076bf688a0SCe Qin   PetscFunctionBegin;
14086bf688a0SCe Qin 
14099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14116bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
14129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14146bf688a0SCe Qin   }
14156bf688a0SCe Qin 
14166bf688a0SCe Qin   jac->dim = dim;
14176bf688a0SCe Qin   if (RT_PiFull) {
14189566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
14196bf688a0SCe Qin     if (ishypre) {
14209566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
14216bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
14226bf688a0SCe Qin     } else {
14239566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
14246bf688a0SCe Qin     }
14256bf688a0SCe Qin   }
14266bf688a0SCe Qin   if (RT_Pi) {
14276bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14286bf688a0SCe Qin       if (RT_Pi[i]) {
14299566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
14306bf688a0SCe Qin         if (ishypre) {
14319566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
14326bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
14336bf688a0SCe Qin         } else {
14349566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
14356bf688a0SCe Qin         }
14366bf688a0SCe Qin       }
14376bf688a0SCe Qin     }
14386bf688a0SCe Qin   }
14396bf688a0SCe Qin   if (ND_PiFull) {
14409566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
14416bf688a0SCe Qin     if (ishypre) {
14429566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
14436bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
14446bf688a0SCe Qin     } else {
14459566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
14466bf688a0SCe Qin     }
14476bf688a0SCe Qin   }
14486bf688a0SCe Qin   if (ND_Pi) {
14496bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14506bf688a0SCe Qin       if (ND_Pi[i]) {
14519566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
14526bf688a0SCe Qin         if (ishypre) {
14539566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
14546bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
14556bf688a0SCe Qin         } else {
14569566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
14576bf688a0SCe Qin         }
14586bf688a0SCe Qin       }
14596bf688a0SCe Qin     }
14606bf688a0SCe Qin   }
14616bf688a0SCe Qin 
14626bf688a0SCe Qin   PetscFunctionReturn(0);
14636bf688a0SCe Qin }
14646bf688a0SCe Qin 
14656bf688a0SCe Qin /*@
14666bf688a0SCe Qin  PCHYPRESetInterpolations - Set interpolation matrices for AMS/ADS preconditioner
14676bf688a0SCe Qin 
14686bf688a0SCe Qin    Collective on PC
14696bf688a0SCe Qin 
14706bf688a0SCe Qin    Input Parameters:
14716bf688a0SCe Qin +  pc - the preconditioning context
14726bf688a0SCe Qin -  dim - the dimension of the problem, only used in AMS
14736bf688a0SCe Qin -  RT_PiFull - Raviart-Thomas interpolation matrix
14746bf688a0SCe Qin -  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
14756bf688a0SCe Qin -  ND_PiFull - Nedelec interpolation matrix
14766bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
14776bf688a0SCe Qin 
147895452b02SPatrick Sanan    Notes:
147995452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1480147403d9SBarry Smith 
14816bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1482147403d9SBarry Smith 
14836bf688a0SCe Qin    Level: intermediate
14846bf688a0SCe Qin 
14856bf688a0SCe Qin @*/
14869371c9d4SSatish Balay PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[]) {
14876bf688a0SCe Qin   PetscInt i;
14886bf688a0SCe Qin 
14896bf688a0SCe Qin   PetscFunctionBegin;
14906bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14916bf688a0SCe Qin   if (RT_PiFull) {
14926bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
14936bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
14946bf688a0SCe Qin   }
14956bf688a0SCe Qin   if (RT_Pi) {
14966bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
14976bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
14986bf688a0SCe Qin       if (RT_Pi[i]) {
14996bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
15006bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
15016bf688a0SCe Qin       }
15026bf688a0SCe Qin     }
15036bf688a0SCe Qin   }
15046bf688a0SCe Qin   if (ND_PiFull) {
15056bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
15066bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
15076bf688a0SCe Qin   }
15086bf688a0SCe Qin   if (ND_Pi) {
15096bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
15106bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15116bf688a0SCe Qin       if (ND_Pi[i]) {
15126bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
15136bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
15146bf688a0SCe Qin       }
15156bf688a0SCe Qin     }
15166bf688a0SCe Qin   }
1517cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
15186bf688a0SCe Qin   PetscFunctionReturn(0);
15196bf688a0SCe Qin }
15206bf688a0SCe Qin 
15219371c9d4SSatish Balay static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha) {
15224cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
15235ac14e1cSStefano Zampini   PetscBool ishypre;
15244cb006feSStefano Zampini 
15254cb006feSStefano Zampini   PetscFunctionBegin;
15269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
15275ac14e1cSStefano Zampini   if (ishypre) {
15285ac14e1cSStefano Zampini     if (isalpha) {
15299566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
15309566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15315ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
15325ac14e1cSStefano Zampini     } else {
15335ac14e1cSStefano Zampini       if (A) {
15349566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
15355ac14e1cSStefano Zampini       } else {
15365ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15375ac14e1cSStefano Zampini       }
15389566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
15395ac14e1cSStefano Zampini       jac->beta_Poisson = A;
15405ac14e1cSStefano Zampini     }
15415ac14e1cSStefano Zampini   } else {
15425ac14e1cSStefano Zampini     if (isalpha) {
15439566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
15449566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
15455ac14e1cSStefano Zampini     } else {
15465ac14e1cSStefano Zampini       if (A) {
15479566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15489566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
15495ac14e1cSStefano Zampini       } else {
15509566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
15515ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
15525ac14e1cSStefano Zampini       }
15535ac14e1cSStefano Zampini     }
15545ac14e1cSStefano Zampini   }
15554cb006feSStefano Zampini   PetscFunctionReturn(0);
15564cb006feSStefano Zampini }
15574cb006feSStefano Zampini 
15584cb006feSStefano Zampini /*@
15594cb006feSStefano Zampini  PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix
15604cb006feSStefano Zampini 
15614cb006feSStefano Zampini    Collective on PC
15624cb006feSStefano Zampini 
15634cb006feSStefano Zampini    Input Parameters:
15644cb006feSStefano Zampini +  pc - the preconditioning context
15654cb006feSStefano Zampini -  A - the matrix
15664cb006feSStefano Zampini 
15674cb006feSStefano Zampini    Level: intermediate
15684cb006feSStefano Zampini 
156995452b02SPatrick Sanan    Notes:
157095452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
15714cb006feSStefano Zampini 
1572db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
15734cb006feSStefano Zampini @*/
15749371c9d4SSatish Balay PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A) {
15754cb006feSStefano Zampini   PetscFunctionBegin;
15764cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15774cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
15784cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1579cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
15804cb006feSStefano Zampini   PetscFunctionReturn(0);
15814cb006feSStefano Zampini }
15824cb006feSStefano Zampini 
15834cb006feSStefano Zampini /*@
15844cb006feSStefano Zampini  PCHYPRESetBetaPoissonMatrix - Set Poisson matrix
15854cb006feSStefano Zampini 
15864cb006feSStefano Zampini    Collective on PC
15874cb006feSStefano Zampini 
15884cb006feSStefano Zampini    Input Parameters:
15894cb006feSStefano Zampini +  pc - the preconditioning context
15904cb006feSStefano Zampini -  A - the matrix
15914cb006feSStefano Zampini 
15924cb006feSStefano Zampini    Level: intermediate
15934cb006feSStefano Zampini 
159495452b02SPatrick Sanan    Notes:
159595452b02SPatrick Sanan     A should be obtained by discretizing the Poisson problem with linear finite elements.
15964cb006feSStefano Zampini           Following HYPRE convention, the scalar Poisson solver of AMS can be turned off by passing NULL.
15974cb006feSStefano Zampini 
1598db781477SPatrick Sanan .seealso: `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
15994cb006feSStefano Zampini @*/
16009371c9d4SSatish Balay PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A) {
16014cb006feSStefano Zampini   PetscFunctionBegin;
16024cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16034cb006feSStefano Zampini   if (A) {
16044cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16054cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
16064cb006feSStefano Zampini   }
1607cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
16084cb006feSStefano Zampini   PetscFunctionReturn(0);
16094cb006feSStefano Zampini }
16104cb006feSStefano Zampini 
16119371c9d4SSatish Balay static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo) {
16124cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16134cb006feSStefano Zampini 
16144cb006feSStefano Zampini   PetscFunctionBegin;
16154cb006feSStefano Zampini   /* throw away any vector if already set */
16169566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
16179566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
16189566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
16199566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
16209566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
16219566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
16229566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
16235ac14e1cSStefano Zampini   jac->dim = 2;
16244cb006feSStefano Zampini   if (zzo) {
16259566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
16269566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
16275ac14e1cSStefano Zampini     jac->dim++;
16284cb006feSStefano Zampini   }
16294cb006feSStefano Zampini   PetscFunctionReturn(0);
16304cb006feSStefano Zampini }
16314cb006feSStefano Zampini 
16324cb006feSStefano Zampini /*@
1633147403d9SBarry Smith  PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis
16344cb006feSStefano Zampini 
16354cb006feSStefano Zampini    Collective on PC
16364cb006feSStefano Zampini 
16374cb006feSStefano Zampini    Input Parameters:
16384cb006feSStefano Zampini +  pc - the preconditioning context
16394cb006feSStefano Zampini -  ozz - vector representing (1,0,0) (or (1,0) in 2D)
16404cb006feSStefano Zampini -  zoz - vector representing (0,1,0) (or (0,1) in 2D)
16414cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
16424cb006feSStefano Zampini 
16434cb006feSStefano Zampini    Level: intermediate
16444cb006feSStefano Zampini 
16454cb006feSStefano Zampini @*/
16469371c9d4SSatish Balay PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo) {
16474cb006feSStefano Zampini   PetscFunctionBegin;
16484cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16494cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
16504cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
16514cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
16524cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
16534cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
16544cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1655cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
16564cb006feSStefano Zampini   PetscFunctionReturn(0);
16574cb006feSStefano Zampini }
16584cb006feSStefano Zampini 
16599371c9d4SSatish Balay static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior) {
1660be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1661be14dc20SKerry Key 
1662be14dc20SKerry Key   PetscFunctionBegin;
1663be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1664be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1665be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1666be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
1667be14dc20SKerry Key   PetscFunctionReturn(0);
1668be14dc20SKerry Key }
1669be14dc20SKerry Key 
1670be14dc20SKerry Key /*@
1671be14dc20SKerry Key  PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region.
1672be14dc20SKerry Key 
1673be14dc20SKerry Key    Collective on PC
1674be14dc20SKerry Key 
1675be14dc20SKerry Key    Input Parameters:
1676be14dc20SKerry Key +  pc - the preconditioning context
1677be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1678be14dc20SKerry Key 
1679be14dc20SKerry Key    Level: intermediate
1680be14dc20SKerry Key 
1681be14dc20SKerry Key    Note:
1682be14dc20SKerry Key    This calls HYPRE_AMSSetInteriorNodes()
1683be14dc20SKerry Key .seealso:
1684be14dc20SKerry Key @*/
16859371c9d4SSatish Balay PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior) {
1686be14dc20SKerry Key   PetscFunctionBegin;
1687be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1688be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1689be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1690be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
1691be14dc20SKerry Key   PetscFunctionReturn(0);
1692be14dc20SKerry Key }
1693be14dc20SKerry Key 
16949371c9d4SSatish Balay static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) {
16954cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16964cb006feSStefano Zampini   Vec       tv;
16974cb006feSStefano Zampini   PetscInt  i;
16984cb006feSStefano Zampini 
16994cb006feSStefano Zampini   PetscFunctionBegin;
17004cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
17019566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
17029566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
17039566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
17045ac14e1cSStefano Zampini   jac->dim = dim;
17055ac14e1cSStefano Zampini 
17064cb006feSStefano Zampini   /* compute IJ vector for coordinates */
17079566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
17089566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
17099566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
17104cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
17114cb006feSStefano Zampini     PetscScalar *array;
17124cb006feSStefano Zampini     PetscInt     j;
17134cb006feSStefano Zampini 
17149566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
17159566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
17166ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
17179566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
17189566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
17194cb006feSStefano Zampini   }
17209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
17214cb006feSStefano Zampini   PetscFunctionReturn(0);
17224cb006feSStefano Zampini }
17234cb006feSStefano Zampini 
172416d9e3a6SLisandro Dalcin /* ---------------------------------------------------------------------------------*/
172516d9e3a6SLisandro Dalcin 
17269371c9d4SSatish Balay static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[]) {
172716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
172816d9e3a6SLisandro Dalcin 
172916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
173016d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
173116d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
173216d9e3a6SLisandro Dalcin }
173316d9e3a6SLisandro Dalcin 
17349371c9d4SSatish Balay static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[]) {
173516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1736ace3abfcSBarry Smith   PetscBool flag;
173716d9e3a6SLisandro Dalcin 
173816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
173916d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
17409566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
17415f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
174216d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
174316d9e3a6SLisandro Dalcin   } else {
17449566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
174516d9e3a6SLisandro Dalcin   }
174616d9e3a6SLisandro Dalcin 
174716d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
174816d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
174916d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
175016d9e3a6SLisandro Dalcin 
17519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
175216d9e3a6SLisandro Dalcin   if (flag) {
17539566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1754792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
175516d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
175616d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
175716d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
175816d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
175916d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
176016d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
176116d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
176216d9e3a6SLisandro Dalcin   }
17639566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1764db966c6cSHong Zhang   if (flag) {
17654e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
17664e3c431bSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64 bit indices");
17678bf83915SBarry Smith #endif
17689566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1769792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1770db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1771db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1772db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1773db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1774db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1775db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1776db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
1777db966c6cSHong Zhang     PetscFunctionReturn(0);
1778db966c6cSHong Zhang   }
17799566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
178016d9e3a6SLisandro Dalcin   if (flag) {
17819566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1782792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
178316d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
178416d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
178516d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
178616d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
178716d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
178816d9e3a6SLisandro Dalcin     /* initialize */
178916d9e3a6SLisandro Dalcin     jac->nlevels            = 1;
17908966356dSPierre Jolivet     jac->threshold          = .1;
179116d9e3a6SLisandro Dalcin     jac->filter             = .1;
179216d9e3a6SLisandro Dalcin     jac->loadbal            = 0;
17932fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
17942fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
17952fa5cd67SKarl Rupp 
179616d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
179716d9e3a6SLisandro Dalcin     jac->symt = 0;
1798792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1799792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1800792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1801792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1802792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1803792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
180416d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
180516d9e3a6SLisandro Dalcin   }
18069566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
180716d9e3a6SLisandro Dalcin   if (flag) {
1808792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
180916d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
181016d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
181116d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
181216d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
18139566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
18149566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
181516d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
181616d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
181716d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
181816d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
181916d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
182016d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
182116d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
182216d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
18238f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
182416d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
182516d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
182616d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
182716d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
182816d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
18290f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
18306a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1831b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
18321810e44eSEike Mueller     jac->eu_level                                                = 0;
18331810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
18341810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1835589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
18360f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
183716d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
183816d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
183916d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
18400f1074feSSatish Balay     jac->interptype                       = 0;
1841589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1842589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1843589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1844589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1845589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
18460f1074feSSatish Balay     jac->agg_nl                           = 0;
18476ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
18480f1074feSSatish Balay     jac->pmax                             = 0;
18490f1074feSSatish Balay     jac->truncfactor                      = 0.0;
18500f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1851589dcaf0SStefano Zampini     jac->maxc                             = 9;
1852589dcaf0SStefano Zampini     jac->minc                             = 1;
185322e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
185422e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
185522e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
185622e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
185722e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
185822e51d31SStefano Zampini     jac->interp_refine                    = 0;
18598f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
18608f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
18616ea7df73SStefano Zampini     jac->rap2                             = 0;
18626ea7df73SStefano Zampini 
18636ea7df73SStefano Zampini     /* GPU defaults
18646ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
18656ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
18666ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
18676ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
18686ea7df73SStefano Zampini     jac->mod_rap2       = 1;
18696ea7df73SStefano Zampini     jac->coarsentype    = 8;
18706ea7df73SStefano Zampini     jac->relaxorder     = 0;
18716ea7df73SStefano Zampini     jac->interptype     = 6;
18726ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
18736ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
18746ea7df73SStefano Zampini     jac->agg_interptype = 7;
18756ea7df73SStefano Zampini #else
18766ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
18776ea7df73SStefano Zampini     jac->mod_rap2      = 0;
18786ea7df73SStefano Zampini #endif
1879792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
1880792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
1881792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
1882792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1883792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
1884792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
1885792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
1886792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
1887792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
1888792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
1889792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
1890792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
1891792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
1892792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
1893792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
1894792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
1895792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
1896792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
1897792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
18986ea7df73SStefano Zampini     /* GPU */
18996ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1900792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1901792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
1902792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
19036ea7df73SStefano Zampini #endif
19046ea7df73SStefano Zampini 
1905589dcaf0SStefano Zampini     /* AIR */
19066ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
1907792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
1908792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
1909792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
1910792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
1911792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
19126ea7df73SStefano Zampini #endif
191316d9e3a6SLisandro Dalcin     PetscFunctionReturn(0);
191416d9e3a6SLisandro Dalcin   }
19159566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
19164cb006feSStefano Zampini   if (flag) {
19179566063dSJacob Faibussowitsch     PetscCall(HYPRE_AMSCreate(&jac->hsolver));
19184cb006feSStefano Zampini     pc->ops->setfromoptions   = PCSetFromOptions_HYPRE_AMS;
19194cb006feSStefano Zampini     pc->ops->view             = PCView_HYPRE_AMS;
19204cb006feSStefano Zampini     jac->destroy              = HYPRE_AMSDestroy;
19214cb006feSStefano Zampini     jac->setup                = HYPRE_AMSSetup;
19224cb006feSStefano Zampini     jac->solve                = HYPRE_AMSSolve;
19234cb006feSStefano Zampini     jac->coords[0]            = NULL;
19244cb006feSStefano Zampini     jac->coords[1]            = NULL;
19254cb006feSStefano Zampini     jac->coords[2]            = NULL;
1926be14dc20SKerry Key     jac->interior             = NULL;
19274cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
1928863406b8SStefano Zampini     jac->as_print             = 0;
1929863406b8SStefano Zampini     jac->as_max_iter          = 1;  /* used as a preconditioner */
1930863406b8SStefano Zampini     jac->as_tol               = 0.; /* used as a preconditioner */
19314cb006feSStefano Zampini     jac->ams_cycle_type       = 13;
19324cb006feSStefano Zampini     /* Smoothing options */
1933863406b8SStefano Zampini     jac->as_relax_type        = 2;
1934863406b8SStefano Zampini     jac->as_relax_times       = 1;
1935863406b8SStefano Zampini     jac->as_relax_weight      = 1.0;
1936863406b8SStefano Zampini     jac->as_omega             = 1.0;
19374cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1938863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
1939863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
19400bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
1941863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
1942863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
1943863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
19444cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1945863406b8SStefano Zampini     jac->as_amg_beta_opts[0]  = 10;
1946863406b8SStefano Zampini     jac->as_amg_beta_opts[1]  = 1;
19470bdd8552SBarry Smith     jac->as_amg_beta_opts[2]  = 6;
1948863406b8SStefano Zampini     jac->as_amg_beta_opts[3]  = 6;
1949863406b8SStefano Zampini     jac->as_amg_beta_opts[4]  = 4;
1950863406b8SStefano Zampini     jac->as_amg_beta_theta    = 0.25;
1951792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
1952792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
1953792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
1954792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
19559371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
1956792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1957863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1958863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
19599371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1960a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
1961792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
1962863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
1963863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
19649371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
1965a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
196623df4f25SStefano Zampini     /* Zero conductivity */
196723df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
196823df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
19694cb006feSStefano Zampini     PetscFunctionReturn(0);
19704cb006feSStefano Zampini   }
19719566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
1972863406b8SStefano Zampini   if (flag) {
19739566063dSJacob Faibussowitsch     PetscCall(HYPRE_ADSCreate(&jac->hsolver));
1974863406b8SStefano Zampini     pc->ops->setfromoptions   = PCSetFromOptions_HYPRE_ADS;
1975863406b8SStefano Zampini     pc->ops->view             = PCView_HYPRE_ADS;
1976863406b8SStefano Zampini     jac->destroy              = HYPRE_ADSDestroy;
1977863406b8SStefano Zampini     jac->setup                = HYPRE_ADSSetup;
1978863406b8SStefano Zampini     jac->solve                = HYPRE_ADSSolve;
1979863406b8SStefano Zampini     jac->coords[0]            = NULL;
1980863406b8SStefano Zampini     jac->coords[1]            = NULL;
1981863406b8SStefano Zampini     jac->coords[2]            = NULL;
1982863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
1983863406b8SStefano Zampini     jac->as_print             = 0;
1984863406b8SStefano Zampini     jac->as_max_iter          = 1;  /* used as a preconditioner */
1985863406b8SStefano Zampini     jac->as_tol               = 0.; /* used as a preconditioner */
1986863406b8SStefano Zampini     jac->ads_cycle_type       = 13;
1987863406b8SStefano Zampini     /* Smoothing options */
1988863406b8SStefano Zampini     jac->as_relax_type        = 2;
1989863406b8SStefano Zampini     jac->as_relax_times       = 1;
1990863406b8SStefano Zampini     jac->as_relax_weight      = 1.0;
1991863406b8SStefano Zampini     jac->as_omega             = 1.0;
1992863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
1993863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
1994863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
1995863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
1996863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
1997863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
1998863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
1999863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2000863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2001863406b8SStefano Zampini     jac->as_amg_beta_opts[0]  = 10;
2002863406b8SStefano Zampini     jac->as_amg_beta_opts[1]  = 1;
2003863406b8SStefano Zampini     jac->as_amg_beta_opts[2]  = 6;
2004863406b8SStefano Zampini     jac->as_amg_beta_opts[3]  = 6;
2005863406b8SStefano Zampini     jac->as_amg_beta_opts[4]  = 4;
2006863406b8SStefano Zampini     jac->as_amg_beta_theta    = 0.25;
2007792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2008792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2009792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2010792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
20119371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2012792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2013863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2014863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2015863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
20169371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2017a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2018792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2019863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2020863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
20219371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2022a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
2023863406b8SStefano Zampini     PetscFunctionReturn(0);
2024863406b8SStefano Zampini   }
20259566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
20262fa5cd67SKarl Rupp 
20270298fd71SBarry Smith   jac->hypre_type = NULL;
202898921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
202916d9e3a6SLisandro Dalcin }
203016d9e3a6SLisandro Dalcin 
203116d9e3a6SLisandro Dalcin /*
203216d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
203316d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
203416d9e3a6SLisandro Dalcin */
20359371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject) {
20364ddd07fcSJed Brown   PetscInt    indx;
2037db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2038ace3abfcSBarry Smith   PetscBool   flg;
203916d9e3a6SLisandro Dalcin 
204016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2041d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2042dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
204316d9e3a6SLisandro Dalcin   if (flg) {
20449566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
204502a17cd4SBarry Smith   } else {
20469566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
204716d9e3a6SLisandro Dalcin   }
2048dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2049d0609cedSBarry Smith   PetscOptionsHeadEnd();
205016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
205116d9e3a6SLisandro Dalcin }
205216d9e3a6SLisandro Dalcin 
205316d9e3a6SLisandro Dalcin /*@C
205416d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
205516d9e3a6SLisandro Dalcin 
205616d9e3a6SLisandro Dalcin    Input Parameters:
205716d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2058db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
205916d9e3a6SLisandro Dalcin 
206016d9e3a6SLisandro Dalcin    Options Database Keys:
2061db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
206216d9e3a6SLisandro Dalcin 
206316d9e3a6SLisandro Dalcin    Level: intermediate
206416d9e3a6SLisandro Dalcin 
2065db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
2066db781477SPatrick Sanan           `PCHYPRE`
206716d9e3a6SLisandro Dalcin 
206816d9e3a6SLisandro Dalcin @*/
20699371c9d4SSatish Balay PetscErrorCode PCHYPRESetType(PC pc, const char name[]) {
207016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
20710700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
207216d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2073cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
207416d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
207516d9e3a6SLisandro Dalcin }
207616d9e3a6SLisandro Dalcin 
207716d9e3a6SLisandro Dalcin /*@C
207816d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
207916d9e3a6SLisandro Dalcin 
208016d9e3a6SLisandro Dalcin    Input Parameter:
208116d9e3a6SLisandro Dalcin .     pc - the preconditioner context
208216d9e3a6SLisandro Dalcin 
208316d9e3a6SLisandro Dalcin    Output Parameter:
2084db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
208516d9e3a6SLisandro Dalcin 
208616d9e3a6SLisandro Dalcin    Level: intermediate
208716d9e3a6SLisandro Dalcin 
2088db781477SPatrick Sanan .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`,
2089db781477SPatrick Sanan           `PCHYPRE`
209016d9e3a6SLisandro Dalcin 
209116d9e3a6SLisandro Dalcin @*/
20929371c9d4SSatish Balay PetscErrorCode PCHYPREGetType(PC pc, const char *name[]) {
209316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
20940700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
209516d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2096cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
209716d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
209816d9e3a6SLisandro Dalcin }
209916d9e3a6SLisandro Dalcin 
2100db6f9c32SMark Adams /*@C
2101db6f9c32SMark Adams    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use
2102db6f9c32SMark Adams 
2103db6f9c32SMark Adams    Logically Collective on PC
2104db6f9c32SMark Adams 
2105db6f9c32SMark Adams    Input Parameters:
2106db6f9c32SMark Adams +  pc - the hypre context
2107db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2108db6f9c32SMark Adams 
2109db6f9c32SMark Adams    Options Database Key:
211067b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2111db6f9c32SMark Adams 
2112db6f9c32SMark Adams    Level: intermediate
2113db6f9c32SMark Adams 
2114db781477SPatrick Sanan .seealso: `PCMGGalerkinGetMatProductAlgorithm()`
2115db6f9c32SMark Adams 
2116db6f9c32SMark Adams @*/
21179371c9d4SSatish Balay PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[]) {
2118db6f9c32SMark Adams   PetscFunctionBegin;
2119db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2120cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
2121db6f9c32SMark Adams   PetscFunctionReturn(0);
2122db6f9c32SMark Adams }
2123db6f9c32SMark Adams 
2124db6f9c32SMark Adams /*@C
2125db6f9c32SMark Adams    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre
2126db6f9c32SMark Adams 
2127db6f9c32SMark Adams    Not Collective
2128db6f9c32SMark Adams 
2129db6f9c32SMark Adams    Input Parameter:
2130db6f9c32SMark Adams .  pc - the multigrid context
2131db6f9c32SMark Adams 
2132db6f9c32SMark Adams    Output Parameter:
2133db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2134db6f9c32SMark Adams 
2135db6f9c32SMark Adams    Level: intermediate
2136db6f9c32SMark Adams 
2137db781477SPatrick Sanan .seealso: `PCMGGalerkinSetMatProductAlgorithm()`
2138db6f9c32SMark Adams 
2139db6f9c32SMark Adams @*/
21409371c9d4SSatish Balay PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[]) {
2141db6f9c32SMark Adams   PetscFunctionBegin;
2142db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2143cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
2144db6f9c32SMark Adams   PetscFunctionReturn(0);
2145db6f9c32SMark Adams }
2146db6f9c32SMark Adams 
214716d9e3a6SLisandro Dalcin /*MC
214816d9e3a6SLisandro Dalcin      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
214916d9e3a6SLisandro Dalcin 
215016d9e3a6SLisandro Dalcin    Options Database Keys:
2151db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2152ead8c081SBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see HYPRE_BOOMERAMGSetNodal())
2153ead8c081SBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see HYPRE_BoomerAMGSetInterpVecVariant())
2154ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
215516d9e3a6SLisandro Dalcin 
215616d9e3a6SLisandro Dalcin    Level: intermediate
215716d9e3a6SLisandro Dalcin 
215895452b02SPatrick Sanan    Notes:
215995452b02SPatrick Sanan     Apart from pc_hypre_type (for which there is PCHYPRESetType()),
216016d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
216116d9e3a6SLisandro Dalcin           or with PetscOptionsSetValue(), there are no functions to set them)
216216d9e3a6SLisandro Dalcin 
2163c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
21640f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
21650f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2166c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
21678f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
21680f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
21690f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
217016d9e3a6SLisandro Dalcin 
21710f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
21720f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
21730f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
217416d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
217516d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
217616d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
217716d9e3a6SLisandro Dalcin 
217816d9e3a6SLisandro Dalcin           2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
217916d9e3a6SLisandro Dalcin           -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
218016d9e3a6SLisandro Dalcin 
21815272c319SBarry Smith           MatSetNearNullSpace() - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2182fdd15c9aSJunchao Zhang           the following two options:
21830b1a5bd9SEric Chamberland 
21849e5bc791SBarry Smith           See PCPFMG for access to the hypre Struct PFMG solver
21859e5bc791SBarry Smith 
2186ead8c081SBarry Smith    GPU Notes:
2187ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2188ead8c081SBarry Smith      Then pass VECCUDA vectors and MATAIJCUSPARSE matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2189ead8c081SBarry Smith 
2190ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2191ead8c081SBarry Smith      Then pass VECHIP vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2192ead8c081SBarry Smith 
2193db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
2194db781477SPatrick Sanan           `PCHYPRESetType()`, `PCPFMG`
219516d9e3a6SLisandro Dalcin 
219616d9e3a6SLisandro Dalcin M*/
219716d9e3a6SLisandro Dalcin 
21989371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc) {
219916d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
220016d9e3a6SLisandro Dalcin 
220116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22029566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &jac));
22032fa5cd67SKarl Rupp 
220416d9e3a6SLisandro Dalcin   pc->data                = jac;
22058695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
220616d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
220716d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
220816d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
220916d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
221016d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
22119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
22129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
22139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
22149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
22159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
22169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
22179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2218be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
22199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
22209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
22219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
22226ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22236ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
22249566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
22256ea7df73SStefano Zampini #endif
22266ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
22279566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
22286ea7df73SStefano Zampini #endif
22296ea7df73SStefano Zampini #endif
223016d9e3a6SLisandro Dalcin   PetscFunctionReturn(0);
223116d9e3a6SLisandro Dalcin }
2232ebc551c0SBarry Smith 
2233f91d8e95SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------*/
2234f91d8e95SBarry Smith 
2235ebc551c0SBarry Smith typedef struct {
223668326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2237f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
22389e5bc791SBarry Smith 
22399e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
22404ddd07fcSJed Brown   PetscInt  its;
22419e5bc791SBarry Smith   double    tol;
22424ddd07fcSJed Brown   PetscInt  relax_type;
22434ddd07fcSJed Brown   PetscInt  rap_type;
22444ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
22454ddd07fcSJed Brown   PetscInt  max_levels;
22460be8cd64Sftrigaux   PetscInt  skip_relax;
22470be8cd64Sftrigaux   PetscBool print_statistics;
2248ebc551c0SBarry Smith } PC_PFMG;
2249ebc551c0SBarry Smith 
22509371c9d4SSatish Balay PetscErrorCode PCDestroy_PFMG(PC pc) {
2251f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2252ebc551c0SBarry Smith 
2253ebc551c0SBarry Smith   PetscFunctionBegin;
2254792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
22559566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
22569566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2257ebc551c0SBarry Smith   PetscFunctionReturn(0);
2258ebc551c0SBarry Smith }
2259ebc551c0SBarry Smith 
22609e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
22619e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
22629e5bc791SBarry Smith 
22639371c9d4SSatish Balay PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer) {
2264ace3abfcSBarry Smith   PetscBool iascii;
2265f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2266ebc551c0SBarry Smith 
2267ebc551c0SBarry Smith   PetscFunctionBegin;
22689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
22699e5bc791SBarry Smith   if (iascii) {
22709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
227163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
22729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
22739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
22749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
227563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
227663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
22770be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
22789e5bc791SBarry Smith   }
2279ebc551c0SBarry Smith   PetscFunctionReturn(0);
2280ebc551c0SBarry Smith }
2281ebc551c0SBarry Smith 
22829371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject) {
2283f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2284ebc551c0SBarry Smith 
2285ebc551c0SBarry Smith   PetscFunctionBegin;
2286d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
22870be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
22889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2289792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
22909566063dSJacob 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));
2291792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
22929566063dSJacob 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));
2293792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
22949e5bc791SBarry Smith 
22959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2296792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
22973b46a515SGlenn Hammond 
22989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2299792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2300dd39110bSPierre 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));
2301792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2302dd39110bSPierre 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));
2303792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
23040be8cd64Sftrigaux   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));
23050be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2306d0609cedSBarry Smith   PetscOptionsHeadEnd();
2307ebc551c0SBarry Smith   PetscFunctionReturn(0);
2308ebc551c0SBarry Smith }
2309ebc551c0SBarry Smith 
23109371c9d4SSatish Balay PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y) {
2311f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2312d9ca1df4SBarry Smith   PetscScalar       *yy;
2313d9ca1df4SBarry Smith   const PetscScalar *xx;
23144ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
23152cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
231668326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2317f91d8e95SBarry Smith 
2318f91d8e95SBarry Smith   PetscFunctionBegin;
23199566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
23209566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
23212cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2322f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2323f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2324f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
23252cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
23262cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
23272cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
23282cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
23292cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
23302cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2331f91d8e95SBarry Smith 
2332f91d8e95SBarry Smith   /* copy x values over to hypre */
2333792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
23349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2335792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
23369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2337792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2338792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2339f91d8e95SBarry Smith 
2340f91d8e95SBarry Smith   /* copy solution values back to PETSc */
23419566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2342792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
23439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2344f91d8e95SBarry Smith   PetscFunctionReturn(0);
2345f91d8e95SBarry Smith }
2346f91d8e95SBarry Smith 
23479371c9d4SSatish Balay 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) {
23489e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
23492cf14000SStefano Zampini   HYPRE_Int oits;
23509e5bc791SBarry Smith 
23519e5bc791SBarry Smith   PetscFunctionBegin;
23529566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2353792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2354792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
23559e5bc791SBarry Smith 
23569566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2357792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
23589e5bc791SBarry Smith   *outits = oits;
23599e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
23609e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2361792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2362792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
23639e5bc791SBarry Smith   PetscFunctionReturn(0);
23649e5bc791SBarry Smith }
23659e5bc791SBarry Smith 
23669371c9d4SSatish Balay PetscErrorCode PCSetUp_PFMG(PC pc) {
23673a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
23683a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2369ace3abfcSBarry Smith   PetscBool        flg;
23703a32d3dbSGlenn Hammond 
23713a32d3dbSGlenn Hammond   PetscFunctionBegin;
23729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
237328b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
23743a32d3dbSGlenn Hammond 
23753a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2376792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2377792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
23780be8cd64Sftrigaux 
23790be8cd64Sftrigaux   // Print Hypre statistics about the solve process
23800be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
23810be8cd64Sftrigaux 
23820be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
23830be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
23840be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
23850be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
23860be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
23870be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
23880be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
23890be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
23900be8cd64Sftrigaux 
2391792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2392792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
23933a32d3dbSGlenn Hammond   PetscFunctionReturn(0);
23943a32d3dbSGlenn Hammond }
23953a32d3dbSGlenn Hammond 
2396ebc551c0SBarry Smith /*MC
2397ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2398ebc551c0SBarry Smith 
2399ebc551c0SBarry Smith    Level: advanced
2400ebc551c0SBarry Smith 
24019e5bc791SBarry Smith    Options Database:
240267b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
240367b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
240467b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
240567b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
24069e5bc791SBarry 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
24070be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
24080be8cd64Sftrigaux - -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, one of 0,1
2409f91d8e95SBarry Smith 
241095452b02SPatrick Sanan    Notes:
241195452b02SPatrick Sanan     This is for CELL-centered descretizations
24129e5bc791SBarry Smith 
24138e395302SJed Brown            This must be used with the MATHYPRESTRUCT matrix type.
2414aa219208SBarry Smith            This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA.
24159e5bc791SBarry Smith 
2416db781477SPatrick Sanan .seealso: `PCMG`, `MATHYPRESTRUCT`
2417ebc551c0SBarry Smith M*/
2418ebc551c0SBarry Smith 
24199371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc) {
2420ebc551c0SBarry Smith   PC_PFMG *ex;
2421ebc551c0SBarry Smith 
2422ebc551c0SBarry Smith   PetscFunctionBegin;
24239371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
242468326731SBarry Smith   pc->data = ex;
2425ebc551c0SBarry Smith 
24269e5bc791SBarry Smith   ex->its              = 1;
24279e5bc791SBarry Smith   ex->tol              = 1.e-8;
24289e5bc791SBarry Smith   ex->relax_type       = 1;
24299e5bc791SBarry Smith   ex->rap_type         = 0;
24309e5bc791SBarry Smith   ex->num_pre_relax    = 1;
24319e5bc791SBarry Smith   ex->num_post_relax   = 1;
24323b46a515SGlenn Hammond   ex->max_levels       = 0;
24330be8cd64Sftrigaux   ex->skip_relax       = 0;
24340be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
24359e5bc791SBarry Smith 
2436ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2437ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2438ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2439f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
24409e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
244168326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
24422fa5cd67SKarl Rupp 
24439566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2444792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
2445ebc551c0SBarry Smith   PetscFunctionReturn(0);
2446ebc551c0SBarry Smith }
2447d851a50bSGlenn Hammond 
2448325fc9f4SBarry Smith /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/
2449325fc9f4SBarry Smith 
2450d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2451d851a50bSGlenn Hammond typedef struct {
2452d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2453d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2454d851a50bSGlenn Hammond 
2455d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
24564ddd07fcSJed Brown   PetscInt its;
2457d851a50bSGlenn Hammond   double   tol;
24584ddd07fcSJed Brown   PetscInt relax_type;
24594ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2460d851a50bSGlenn Hammond } PC_SysPFMG;
2461d851a50bSGlenn Hammond 
24629371c9d4SSatish Balay PetscErrorCode PCDestroy_SysPFMG(PC pc) {
2463d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2464d851a50bSGlenn Hammond 
2465d851a50bSGlenn Hammond   PetscFunctionBegin;
2466792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
24679566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
24689566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2469d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2470d851a50bSGlenn Hammond }
2471d851a50bSGlenn Hammond 
2472d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2473d851a50bSGlenn Hammond 
24749371c9d4SSatish Balay PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer) {
2475ace3abfcSBarry Smith   PetscBool   iascii;
2476d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2477d851a50bSGlenn Hammond 
2478d851a50bSGlenn Hammond   PetscFunctionBegin;
24799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2480d851a50bSGlenn Hammond   if (iascii) {
24819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
248263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
24839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
24849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
248563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2486d851a50bSGlenn Hammond   }
2487d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2488d851a50bSGlenn Hammond }
2489d851a50bSGlenn Hammond 
24909371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject) {
2491d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2492ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2493d851a50bSGlenn Hammond 
2494d851a50bSGlenn Hammond   PetscFunctionBegin;
2495d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
24969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
2497*48a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
24989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2499792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
25009566063dSJacob 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));
2501792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
25029566063dSJacob 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));
2503792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2504d851a50bSGlenn Hammond 
25059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2506792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2507dd39110bSPierre 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));
2508792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2509d0609cedSBarry Smith   PetscOptionsHeadEnd();
2510d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2511d851a50bSGlenn Hammond }
2512d851a50bSGlenn Hammond 
25139371c9d4SSatish Balay PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y) {
2514d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2515d9ca1df4SBarry Smith   PetscScalar       *yy;
2516d9ca1df4SBarry Smith   const PetscScalar *xx;
25174ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
25182cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2519d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
25204ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
25214ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
25224ddd07fcSJed Brown   PetscInt           part     = 0;
25234ddd07fcSJed Brown   PetscInt           size;
25244ddd07fcSJed Brown   PetscInt           i;
2525d851a50bSGlenn Hammond 
2526d851a50bSGlenn Hammond   PetscFunctionBegin;
25279566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
25289566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
25292cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2530d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2531d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2532d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
25332cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
25342cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
25352cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
25362cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
25372cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
25382cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2539d851a50bSGlenn Hammond 
2540d851a50bSGlenn Hammond   size = 1;
25412fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
25422fa5cd67SKarl Rupp 
2543d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2544d851a50bSGlenn Hammond   if (ordering) {
2545792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
25469566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2547792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
25489566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2549792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2550792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2551792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2552d851a50bSGlenn Hammond 
2553d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
25549566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2555792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
25569566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2557a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2558d851a50bSGlenn Hammond     PetscScalar *z;
25594ddd07fcSJed Brown     PetscInt     j, k;
2560d851a50bSGlenn Hammond 
25619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2562792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
25639566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2564d851a50bSGlenn Hammond 
2565d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2566d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2567d851a50bSGlenn Hammond       k = i * nvars;
25682fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2569d851a50bSGlenn Hammond     }
2570792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
25719566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2572792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2573792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2574d851a50bSGlenn Hammond 
2575d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
25769566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2577792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2578d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2579d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2580d851a50bSGlenn Hammond       k = i * nvars;
25812fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2582d851a50bSGlenn Hammond     }
25839566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
25849566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2585d851a50bSGlenn Hammond   }
2586d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2587d851a50bSGlenn Hammond }
2588d851a50bSGlenn Hammond 
25899371c9d4SSatish Balay 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) {
2590d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
25912cf14000SStefano Zampini   HYPRE_Int   oits;
2592d851a50bSGlenn Hammond 
2593d851a50bSGlenn Hammond   PetscFunctionBegin;
25949566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2595792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2596792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
25979566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2598792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2599d851a50bSGlenn Hammond   *outits = oits;
2600d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2601d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2602792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2603792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
2604d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2605d851a50bSGlenn Hammond }
2606d851a50bSGlenn Hammond 
26079371c9d4SSatish Balay PetscErrorCode PCSetUp_SysPFMG(PC pc) {
2608d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2609d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2610ace3abfcSBarry Smith   PetscBool         flg;
2611d851a50bSGlenn Hammond 
2612d851a50bSGlenn Hammond   PetscFunctionBegin;
26139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
261428b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2615d851a50bSGlenn Hammond 
2616d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2617792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2618792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2619792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2620792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2621d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2622d851a50bSGlenn Hammond }
2623d851a50bSGlenn Hammond 
2624d851a50bSGlenn Hammond /*MC
2625d851a50bSGlenn Hammond      PCSysPFMG - the hypre SysPFMG multigrid solver
2626d851a50bSGlenn Hammond 
2627d851a50bSGlenn Hammond    Level: advanced
2628d851a50bSGlenn Hammond 
2629d851a50bSGlenn Hammond    Options Database:
263067b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
263167b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
263267b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
263367b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
263467b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2635d851a50bSGlenn Hammond 
263695452b02SPatrick Sanan    Notes:
263795452b02SPatrick Sanan     This is for CELL-centered descretizations
2638d851a50bSGlenn Hammond 
2639f6680f47SSatish Balay            This must be used with the MATHYPRESSTRUCT matrix type.
2640aa219208SBarry Smith            This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA.
2641d851a50bSGlenn Hammond            Also, only cell-centered variables.
2642d851a50bSGlenn Hammond 
2643db781477SPatrick Sanan .seealso: `PCMG`, `MATHYPRESSTRUCT`
2644d851a50bSGlenn Hammond M*/
2645d851a50bSGlenn Hammond 
26469371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc) {
2647d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2648d851a50bSGlenn Hammond 
2649d851a50bSGlenn Hammond   PetscFunctionBegin;
26509371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2651d851a50bSGlenn Hammond   pc->data = ex;
2652d851a50bSGlenn Hammond 
2653d851a50bSGlenn Hammond   ex->its            = 1;
2654d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2655d851a50bSGlenn Hammond   ex->relax_type     = 1;
2656d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2657d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2658d851a50bSGlenn Hammond 
2659d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2660d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2661d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2662d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2663d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2664d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
26652fa5cd67SKarl Rupp 
26669566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2667792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2668d851a50bSGlenn Hammond   PetscFunctionReturn(0);
2669d851a50bSGlenn Hammond }
26701c188c59Sftrigaux 
26711c188c59Sftrigaux /* ---------------------------------------------------------------------------------------------------------------------------------*/
26721c188c59Sftrigaux 
26731c188c59Sftrigaux // PC SMG
26741c188c59Sftrigaux typedef struct {
26751c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
26761c188c59Sftrigaux   HYPRE_StructSolver hsolver;
26771c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
26781c188c59Sftrigaux   double             tol;
26791c188c59Sftrigaux   PetscBool          print_statistics;
26801c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
26811c188c59Sftrigaux } PC_SMG;
26821c188c59Sftrigaux 
26839371c9d4SSatish Balay PetscErrorCode PCDestroy_SMG(PC pc) {
26841c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
26851c188c59Sftrigaux 
26861c188c59Sftrigaux   PetscFunctionBegin;
26871c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
26881c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26891c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
26901c188c59Sftrigaux   PetscFunctionReturn(0);
26911c188c59Sftrigaux }
26921c188c59Sftrigaux 
26939371c9d4SSatish Balay PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer) {
26941c188c59Sftrigaux   PetscBool iascii;
26951c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
26961c188c59Sftrigaux 
26971c188c59Sftrigaux   PetscFunctionBegin;
26981c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
26991c188c59Sftrigaux   if (iascii) {
27001c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
27011c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
27021c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
27031c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
27041c188c59Sftrigaux   }
27051c188c59Sftrigaux   PetscFunctionReturn(0);
27061c188c59Sftrigaux }
27071c188c59Sftrigaux 
27089371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject) {
27091c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
27101c188c59Sftrigaux 
27111c188c59Sftrigaux   PetscFunctionBegin;
27121c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
27131c188c59Sftrigaux 
27141c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
27151c188c59Sftrigaux   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));
27161c188c59Sftrigaux   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));
27171c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
27181c188c59Sftrigaux 
27191c188c59Sftrigaux   PetscOptionsHeadEnd();
27201c188c59Sftrigaux   PetscFunctionReturn(0);
27211c188c59Sftrigaux }
27221c188c59Sftrigaux 
27239371c9d4SSatish Balay PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y) {
27241c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
27251c188c59Sftrigaux   PetscScalar       *yy;
27261c188c59Sftrigaux   const PetscScalar *xx;
27271c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
27281c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
27291c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
27301c188c59Sftrigaux 
27311c188c59Sftrigaux   PetscFunctionBegin;
27321c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27331c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
27341c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
27351c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
27361c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
27371c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
27381c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
27391c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
27401c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
27411c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
27421c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
27431c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
27441c188c59Sftrigaux 
27451c188c59Sftrigaux   /* copy x values over to hypre */
27461c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
27471c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
27481c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
27491c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
27501c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
27511c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
27521c188c59Sftrigaux 
27531c188c59Sftrigaux   /* copy solution values back to PETSc */
27541c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
27551c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
27561c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
27571c188c59Sftrigaux   PetscFunctionReturn(0);
27581c188c59Sftrigaux }
27591c188c59Sftrigaux 
27609371c9d4SSatish Balay 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) {
27611c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
27621c188c59Sftrigaux   HYPRE_Int oits;
27631c188c59Sftrigaux 
27641c188c59Sftrigaux   PetscFunctionBegin;
27651c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
27661c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
27671c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
27681c188c59Sftrigaux 
27691c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
27701c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
27711c188c59Sftrigaux   *outits = oits;
27721c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
27731c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
27741c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
27751c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
27761c188c59Sftrigaux   PetscFunctionReturn(0);
27771c188c59Sftrigaux }
27781c188c59Sftrigaux 
27799371c9d4SSatish Balay PetscErrorCode PCSetUp_SMG(PC pc) {
27801c188c59Sftrigaux   PetscInt         i, dim;
27811c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
27821c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
27831c188c59Sftrigaux   PetscBool        flg;
27841c188c59Sftrigaux   DMBoundaryType   p[3];
27851c188c59Sftrigaux   PetscInt         M[3];
27861c188c59Sftrigaux 
27871c188c59Sftrigaux   PetscFunctionBegin;
27881c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
27891c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
27901c188c59Sftrigaux 
27911c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
27921c188c59Sftrigaux   // Check if power of 2 in periodic directions
27931c188c59Sftrigaux   for (i = 0; i < dim; i++) {
27941c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
27951c188c59Sftrigaux       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "With SMG, the number of points in a periodic direction must be a power of 2, but is here %" PetscInt_FMT ".", M[i]);
27961c188c59Sftrigaux     }
27971c188c59Sftrigaux   }
27981c188c59Sftrigaux 
27991c188c59Sftrigaux   /* create the hypre solver object and set its information */
28001c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
28011c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
28021c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
28031c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
28041c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
28051c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
28061c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
28071c188c59Sftrigaux 
28081c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28091c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
28101c188c59Sftrigaux   PetscFunctionReturn(0);
28111c188c59Sftrigaux }
28121c188c59Sftrigaux 
28131c188c59Sftrigaux /*MC
28145cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
28151c188c59Sftrigaux 
28161c188c59Sftrigaux    Level: advanced
28171c188c59Sftrigaux 
28181c188c59Sftrigaux    Options Database:
28195cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
28205cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
28215cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
28225cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
28231c188c59Sftrigaux 
28241c188c59Sftrigaux    Notes:
28251c188c59Sftrigaux    This is for CELL-centered descretizations
28261c188c59Sftrigaux 
28275cb80ecdSBarry Smith   This must be used with the `MATHYPRESTRUCT` `MatType`.
28285cb80ecdSBarry Smith   This support is less general than in hypre, it supports only one block per process defined by a PETSc `DMDA`.
28291c188c59Sftrigaux 
28301c188c59Sftrigaux .seealso:  PCMG, MATHYPRESTRUCT, PCPFMG
28311c188c59Sftrigaux M*/
28321c188c59Sftrigaux 
28339371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc) {
28341c188c59Sftrigaux   PC_SMG *ex;
28351c188c59Sftrigaux 
28361c188c59Sftrigaux   PetscFunctionBegin;
28379371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
28381c188c59Sftrigaux   pc->data = ex;
28391c188c59Sftrigaux 
28401c188c59Sftrigaux   ex->its            = 1;
28411c188c59Sftrigaux   ex->tol            = 1.e-8;
28421c188c59Sftrigaux   ex->num_pre_relax  = 1;
28431c188c59Sftrigaux   ex->num_post_relax = 1;
28441c188c59Sftrigaux 
28451c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
28461c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
28471c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
28481c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
28491c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
28501c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
28511c188c59Sftrigaux 
28521c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28531c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
28541c188c59Sftrigaux   PetscFunctionReturn(0);
28551c188c59Sftrigaux }
2856