xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision ea9ee2c1d69c9e3cf6d2b3c8a205b9880d3dba39)
116d9e3a6SLisandro Dalcin /*
216d9e3a6SLisandro Dalcin    Provides an interface to the LLNL package hypre
316d9e3a6SLisandro Dalcin */
40f1074feSSatish Balay 
5589dcaf0SStefano Zampini #include <petscpkg_version.h>
6af0996ceSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
749a781f5SStefano Zampini /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */
849a781f5SStefano Zampini #include <petsc/private/matimpl.h>
96ea7df73SStefano Zampini #include <petsc/private/vecimpl.h>
1058968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1149a781f5SStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
12c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
134cb006feSStefano Zampini #include <_hypre_parcsr_ls.h>
148a2c336bSFande Kong #include <petscmathypre.h>
1516d9e3a6SLisandro Dalcin 
16a4af0ceeSJacob Faibussowitsch #if defined(PETSC_HAVE_HYPRE_DEVICE)
17a4af0ceeSJacob Faibussowitsch   #include <petsc/private/deviceimpl.h>
18a4af0ceeSJacob Faibussowitsch #endif
19a4af0ceeSJacob Faibussowitsch 
20dff31646SBarry Smith static PetscBool  cite            = PETSC_FALSE;
219371c9d4SSatish Balay static const char hypreCitation[] = "@manual{hypre-web-page,\n  title  = {{\\sl hypre}: High Performance Preconditioners},\n  organization = {Lawrence Livermore National Laboratory},\n  note  = "
22bd87328aSJed Brown                                     "{\\url{https://www.llnl.gov/casc/hypre}}\n}\n";
231f817a21SBarry Smith 
2416d9e3a6SLisandro Dalcin /*
2516d9e3a6SLisandro Dalcin    Private context (data structure) for the  preconditioner.
2616d9e3a6SLisandro Dalcin */
2716d9e3a6SLisandro Dalcin typedef struct {
2816d9e3a6SLisandro Dalcin   HYPRE_Solver hsolver;
2949a781f5SStefano Zampini   Mat          hpmat; /* MatHYPRE */
3016d9e3a6SLisandro Dalcin 
314ddd07fcSJed Brown   HYPRE_Int (*destroy)(HYPRE_Solver);
324ddd07fcSJed Brown   HYPRE_Int (*solve)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
334ddd07fcSJed Brown   HYPRE_Int (*setup)(HYPRE_Solver, HYPRE_ParCSRMatrix, HYPRE_ParVector, HYPRE_ParVector);
3416d9e3a6SLisandro Dalcin 
3516d9e3a6SLisandro Dalcin   MPI_Comm comm_hypre;
3616d9e3a6SLisandro Dalcin   char    *hypre_type;
3716d9e3a6SLisandro Dalcin 
3816d9e3a6SLisandro Dalcin   /* options for Pilut and BoomerAMG*/
394ddd07fcSJed Brown   PetscInt  maxiter;
4039accc25SStefano Zampini   PetscReal tol;
4116d9e3a6SLisandro Dalcin 
4216d9e3a6SLisandro Dalcin   /* options for Pilut */
434ddd07fcSJed Brown   PetscInt factorrowsize;
4416d9e3a6SLisandro Dalcin 
4516d9e3a6SLisandro Dalcin   /* options for ParaSails */
464ddd07fcSJed Brown   PetscInt  nlevels;
478966356dSPierre Jolivet   PetscReal threshold;
4839accc25SStefano Zampini   PetscReal filter;
4939accc25SStefano Zampini   PetscReal loadbal;
504ddd07fcSJed Brown   PetscInt  logging;
514ddd07fcSJed Brown   PetscInt  ruse;
524ddd07fcSJed Brown   PetscInt  symt;
5316d9e3a6SLisandro Dalcin 
5422b6d1caSBarry Smith   /* options for BoomerAMG */
55ace3abfcSBarry Smith   PetscBool printstatistics;
5616d9e3a6SLisandro Dalcin 
5716d9e3a6SLisandro Dalcin   /* options for BoomerAMG */
584ddd07fcSJed Brown   PetscInt  cycletype;
594ddd07fcSJed Brown   PetscInt  maxlevels;
6039accc25SStefano Zampini   PetscReal strongthreshold;
6139accc25SStefano Zampini   PetscReal maxrowsum;
624ddd07fcSJed Brown   PetscInt  gridsweeps[3];
634ddd07fcSJed Brown   PetscInt  coarsentype;
644ddd07fcSJed Brown   PetscInt  measuretype;
656a251517SEike Mueller   PetscInt  smoothtype;
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 
147d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetSolver(PC pc, HYPRE_Solver *hsolver)
148d71ae5a4SJacob Faibussowitsch {
149d2128fa2SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
150d2128fa2SBarry Smith 
151d2128fa2SBarry Smith   PetscFunctionBegin;
152d2128fa2SBarry Smith   *hsolver = jac->hsolver;
1533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
154d2128fa2SBarry Smith }
15516d9e3a6SLisandro Dalcin 
156fd2dd295SFande Kong /*
1578a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1588a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1598a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
160fd2dd295SFande Kong */
161d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc, PetscInt *nlevels, Mat *operators[])
162d71ae5a4SJacob Faibussowitsch {
1638a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1648a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1658a2c336bSFande Kong   PetscInt             num_levels, l;
1668a2c336bSFande Kong   Mat                 *mattmp;
1678a2c336bSFande Kong   hypre_ParCSRMatrix **A_array;
1688a2c336bSFande Kong 
1698a2c336bSFande Kong   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
1715f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
1728a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
1739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
1748a2c336bSFande Kong   A_array = hypre_ParAMGDataAArray((hypre_ParAMGData *)(jac->hsolver));
1758a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
1769566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(A_array[l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[num_levels - 1 - l])));
1778a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
1788a2c336bSFande Kong     A_array[l] = NULL;
1798a2c336bSFande Kong   }
1808a2c336bSFande Kong   *nlevels   = num_levels;
1818a2c336bSFande Kong   *operators = mattmp;
1823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1838a2c336bSFande Kong }
1848a2c336bSFande Kong 
185fd2dd295SFande Kong /*
1868a2c336bSFande Kong   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
1878a2c336bSFande Kong   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
1888a2c336bSFande Kong   It is used in PCHMG. Other users should avoid using this function.
189fd2dd295SFande Kong */
190d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc, PetscInt *nlevels, Mat *interpolations[])
191d71ae5a4SJacob Faibussowitsch {
1928a2c336bSFande Kong   PC_HYPRE            *jac  = (PC_HYPRE *)pc->data;
1938a2c336bSFande Kong   PetscBool            same = PETSC_FALSE;
1948a2c336bSFande Kong   PetscInt             num_levels, l;
1958a2c336bSFande Kong   Mat                 *mattmp;
1968a2c336bSFande Kong   hypre_ParCSRMatrix **P_array;
1978a2c336bSFande Kong 
1988a2c336bSFande Kong   PetscFunctionBegin;
1999566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(jac->hypre_type, "boomeramg", &same));
2005f80ce2aSJacob Faibussowitsch   PetscCheck(same, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_NOTSAMETYPE, "Hypre type is not BoomerAMG ");
2018a2c336bSFande Kong   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData *)(jac->hsolver));
2029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(num_levels, &mattmp));
2038a2c336bSFande Kong   P_array = hypre_ParAMGDataPArray((hypre_ParAMGData *)(jac->hsolver));
2048a2c336bSFande Kong   for (l = 1; l < num_levels; l++) {
2059566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(P_array[num_levels - 1 - l], MATAIJ, PETSC_OWN_POINTER, &(mattmp[l - 1])));
2068a2c336bSFande Kong     /* We want to own the data, and HYPRE can not touch this matrix any more */
2078a2c336bSFande Kong     P_array[num_levels - 1 - l] = NULL;
2088a2c336bSFande Kong   }
2098a2c336bSFande Kong   *nlevels        = num_levels;
2108a2c336bSFande Kong   *interpolations = mattmp;
2113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128a2c336bSFande Kong }
2138a2c336bSFande Kong 
214ce6a8a0dSJed Brown /* Resets (frees) Hypre's representation of the near null space */
215d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
216d71ae5a4SJacob Faibussowitsch {
217ce6a8a0dSJed Brown   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
218ce6a8a0dSJed Brown   PetscInt  i;
219ce6a8a0dSJed Brown 
2209d678128SJed Brown   PetscFunctionBegin;
22148a46eb9SPierre Jolivet   for (i = 0; i < jac->n_hmnull; i++) PetscCall(VecHYPRE_IJVectorDestroy(&jac->hmnull[i]));
2229566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hmnull));
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->phmnull));
2249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->hmnull_constant));
2259d678128SJed Brown   jac->n_hmnull = 0;
2263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227ce6a8a0dSJed Brown }
228ce6a8a0dSJed Brown 
229d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_HYPRE(PC pc)
230d71ae5a4SJacob Faibussowitsch {
23116d9e3a6SLisandro Dalcin   PC_HYPRE          *jac = (PC_HYPRE *)pc->data;
23249a781f5SStefano Zampini   Mat_HYPRE         *hjac;
23316d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
23416d9e3a6SLisandro Dalcin   HYPRE_ParVector    bv, xv;
23549a781f5SStefano Zampini   PetscBool          ishypre;
23616d9e3a6SLisandro Dalcin 
23716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23848a46eb9SPierre Jolivet   if (!jac->hypre_type) PetscCall(PCHYPRESetType(pc, "boomeramg"));
2395f5c5b43SBarry Smith 
2409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRE, &ishypre));
24149a781f5SStefano Zampini   if (!ishypre) {
2429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
2439566063dSJacob Faibussowitsch     PetscCall(MatConvert(pc->pmat, MATHYPRE, MAT_INITIAL_MATRIX, &jac->hpmat));
24449a781f5SStefano Zampini   } else {
2459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pc->pmat));
2469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->hpmat));
24749a781f5SStefano Zampini     jac->hpmat = pc->pmat;
24816d9e3a6SLisandro Dalcin   }
2496ea7df73SStefano Zampini   /* allow debug */
2509566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(jac->hpmat, NULL, "-pc_hypre_mat_view"));
25149a781f5SStefano Zampini   hjac = (Mat_HYPRE *)(jac->hpmat->data);
2525f5c5b43SBarry Smith 
25316d9e3a6SLisandro Dalcin   /* special case for BoomerAMG */
25416d9e3a6SLisandro Dalcin   if (jac->setup == HYPRE_BoomerAMGSetup) {
2555272c319SBarry Smith     MatNullSpace mnull;
2565272c319SBarry Smith     PetscBool    has_const;
25749a781f5SStefano Zampini     PetscInt     bs, nvec, i;
2585272c319SBarry Smith     const Vec   *vecs;
2595272c319SBarry Smith 
2609566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(pc->pmat, &bs));
261792fecdfSBarry Smith     if (bs > 1) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
2629566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(pc->mat, &mnull));
2635272c319SBarry Smith     if (mnull) {
2649566063dSJacob Faibussowitsch       PetscCall(PCHYPREResetNearNullSpace_Private(pc));
2659566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs));
2669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->hmnull));
2679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvec + 1, &jac->phmnull));
2685272c319SBarry Smith       for (i = 0; i < nvec; i++) {
2699566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(vecs[i]->map, &jac->hmnull[i]));
2709566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(vecs[i], jac->hmnull[i]));
271792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[i]->ij, (void **)&jac->phmnull[i]);
2725272c319SBarry Smith       }
2735272c319SBarry Smith       if (has_const) {
2749566063dSJacob Faibussowitsch         PetscCall(MatCreateVecs(pc->pmat, &jac->hmnull_constant, NULL));
2759566063dSJacob Faibussowitsch         PetscCall(VecSet(jac->hmnull_constant, 1));
2769566063dSJacob Faibussowitsch         PetscCall(VecNormalize(jac->hmnull_constant, NULL));
2779566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCreate(jac->hmnull_constant->map, &jac->hmnull[nvec]));
2789566063dSJacob Faibussowitsch         PetscCall(VecHYPRE_IJVectorCopy(jac->hmnull_constant, jac->hmnull[nvec]));
279792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJVectorGetObject, jac->hmnull[nvec]->ij, (void **)&jac->phmnull[nvec]);
2805272c319SBarry Smith         nvec++;
2815272c319SBarry Smith       }
282792fecdfSBarry Smith       PetscCallExternal(HYPRE_BoomerAMGSetInterpVectors, jac->hsolver, nvec, jac->phmnull);
2835272c319SBarry Smith       jac->n_hmnull = nvec;
2845272c319SBarry Smith     }
2854cb006feSStefano Zampini   }
286863406b8SStefano Zampini 
2874cb006feSStefano Zampini   /* special case for AMS */
2884cb006feSStefano Zampini   if (jac->setup == HYPRE_AMSSetup) {
2895ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
2905ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
2916bf688a0SCe Qin     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
292f1580f4eSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the edge constant vectors via PCHYPRESetEdgeConstantVectors() or the interpolation matrix via PCHYPRESetInterpolations()");
2936bf688a0SCe Qin     }
29448a46eb9SPierre Jolivet     if (jac->dim) PetscCallExternal(HYPRE_AMSSetDimension, jac->hsolver, jac->dim);
2955ac14e1cSStefano Zampini     if (jac->constants[0]) {
2965ac14e1cSStefano Zampini       HYPRE_ParVector ozz, zoz, zzo = NULL;
297792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[0]->ij, (void **)(&ozz));
298792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[1]->ij, (void **)(&zoz));
29948a46eb9SPierre Jolivet       if (jac->constants[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->constants[2]->ij, (void **)(&zzo));
300792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetEdgeConstantVectors, jac->hsolver, ozz, zoz, zzo);
3015ac14e1cSStefano Zampini     }
3025ac14e1cSStefano Zampini     if (jac->coords[0]) {
3035ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3045ac14e1cSStefano Zampini       coords[0] = NULL;
3055ac14e1cSStefano Zampini       coords[1] = NULL;
3065ac14e1cSStefano Zampini       coords[2] = NULL;
307792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
308792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
309792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
310792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3115ac14e1cSStefano Zampini     }
3125f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3135ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
314792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
315792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetDiscreteGradient, jac->hsolver, parcsr);
3165ac14e1cSStefano Zampini     if (jac->alpha_Poisson) {
3175ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->alpha_Poisson->data);
318792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
319792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetAlphaPoissonMatrix, jac->hsolver, parcsr);
3205ac14e1cSStefano Zampini     }
3215ac14e1cSStefano Zampini     if (jac->ams_beta_is_zero) {
322792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, NULL);
3235ac14e1cSStefano Zampini     } else if (jac->beta_Poisson) {
3245ac14e1cSStefano Zampini       hm = (Mat_HYPRE *)(jac->beta_Poisson->data);
325792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
326792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetBetaPoissonMatrix, jac->hsolver, parcsr);
327be14dc20SKerry Key     } else if (jac->ams_beta_is_zero_part) {
328be14dc20SKerry Key       if (jac->interior) {
329be14dc20SKerry Key         HYPRE_ParVector interior = NULL;
330be14dc20SKerry Key         PetscCallExternal(HYPRE_IJVectorGetObject, jac->interior->ij, (void **)(&interior));
331be14dc20SKerry Key         PetscCallExternal(HYPRE_AMSSetInteriorNodes, jac->hsolver, interior);
332be14dc20SKerry Key       } else {
333be14dc20SKerry Key         jac->ams_beta_is_zero_part = PETSC_FALSE;
334be14dc20SKerry Key       }
3355ac14e1cSStefano Zampini     }
3366bf688a0SCe Qin     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
3376bf688a0SCe Qin       PetscInt           i;
3386bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3396bf688a0SCe Qin       if (jac->ND_PiFull) {
3406bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
341792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
3426bf688a0SCe Qin       } else {
3436bf688a0SCe Qin         nd_parcsrfull = NULL;
3446bf688a0SCe Qin       }
3456bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3466bf688a0SCe Qin         if (jac->ND_Pi[i]) {
3476bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
348792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
3496bf688a0SCe Qin         } else {
3506bf688a0SCe Qin           nd_parcsr[i] = NULL;
3516bf688a0SCe Qin         }
3526bf688a0SCe Qin       }
353792fecdfSBarry Smith       PetscCallExternal(HYPRE_AMSSetInterpolations, jac->hsolver, nd_parcsrfull, nd_parcsr[0], nd_parcsr[1], nd_parcsr[2]);
3546bf688a0SCe Qin     }
3554cb006feSStefano Zampini   }
356863406b8SStefano Zampini   /* special case for ADS */
357863406b8SStefano Zampini   if (jac->setup == HYPRE_ADSSetup) {
3585ac14e1cSStefano Zampini     Mat_HYPRE         *hm;
3595ac14e1cSStefano Zampini     HYPRE_ParCSRMatrix parcsr;
3606bf688a0SCe 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])))) {
3616bf688a0SCe Qin       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
3629371c9d4SSatish 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");
3635f80ce2aSJacob Faibussowitsch     PetscCheck(jac->G, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
3645f80ce2aSJacob Faibussowitsch     PetscCheck(jac->C, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
3655ac14e1cSStefano Zampini     if (jac->coords[0]) {
3665ac14e1cSStefano Zampini       HYPRE_ParVector coords[3];
3675ac14e1cSStefano Zampini       coords[0] = NULL;
3685ac14e1cSStefano Zampini       coords[1] = NULL;
3695ac14e1cSStefano Zampini       coords[2] = NULL;
370792fecdfSBarry Smith       if (jac->coords[0]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[0]->ij, (void **)(&coords[0]));
371792fecdfSBarry Smith       if (jac->coords[1]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[1]->ij, (void **)(&coords[1]));
372792fecdfSBarry Smith       if (jac->coords[2]) PetscCallExternal(HYPRE_IJVectorGetObject, jac->coords[2]->ij, (void **)(&coords[2]));
373792fecdfSBarry Smith       PetscCallExternal(HYPRE_ADSSetCoordinateVectors, jac->hsolver, coords[0], coords[1], coords[2]);
3745ac14e1cSStefano Zampini     }
3755ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->G->data);
376792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
377792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteGradient, jac->hsolver, parcsr);
3785ac14e1cSStefano Zampini     hm = (Mat_HYPRE *)(jac->C->data);
379792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&parcsr));
380792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetDiscreteCurl, jac->hsolver, parcsr);
3816bf688a0SCe Qin     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
3826bf688a0SCe Qin       PetscInt           i;
3836bf688a0SCe Qin       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
3846bf688a0SCe Qin       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
3856bf688a0SCe Qin       if (jac->RT_PiFull) {
3866bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->RT_PiFull->data);
387792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsrfull));
3886bf688a0SCe Qin       } else {
3896bf688a0SCe Qin         rt_parcsrfull = NULL;
3906bf688a0SCe Qin       }
3916bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
3926bf688a0SCe Qin         if (jac->RT_Pi[i]) {
3936bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->RT_Pi[i]->data);
394792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&rt_parcsr[i]));
3956bf688a0SCe Qin         } else {
3966bf688a0SCe Qin           rt_parcsr[i] = NULL;
3976bf688a0SCe Qin         }
3986bf688a0SCe Qin       }
3996bf688a0SCe Qin       if (jac->ND_PiFull) {
4006bf688a0SCe Qin         hm = (Mat_HYPRE *)(jac->ND_PiFull->data);
401792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsrfull));
4026bf688a0SCe Qin       } else {
4036bf688a0SCe Qin         nd_parcsrfull = NULL;
4046bf688a0SCe Qin       }
4056bf688a0SCe Qin       for (i = 0; i < 3; ++i) {
4066bf688a0SCe Qin         if (jac->ND_Pi[i]) {
4076bf688a0SCe Qin           hm = (Mat_HYPRE *)(jac->ND_Pi[i]->data);
408792fecdfSBarry Smith           PetscCallExternal(HYPRE_IJMatrixGetObject, hm->ij, (void **)(&nd_parcsr[i]));
4096bf688a0SCe Qin         } else {
4106bf688a0SCe Qin           nd_parcsr[i] = NULL;
4116bf688a0SCe Qin         }
4126bf688a0SCe Qin       }
413792fecdfSBarry 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]);
4146bf688a0SCe Qin     }
415863406b8SStefano Zampini   }
416792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
417792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&bv);
418792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&xv);
41997c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
420792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
42197c1e3cbSStefano Zampini   PetscCall(PetscFPTrapPop());
4223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42316d9e3a6SLisandro Dalcin }
42416d9e3a6SLisandro Dalcin 
425d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
426d71ae5a4SJacob Faibussowitsch {
42716d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
42849a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
42916d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
43016d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
43116d9e3a6SLisandro Dalcin 
43216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4339566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4349566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4359566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4369566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4379566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
438792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
439792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
440792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4419371c9d4SSatish Balay   PetscStackCallExternalVoid(
4429371c9d4SSatish Balay     "Hypre solve", do {
4435f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4445f80ce2aSJacob Faibussowitsch       if (hierr) {
4455f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
44685245615SPierre Jolivet         HYPRE_ClearAllErrors();
4475f80ce2aSJacob Faibussowitsch       }
4485f80ce2aSJacob Faibussowitsch     } while (0));
44916d9e3a6SLisandro Dalcin 
45048a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4519566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45416d9e3a6SLisandro Dalcin }
45516d9e3a6SLisandro Dalcin 
45685245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
45785245615SPierre Jolivet {
45885245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
45985245615SPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)(jac->hpmat->data);
46085245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
46185245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
46285245615SPierre Jolivet   const PetscScalar  *b;
46385245615SPierre Jolivet   PetscScalar        *x;
46485245615SPierre Jolivet   PetscInt            m, N, lda;
46585245615SPierre Jolivet   hypre_Vector       *x_local;
46685245615SPierre Jolivet   PetscMemType        type;
46785245615SPierre Jolivet 
46885245615SPierre Jolivet   PetscFunctionBegin;
46985245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
47085245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
47185245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
47285245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
47385245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
47485245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
47585245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
47685245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
47785245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
47885245615SPierre Jolivet   PetscCheck(lda == m, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot use a LDA different than the number of local rows: % " PetscInt_FMT " != % " PetscInt_FMT, lda, m);
47985245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
48085245615SPierre Jolivet   PetscCheck(lda == m, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot use a LDA different than the number of local rows: % " PetscInt_FMT " != % " PetscInt_FMT, lda, m);
48185245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
48285245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
48385245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
48485245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
48585245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
48685245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
48785245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
48885245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
48985245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
49085245615SPierre Jolivet   PetscStackCallExternalVoid(
49185245615SPierre Jolivet     "Hypre solve", do {
49285245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
49385245615SPierre Jolivet       if (hierr) {
49485245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
49585245615SPierre Jolivet         HYPRE_ClearAllErrors();
49685245615SPierre Jolivet       }
49785245615SPierre Jolivet     } while (0));
49885245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
49985245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
50085245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
50185245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
50285245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
50385245615SPierre Jolivet }
50485245615SPierre Jolivet 
505d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
506d71ae5a4SJacob Faibussowitsch {
5078695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5088695de01SBarry Smith 
5098695de01SBarry Smith   PetscFunctionBegin;
5109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
5119566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
5129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
5139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
5149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
5159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
5169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
5179566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
5189566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
5199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
5209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
5219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
5229566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
5239566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
5249566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
5259566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
5269566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
5279566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
5289566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
529be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
5309566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
5315ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
532be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
5335ac14e1cSStefano Zampini   jac->dim                   = 0;
5343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5358695de01SBarry Smith }
5368695de01SBarry Smith 
537d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
538d71ae5a4SJacob Faibussowitsch {
53916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
54016d9e3a6SLisandro Dalcin 
54116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5429566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
543792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
5449566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
545db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
5469566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
547db6f9c32SMark Adams #endif
5489566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5499566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
55016d9e3a6SLisandro Dalcin 
5519566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5592e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
560be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5652e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56716d9e3a6SLisandro Dalcin }
56816d9e3a6SLisandro Dalcin 
569d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
570d71ae5a4SJacob Faibussowitsch {
57116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
572ace3abfcSBarry Smith   PetscBool flag;
57316d9e3a6SLisandro Dalcin 
57416d9e3a6SLisandro Dalcin   PetscFunctionBegin;
575d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
577792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
579792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
581792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
582d0609cedSBarry Smith   PetscOptionsHeadEnd();
5833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58416d9e3a6SLisandro Dalcin }
58516d9e3a6SLisandro Dalcin 
586d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
587d71ae5a4SJacob Faibussowitsch {
58816d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
589ace3abfcSBarry Smith   PetscBool iascii;
59016d9e3a6SLisandro Dalcin 
59116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
59316d9e3a6SLisandro Dalcin   if (iascii) {
5949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
59516d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
59663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
59716d9e3a6SLisandro Dalcin     } else {
5989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
59916d9e3a6SLisandro Dalcin     }
60016d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
6019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
60216d9e3a6SLisandro Dalcin     } else {
6039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
60416d9e3a6SLisandro Dalcin     }
60516d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
60663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
60716d9e3a6SLisandro Dalcin     } else {
6089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
60916d9e3a6SLisandro Dalcin     }
61016d9e3a6SLisandro Dalcin   }
6113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61216d9e3a6SLisandro Dalcin }
61316d9e3a6SLisandro Dalcin 
614d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
615d71ae5a4SJacob Faibussowitsch {
616db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6178bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
618db966c6cSHong Zhang 
619db966c6cSHong Zhang   PetscFunctionBegin;
620d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
6219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
622792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
6238bf83915SBarry Smith 
6249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
6258bf83915SBarry Smith   if (flag) {
6268bf83915SBarry Smith     PetscMPIInt size;
6278bf83915SBarry Smith 
6289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
6297827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
630792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
6318bf83915SBarry Smith   }
6328bf83915SBarry Smith 
6339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
6348bf83915SBarry Smith   if (flag) {
6358bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
636792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
6378bf83915SBarry Smith   }
638d0609cedSBarry Smith   PetscOptionsHeadEnd();
6393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
640db966c6cSHong Zhang }
641db966c6cSHong Zhang 
642d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
643d71ae5a4SJacob Faibussowitsch {
644db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
645db966c6cSHong Zhang   PetscBool iascii;
646db966c6cSHong Zhang 
647db966c6cSHong Zhang   PetscFunctionBegin;
6489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
649db966c6cSHong Zhang   if (iascii) {
6509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
651db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
65263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
653db966c6cSHong Zhang     } else {
6549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
655db966c6cSHong Zhang     }
6569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
65763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
658db966c6cSHong Zhang   }
6593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
660db966c6cSHong Zhang }
661db966c6cSHong Zhang 
662d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
663d71ae5a4SJacob Faibussowitsch {
66416d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
66549a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
66616d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
66716d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
66816d9e3a6SLisandro Dalcin 
66916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6709566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6719566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
67416d9e3a6SLisandro Dalcin 
675792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
676792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
677792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
67816d9e3a6SLisandro Dalcin 
6799371c9d4SSatish Balay   PetscStackCallExternalVoid(
6809371c9d4SSatish Balay     "Hypre Transpose solve", do {
6815f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6825f80ce2aSJacob Faibussowitsch       if (hierr) {
68316d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6845f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
68585245615SPierre Jolivet         HYPRE_ClearAllErrors();
6865f80ce2aSJacob Faibussowitsch       }
6875f80ce2aSJacob Faibussowitsch     } while (0));
68816d9e3a6SLisandro Dalcin 
6899566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6909566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
6913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69216d9e3a6SLisandro Dalcin }
69316d9e3a6SLisandro Dalcin 
694d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
695d71ae5a4SJacob Faibussowitsch {
696db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
697db6f9c32SMark Adams   PetscBool flag;
698db6f9c32SMark Adams 
699db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
700db6f9c32SMark Adams   PetscFunctionBegin;
701db6f9c32SMark Adams   if (jac->spgemm_type) {
7029566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
70328b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
7043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
705db6f9c32SMark Adams   } else {
7069566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
707db6f9c32SMark Adams   }
7089566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
709db6f9c32SMark Adams   if (flag) {
710792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
7113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
712db6f9c32SMark Adams   }
7139566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
714db6f9c32SMark Adams   if (flag) {
715792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
7163ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
717db6f9c32SMark Adams   }
718db6f9c32SMark Adams   jac->spgemm_type = NULL;
7192d6c3ceeSStefano Zampini   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEMM type %s; Choices are cusparse, hypre", name);
720db6f9c32SMark Adams #endif
721db6f9c32SMark Adams }
722db6f9c32SMark Adams 
723d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
724d71ae5a4SJacob Faibussowitsch {
725db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
726db6f9c32SMark Adams 
727db6f9c32SMark Adams   PetscFunctionBegin;
728db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
729db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
730db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
731db6f9c32SMark Adams #endif
7323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
733db6f9c32SMark Adams }
734db6f9c32SMark Adams 
73516d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
7360f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
73716d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
73865de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
7396a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[] = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
7409371c9d4SSatish 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"};
7419371c9d4SSatish 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"};
742d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
743d71ae5a4SJacob Faibussowitsch {
74416d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
74522e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
746ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
74716d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
748589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
749db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
75016d9e3a6SLisandro Dalcin 
75116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
752d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
7539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
75416d9e3a6SLisandro Dalcin   if (flg) {
7554336a9eeSBarry Smith     jac->cycletype = indx + 1;
756792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
75716d9e3a6SLisandro Dalcin   }
7589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
75916d9e3a6SLisandro Dalcin   if (flg) {
76063a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
761792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
76216d9e3a6SLisandro Dalcin   }
7639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
76416d9e3a6SLisandro Dalcin   if (flg) {
76563a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
766792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
76716d9e3a6SLisandro Dalcin   }
7689566063dSJacob 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));
76916d9e3a6SLisandro Dalcin   if (flg) {
77008401ef6SPierre 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);
771792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
77216d9e3a6SLisandro Dalcin   }
77322e51d31SStefano Zampini   bs = 1;
77448a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
77648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
77716d9e3a6SLisandro Dalcin 
7789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
77916d9e3a6SLisandro Dalcin   if (flg) {
78008401ef6SPierre 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);
781792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
78216d9e3a6SLisandro Dalcin   }
78316d9e3a6SLisandro Dalcin 
7849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7850f1074feSSatish Balay   if (flg) {
78663a3b9bcSJacob 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);
787792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7880f1074feSSatish Balay   }
7890f1074feSSatish Balay 
7909566063dSJacob 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));
791792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7920f1074feSSatish Balay 
7939566063dSJacob 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));
7940f1074feSSatish Balay   if (flg) {
79563a3b9bcSJacob 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);
796792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7970f1074feSSatish Balay   }
7980f1074feSSatish Balay 
7999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
80016d9e3a6SLisandro Dalcin   if (flg) {
80108401ef6SPierre 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);
802792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
80316d9e3a6SLisandro Dalcin   }
8049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
80516d9e3a6SLisandro Dalcin   if (flg) {
80608401ef6SPierre 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);
80708401ef6SPierre 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);
808792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
80916d9e3a6SLisandro Dalcin   }
81016d9e3a6SLisandro Dalcin 
81116d9e3a6SLisandro Dalcin   /* Grid sweeps */
8129566063dSJacob 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));
81316d9e3a6SLisandro Dalcin   if (flg) {
814792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
81516d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
81616d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
8170f1074feSSatish Balay     jac->gridsweeps[1] = indx;
8180f1074feSSatish Balay     /*defaults coarse to 1 */
8190f1074feSSatish Balay     jac->gridsweeps[2] = 1;
82016d9e3a6SLisandro Dalcin   }
8219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
82248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
8239566063dSJacob 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));
82448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
8259566063dSJacob 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));
82648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
8279566063dSJacob 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));
82848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
8299566063dSJacob 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));
83048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
8319566063dSJacob 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));
83248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
8339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
83416d9e3a6SLisandro Dalcin   if (flg) {
835792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
8360f1074feSSatish Balay     jac->gridsweeps[0] = indx;
83716d9e3a6SLisandro Dalcin   }
8389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
83916d9e3a6SLisandro Dalcin   if (flg) {
840792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
8410f1074feSSatish Balay     jac->gridsweeps[1] = indx;
84216d9e3a6SLisandro Dalcin   }
8439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
84416d9e3a6SLisandro Dalcin   if (flg) {
845792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
8460f1074feSSatish Balay     jac->gridsweeps[2] = indx;
84716d9e3a6SLisandro Dalcin   }
84816d9e3a6SLisandro Dalcin 
8496a251517SEike Mueller   /* Smooth type */
850dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8516a251517SEike Mueller   if (flg) {
8526a251517SEike Mueller     jac->smoothtype = indx;
853792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8548131ecf7SEike Mueller     jac->smoothnumlevels = 25;
855792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8568131ecf7SEike Mueller   }
8578131ecf7SEike Mueller 
8588131ecf7SEike Mueller   /* Number of smoothing levels */
8599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8608131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8618131ecf7SEike Mueller     jac->smoothnumlevels = indx;
862792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8636a251517SEike Mueller   }
8646a251517SEike Mueller 
8651810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8671810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8681810e44eSEike Mueller     jac->eu_level = indx;
869792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8701810e44eSEike Mueller   }
8711810e44eSEike Mueller 
8721810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8731810e44eSEike Mueller   double droptolerance;
8749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8751810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8761810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
877792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8781810e44eSEike Mueller   }
8791810e44eSEike Mueller 
8801810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8821810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8831810e44eSEike Mueller     jac->eu_bj = tmp_truth;
884792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8851810e44eSEike Mueller   }
8861810e44eSEike Mueller 
88716d9e3a6SLisandro Dalcin   /* Relax type */
888dd39110bSPierre 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));
88916d9e3a6SLisandro Dalcin   if (flg) {
8900f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
891792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8920f1074feSSatish Balay     /* by default, coarse type set to 9 */
8930f1074feSSatish Balay     jac->relaxtype[2] = 9;
894792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
89516d9e3a6SLisandro Dalcin   }
896dd39110bSPierre 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));
89716d9e3a6SLisandro Dalcin   if (flg) {
89816d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
899792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
90016d9e3a6SLisandro Dalcin   }
901dd39110bSPierre 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));
90216d9e3a6SLisandro Dalcin   if (flg) {
9030f1074feSSatish Balay     jac->relaxtype[1] = indx;
904792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
90516d9e3a6SLisandro Dalcin   }
906dd39110bSPierre 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));
90716d9e3a6SLisandro Dalcin   if (flg) {
9080f1074feSSatish Balay     jac->relaxtype[2] = indx;
909792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
91016d9e3a6SLisandro Dalcin   }
91116d9e3a6SLisandro Dalcin 
91216d9e3a6SLisandro Dalcin   /* Relaxation Weight */
9139566063dSJacob 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));
91416d9e3a6SLisandro Dalcin   if (flg) {
915792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
91616d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
91716d9e3a6SLisandro Dalcin   }
91816d9e3a6SLisandro Dalcin 
91916d9e3a6SLisandro Dalcin   n         = 2;
92016d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
92216d9e3a6SLisandro Dalcin   if (flg) {
9230fdf79fbSJacob Faibussowitsch     PetscCheck(n == 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT, n);
92416d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
925792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
92616d9e3a6SLisandro Dalcin   }
92716d9e3a6SLisandro Dalcin 
92816d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
9299566063dSJacob 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));
93016d9e3a6SLisandro Dalcin   if (flg) {
931792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
93216d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
93316d9e3a6SLisandro Dalcin   }
93416d9e3a6SLisandro Dalcin 
93516d9e3a6SLisandro Dalcin   n         = 2;
93616d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9379566063dSJacob 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));
93816d9e3a6SLisandro Dalcin   if (flg) {
9390fdf79fbSJacob Faibussowitsch     PetscCheck(n == 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %" PetscInt_FMT, n);
94016d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
941792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
94216d9e3a6SLisandro Dalcin   }
94316d9e3a6SLisandro Dalcin 
94416d9e3a6SLisandro Dalcin   /* the Relax Order */
9459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
94616d9e3a6SLisandro Dalcin 
9478afaa268SBarry Smith   if (flg && tmp_truth) {
94816d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
949792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
95016d9e3a6SLisandro Dalcin   }
951dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
95216d9e3a6SLisandro Dalcin   if (flg) {
95316d9e3a6SLisandro Dalcin     jac->measuretype = indx;
954792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
95516d9e3a6SLisandro Dalcin   }
9560f1074feSSatish Balay   /* update list length 3/07 */
957dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
95816d9e3a6SLisandro Dalcin   if (flg) {
95916d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
960792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
96116d9e3a6SLisandro Dalcin   }
9620f1074feSSatish Balay 
9639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
96448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
96648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
967db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
968db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
969dd39110bSPierre 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));
9702d6c3ceeSStefano Zampini   #if defined(PETSC_HAVE_HYPRE_DEVICE)
971db6f9c32SMark Adams   if (!flg) indx = 0;
9729566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
9732d6c3ceeSStefano Zampini   #else
9742d6c3ceeSStefano Zampini   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, "hypre"));
9752d6c3ceeSStefano Zampini   #endif
976db6f9c32SMark Adams #endif
977589dcaf0SStefano Zampini   /* AIR */
978589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9799566063dSJacob 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));
980792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
981589dcaf0SStefano Zampini   if (jac->Rtype) {
982589dcaf0SStefano 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 */
983589dcaf0SStefano Zampini 
9849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
985792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
986589dcaf0SStefano Zampini 
9879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
988792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
989589dcaf0SStefano Zampini 
9909566063dSJacob 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));
991792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
992589dcaf0SStefano Zampini 
9939566063dSJacob 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));
994792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
995589dcaf0SStefano Zampini   }
996589dcaf0SStefano Zampini #endif
997589dcaf0SStefano Zampini 
998ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
99963a3b9bcSJacob 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);
1000ecae95adSPierre Jolivet #endif
1001ecae95adSPierre Jolivet 
10020f1074feSSatish Balay   /* new 3/07 */
1003dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
1004589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
1005589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1006792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
10070f1074feSSatish Balay   }
10080f1074feSSatish Balay 
10099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
101016d9e3a6SLisandro Dalcin   if (flg) {
1011b96a4a96SBarry Smith     level = 3;
10129566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
10132fa5cd67SKarl Rupp 
1014b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1015792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
10162ae77aedSBarry Smith   }
10172ae77aedSBarry Smith 
10189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
10192ae77aedSBarry Smith   if (flg) {
1020b96a4a96SBarry Smith     level = 3;
10219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
10222fa5cd67SKarl Rupp 
1023b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1024792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
102516d9e3a6SLisandro Dalcin   }
10268f87f92bSBarry Smith 
10279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10288f87f92bSBarry Smith   if (flg && tmp_truth) {
10298f87f92bSBarry Smith     PetscInt tmp_int;
10309566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
10318f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1032792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1033792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1034792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1035792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
10368f87f92bSBarry Smith   }
10378f87f92bSBarry Smith 
10389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1039792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1040589dcaf0SStefano Zampini 
1041589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1042dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1043589dcaf0SStefano Zampini   if (flg) {
1044589dcaf0SStefano Zampini     jac->symt = indx;
1045792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1046589dcaf0SStefano Zampini   }
1047589dcaf0SStefano Zampini 
1048d0609cedSBarry Smith   PetscOptionsHeadEnd();
10493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105016d9e3a6SLisandro Dalcin }
105116d9e3a6SLisandro Dalcin 
1052d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
1053d71ae5a4SJacob Faibussowitsch {
105416d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
10552cf14000SStefano Zampini   HYPRE_Int oits;
105616d9e3a6SLisandro Dalcin 
105716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10589566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1059792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1060792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
106116d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10629566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
106316d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1064792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10654d0a8057SBarry Smith   *outits = oits;
10664d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10674d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1068792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1069792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
10703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107116d9e3a6SLisandro Dalcin }
107216d9e3a6SLisandro Dalcin 
1073d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1074d71ae5a4SJacob Faibussowitsch {
107516d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1076ace3abfcSBarry Smith   PetscBool iascii;
107716d9e3a6SLisandro Dalcin 
107816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
108016d9e3a6SLisandro Dalcin   if (iascii) {
10819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
108363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
108463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
108863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
108948a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
109063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
109163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
10920f1074feSSatish Balay 
10939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
109416d9e3a6SLisandro Dalcin 
109563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
109663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
109763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
109816d9e3a6SLisandro Dalcin 
10999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
11009566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
11019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
110216d9e3a6SLisandro Dalcin 
11039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
11049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
110516d9e3a6SLisandro Dalcin 
110616d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
11079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
110816d9e3a6SLisandro Dalcin     } else {
11099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
111016d9e3a6SLisandro Dalcin     }
11116a251517SEike Mueller     if (jac->smoothtype != -1) {
11129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
111363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
11147e352d70SEike Mueller     } else {
11159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
11161810e44eSEike Mueller     }
11171810e44eSEike Mueller     if (jac->smoothtype == 3) {
111863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
11199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
112063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
11216a251517SEike Mueller     }
11229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
11239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
112548a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
11265272c319SBarry Smith     if (jac->vec_interp_variant) {
112763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
112863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
11299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
11308f87f92bSBarry Smith     }
113148a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1132db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
11339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
11342d6c3ceeSStefano Zampini #else
11352d6c3ceeSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", "hypre"));
1136db6f9c32SMark Adams #endif
1137589dcaf0SStefano Zampini     /* AIR */
1138589dcaf0SStefano Zampini     if (jac->Rtype) {
113963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
11409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
11419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
11429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
114363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1144589dcaf0SStefano Zampini     }
114516d9e3a6SLisandro Dalcin   }
11463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
114716d9e3a6SLisandro Dalcin }
114816d9e3a6SLisandro Dalcin 
1149d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1150d71ae5a4SJacob Faibussowitsch {
115116d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
11524ddd07fcSJed Brown   PetscInt    indx;
1153ace3abfcSBarry Smith   PetscBool   flag;
115416d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
115516d9e3a6SLisandro Dalcin 
115616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1157d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
11589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
11599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1160792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
116116d9e3a6SLisandro Dalcin 
11629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1163792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
116416d9e3a6SLisandro Dalcin 
11659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1166792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
116716d9e3a6SLisandro Dalcin 
11689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1169792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
117016d9e3a6SLisandro Dalcin 
11719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1172792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
117316d9e3a6SLisandro Dalcin 
1174dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
117516d9e3a6SLisandro Dalcin   if (flag) {
117616d9e3a6SLisandro Dalcin     jac->symt = indx;
1177792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
117816d9e3a6SLisandro Dalcin   }
117916d9e3a6SLisandro Dalcin 
1180d0609cedSBarry Smith   PetscOptionsHeadEnd();
11813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118216d9e3a6SLisandro Dalcin }
118316d9e3a6SLisandro Dalcin 
1184d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1185d71ae5a4SJacob Faibussowitsch {
118616d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1187ace3abfcSBarry Smith   PetscBool   iascii;
1188feb237baSPierre Jolivet   const char *symt = 0;
118916d9e3a6SLisandro Dalcin 
119016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
119216d9e3a6SLisandro Dalcin   if (iascii) {
11939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
119463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
11959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
11969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
11979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
11989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
11999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
12002fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
12012fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
12022fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
120363a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
12049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
120516d9e3a6SLisandro Dalcin   }
12063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120716d9e3a6SLisandro Dalcin }
1208f1580f4eSBarry Smith 
1209d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1210d71ae5a4SJacob Faibussowitsch {
12114cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12124cb006feSStefano Zampini   PetscInt  n;
12134cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
12144cb006feSStefano Zampini 
12154cb006feSStefano Zampini   PetscFunctionBegin;
1216d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
12179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1218792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
12199566063dSJacob 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));
1220792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
12219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1222792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
12239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1224792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
12259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12269566063dSJacob 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));
12279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
122948a46eb9SPierre 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);
12309566063dSJacob 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));
12314cb006feSStefano Zampini   n = 5;
12329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
12334cb006feSStefano Zampini   if (flag || flag2) {
1234792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1235863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1236863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
12379371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1238a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
12394cb006feSStefano Zampini   }
12409566063dSJacob 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));
12414cb006feSStefano Zampini   n = 5;
12429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
12434cb006feSStefano Zampini   if (flag || flag2) {
1244792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1245863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1246863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
12479371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1248a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
12494cb006feSStefano Zampini   }
12509566063dSJacob 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));
125123df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1252792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
125323df4f25SStefano Zampini   }
1254d0609cedSBarry Smith   PetscOptionsHeadEnd();
12553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12564cb006feSStefano Zampini }
12574cb006feSStefano Zampini 
1258d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1259d71ae5a4SJacob Faibussowitsch {
12604cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12614cb006feSStefano Zampini   PetscBool iascii;
12624cb006feSStefano Zampini 
12634cb006feSStefano Zampini   PetscFunctionBegin;
12649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
12654cb006feSStefano Zampini   if (iascii) {
12669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
126763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
126863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
126963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
127063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
127163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
127263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
127363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12744cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12764cb006feSStefano Zampini     } else {
12779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12784cb006feSStefano Zampini     }
127963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
128063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
128163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
128263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
128363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
128463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12854cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12864cb006feSStefano Zampini       if (jac->beta_Poisson) {
12879566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
12884cb006feSStefano Zampini       } else {
12899566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
12904cb006feSStefano Zampini       }
129163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
129263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
129363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
129463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
129563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
129663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
129748a46eb9SPierre 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));
129823df4f25SStefano Zampini     } else {
12999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
13004cb006feSStefano Zampini     }
13014cb006feSStefano Zampini   }
13023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13034cb006feSStefano Zampini }
13044cb006feSStefano Zampini 
1305d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1306d71ae5a4SJacob Faibussowitsch {
1307863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1308863406b8SStefano Zampini   PetscInt  n;
1309863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1310863406b8SStefano Zampini 
1311863406b8SStefano Zampini   PetscFunctionBegin;
1312d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
13139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1314792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
13159566063dSJacob 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));
1316792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
13179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1318792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
13199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1320792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
13219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
13229566063dSJacob 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));
13239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
13249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
132548a46eb9SPierre 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);
13269566063dSJacob 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));
1327863406b8SStefano Zampini   n = 5;
13289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
13299566063dSJacob 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));
1330863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1331792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1332863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1333863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1334863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
13359371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1336a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1337863406b8SStefano Zampini   }
13389566063dSJacob 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));
1339863406b8SStefano Zampini   n = 5;
13409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1341863406b8SStefano Zampini   if (flag || flag2) {
1342792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1343863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1344863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
13459371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1346a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1347863406b8SStefano Zampini   }
1348d0609cedSBarry Smith   PetscOptionsHeadEnd();
13493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1350863406b8SStefano Zampini }
1351863406b8SStefano Zampini 
1352d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1353d71ae5a4SJacob Faibussowitsch {
1354863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1355863406b8SStefano Zampini   PetscBool iascii;
1356863406b8SStefano Zampini 
1357863406b8SStefano Zampini   PetscFunctionBegin;
13589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1359863406b8SStefano Zampini   if (iascii) {
13609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
136163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
136263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
136363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
136463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
136563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
136663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
136763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
136963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
137063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
137163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
137263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
137363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
137463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
137563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
137763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
137863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
137963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
138063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
138163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
138263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1383863406b8SStefano Zampini   }
13843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1385863406b8SStefano Zampini }
1386863406b8SStefano Zampini 
1387d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1388d71ae5a4SJacob Faibussowitsch {
13894cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13905ac14e1cSStefano Zampini   PetscBool ishypre;
13914cb006feSStefano Zampini 
13924cb006feSStefano Zampini   PetscFunctionBegin;
13939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
13945ac14e1cSStefano Zampini   if (ishypre) {
13959566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
13969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13975ac14e1cSStefano Zampini     jac->G = G;
13985ac14e1cSStefano Zampini   } else {
13999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
14009566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
14015ac14e1cSStefano Zampini   }
14023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14034cb006feSStefano Zampini }
14044cb006feSStefano Zampini 
14054cb006feSStefano Zampini /*@
1406f1580f4eSBarry Smith    PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
14074cb006feSStefano Zampini 
1408c3339decSBarry Smith    Collective
14094cb006feSStefano Zampini 
14104cb006feSStefano Zampini    Input Parameters:
14114cb006feSStefano Zampini +  pc - the preconditioning context
14124cb006feSStefano Zampini -  G - the discrete gradient
14134cb006feSStefano Zampini 
14144cb006feSStefano Zampini    Level: intermediate
14154cb006feSStefano Zampini 
141695452b02SPatrick Sanan    Notes:
141795452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1418147403d9SBarry Smith 
1419863406b8SStefano 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
14204cb006feSStefano Zampini 
1421f1580f4eSBarry Smith    Developer Note:
1422f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1423f1580f4eSBarry Smith 
1424f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
14254cb006feSStefano Zampini @*/
1426d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1427d71ae5a4SJacob Faibussowitsch {
14284cb006feSStefano Zampini   PetscFunctionBegin;
14294cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14304cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
14314cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1432cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
14333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14344cb006feSStefano Zampini }
14354cb006feSStefano Zampini 
1436d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1437d71ae5a4SJacob Faibussowitsch {
1438863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14395ac14e1cSStefano Zampini   PetscBool ishypre;
1440863406b8SStefano Zampini 
1441863406b8SStefano Zampini   PetscFunctionBegin;
14429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
14435ac14e1cSStefano Zampini   if (ishypre) {
14449566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
14459566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14465ac14e1cSStefano Zampini     jac->C = C;
14475ac14e1cSStefano Zampini   } else {
14489566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14499566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
14505ac14e1cSStefano Zampini   }
14513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1452863406b8SStefano Zampini }
1453863406b8SStefano Zampini 
1454863406b8SStefano Zampini /*@
1455f1580f4eSBarry Smith    PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1456863406b8SStefano Zampini 
1457c3339decSBarry Smith    Collective
1458863406b8SStefano Zampini 
1459863406b8SStefano Zampini    Input Parameters:
1460863406b8SStefano Zampini +  pc - the preconditioning context
1461863406b8SStefano Zampini -  C - the discrete curl
1462863406b8SStefano Zampini 
1463863406b8SStefano Zampini    Level: intermediate
1464863406b8SStefano Zampini 
146595452b02SPatrick Sanan    Notes:
146695452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1467147403d9SBarry Smith 
1468863406b8SStefano 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
1469863406b8SStefano Zampini 
1470f1580f4eSBarry Smith    Developer Note:
1471f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1472f1580f4eSBarry Smith 
1473f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1474f1580f4eSBarry Smith 
1475f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1476863406b8SStefano Zampini @*/
1477d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1478d71ae5a4SJacob Faibussowitsch {
1479863406b8SStefano Zampini   PetscFunctionBegin;
1480863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1481863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1482863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1483cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
14843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1485863406b8SStefano Zampini }
1486863406b8SStefano Zampini 
1487d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1488d71ae5a4SJacob Faibussowitsch {
14896bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14906bf688a0SCe Qin   PetscBool ishypre;
14916bf688a0SCe Qin   PetscInt  i;
14926bf688a0SCe Qin   PetscFunctionBegin;
14936bf688a0SCe Qin 
14949566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14966bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
14979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14996bf688a0SCe Qin   }
15006bf688a0SCe Qin 
15016bf688a0SCe Qin   jac->dim = dim;
15026bf688a0SCe Qin   if (RT_PiFull) {
15039566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
15046bf688a0SCe Qin     if (ishypre) {
15059566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
15066bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
15076bf688a0SCe Qin     } else {
15089566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
15096bf688a0SCe Qin     }
15106bf688a0SCe Qin   }
15116bf688a0SCe Qin   if (RT_Pi) {
15126bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15136bf688a0SCe Qin       if (RT_Pi[i]) {
15149566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
15156bf688a0SCe Qin         if (ishypre) {
15169566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15176bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15186bf688a0SCe Qin         } else {
15199566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
15206bf688a0SCe Qin         }
15216bf688a0SCe Qin       }
15226bf688a0SCe Qin     }
15236bf688a0SCe Qin   }
15246bf688a0SCe Qin   if (ND_PiFull) {
15259566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
15266bf688a0SCe Qin     if (ishypre) {
15279566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15286bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15296bf688a0SCe Qin     } else {
15309566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
15316bf688a0SCe Qin     }
15326bf688a0SCe Qin   }
15336bf688a0SCe Qin   if (ND_Pi) {
15346bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15356bf688a0SCe Qin       if (ND_Pi[i]) {
15369566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
15376bf688a0SCe Qin         if (ishypre) {
15389566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
15396bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
15406bf688a0SCe Qin         } else {
15419566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
15426bf688a0SCe Qin         }
15436bf688a0SCe Qin       }
15446bf688a0SCe Qin     }
15456bf688a0SCe Qin   }
15466bf688a0SCe Qin 
15473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15486bf688a0SCe Qin }
15496bf688a0SCe Qin 
15506bf688a0SCe Qin /*@
1551f1580f4eSBarry Smith    PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
15526bf688a0SCe Qin 
1553c3339decSBarry Smith    Collective
15546bf688a0SCe Qin 
15556bf688a0SCe Qin    Input Parameters:
15566bf688a0SCe Qin +  pc - the preconditioning context
15572fe279fdSBarry Smith .  dim - the dimension of the problem, only used in AMS
15582fe279fdSBarry Smith .  RT_PiFull - Raviart-Thomas interpolation matrix
15592fe279fdSBarry Smith .  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
15602fe279fdSBarry Smith .  ND_PiFull - Nedelec interpolation matrix
15616bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
15626bf688a0SCe Qin 
1563f1580f4eSBarry Smith    Level: intermediate
1564f1580f4eSBarry Smith 
156595452b02SPatrick Sanan    Notes:
156695452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1567147403d9SBarry Smith 
15686bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1569147403d9SBarry Smith 
1570f1580f4eSBarry Smith    Developer Note:
1571f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
15726bf688a0SCe Qin 
1573f1580f4eSBarry Smith .seealso: `PCHYPRE`
15746bf688a0SCe Qin @*/
1575d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1576d71ae5a4SJacob Faibussowitsch {
15776bf688a0SCe Qin   PetscInt i;
15786bf688a0SCe Qin 
15796bf688a0SCe Qin   PetscFunctionBegin;
15806bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15816bf688a0SCe Qin   if (RT_PiFull) {
15826bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
15836bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
15846bf688a0SCe Qin   }
15856bf688a0SCe Qin   if (RT_Pi) {
15866bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
15876bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15886bf688a0SCe Qin       if (RT_Pi[i]) {
15896bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
15906bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
15916bf688a0SCe Qin       }
15926bf688a0SCe Qin     }
15936bf688a0SCe Qin   }
15946bf688a0SCe Qin   if (ND_PiFull) {
15956bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
15966bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
15976bf688a0SCe Qin   }
15986bf688a0SCe Qin   if (ND_Pi) {
15996bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
16006bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
16016bf688a0SCe Qin       if (ND_Pi[i]) {
16026bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
16036bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
16046bf688a0SCe Qin       }
16056bf688a0SCe Qin     }
16066bf688a0SCe Qin   }
1607cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
16083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16096bf688a0SCe Qin }
16106bf688a0SCe Qin 
1611d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1612d71ae5a4SJacob Faibussowitsch {
16134cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16145ac14e1cSStefano Zampini   PetscBool ishypre;
16154cb006feSStefano Zampini 
16164cb006feSStefano Zampini   PetscFunctionBegin;
16179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
16185ac14e1cSStefano Zampini   if (ishypre) {
16195ac14e1cSStefano Zampini     if (isalpha) {
16209566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16219566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16225ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16235ac14e1cSStefano Zampini     } else {
16245ac14e1cSStefano Zampini       if (A) {
16259566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16265ac14e1cSStefano Zampini       } else {
16275ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16285ac14e1cSStefano Zampini       }
16299566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16305ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16315ac14e1cSStefano Zampini     }
16325ac14e1cSStefano Zampini   } else {
16335ac14e1cSStefano Zampini     if (isalpha) {
16349566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16359566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
16365ac14e1cSStefano Zampini     } else {
16375ac14e1cSStefano Zampini       if (A) {
16389566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16399566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
16405ac14e1cSStefano Zampini       } else {
16419566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16425ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16435ac14e1cSStefano Zampini       }
16445ac14e1cSStefano Zampini     }
16455ac14e1cSStefano Zampini   }
16463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16474cb006feSStefano Zampini }
16484cb006feSStefano Zampini 
16494cb006feSStefano Zampini /*@
1650f1580f4eSBarry Smith    PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
16514cb006feSStefano Zampini 
1652c3339decSBarry Smith    Collective
16534cb006feSStefano Zampini 
16544cb006feSStefano Zampini    Input Parameters:
16554cb006feSStefano Zampini +  pc - the preconditioning context
16564cb006feSStefano Zampini -  A - the matrix
16574cb006feSStefano Zampini 
16584cb006feSStefano Zampini    Level: intermediate
16594cb006feSStefano Zampini 
1660f1580f4eSBarry Smith    Note:
166195452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16624cb006feSStefano Zampini 
1663f1580f4eSBarry Smith    Developer Note:
1664f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1665f1580f4eSBarry Smith 
1666f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1667f1580f4eSBarry Smith 
1668f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16694cb006feSStefano Zampini @*/
1670d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1671d71ae5a4SJacob Faibussowitsch {
16724cb006feSStefano Zampini   PetscFunctionBegin;
16734cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16744cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16754cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1676cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
16773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16784cb006feSStefano Zampini }
16794cb006feSStefano Zampini 
16804cb006feSStefano Zampini /*@
1681f1580f4eSBarry Smith    PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
16824cb006feSStefano Zampini 
1683c3339decSBarry Smith    Collective
16844cb006feSStefano Zampini 
16854cb006feSStefano Zampini    Input Parameters:
16864cb006feSStefano Zampini +  pc - the preconditioning context
1687f1580f4eSBarry Smith -  A - the matrix, or NULL to turn it off
16884cb006feSStefano Zampini 
16894cb006feSStefano Zampini    Level: intermediate
16904cb006feSStefano Zampini 
1691f1580f4eSBarry Smith    Note:
169295452b02SPatrick Sanan    A should be obtained by discretizing the Poisson problem with linear finite elements.
16934cb006feSStefano Zampini 
1694f1580f4eSBarry Smith    Developer Note:
1695f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1696f1580f4eSBarry Smith 
1697f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1698f1580f4eSBarry Smith 
1699f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17004cb006feSStefano Zampini @*/
1701d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1702d71ae5a4SJacob Faibussowitsch {
17034cb006feSStefano Zampini   PetscFunctionBegin;
17044cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17054cb006feSStefano Zampini   if (A) {
17064cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
17074cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
17084cb006feSStefano Zampini   }
1709cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
17103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17114cb006feSStefano Zampini }
17124cb006feSStefano Zampini 
1713d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1714d71ae5a4SJacob Faibussowitsch {
17154cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17164cb006feSStefano Zampini 
17174cb006feSStefano Zampini   PetscFunctionBegin;
17184cb006feSStefano Zampini   /* throw away any vector if already set */
17199566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17209566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17219566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17229566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
17239566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
17249566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
17259566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
17265ac14e1cSStefano Zampini   jac->dim = 2;
17274cb006feSStefano Zampini   if (zzo) {
17289566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
17299566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
17305ac14e1cSStefano Zampini     jac->dim++;
17314cb006feSStefano Zampini   }
17323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17334cb006feSStefano Zampini }
17344cb006feSStefano Zampini 
17354cb006feSStefano Zampini /*@
1736f1580f4eSBarry Smith    PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
17374cb006feSStefano Zampini 
1738c3339decSBarry Smith    Collective
17394cb006feSStefano Zampini 
17404cb006feSStefano Zampini    Input Parameters:
17414cb006feSStefano Zampini +  pc - the preconditioning context
17422fe279fdSBarry Smith .  ozz - vector representing (1,0,0) (or (1,0) in 2D)
17432fe279fdSBarry Smith .  zoz - vector representing (0,1,0) (or (0,1) in 2D)
17444cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
17454cb006feSStefano Zampini 
17464cb006feSStefano Zampini    Level: intermediate
17474cb006feSStefano Zampini 
1748f1580f4eSBarry Smith    Developer Note:
1749f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1750f1580f4eSBarry Smith 
1751f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17524cb006feSStefano Zampini @*/
1753d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1754d71ae5a4SJacob Faibussowitsch {
17554cb006feSStefano Zampini   PetscFunctionBegin;
17564cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17574cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
17584cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
17594cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
17604cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
17614cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
17624cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1763cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
17643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17654cb006feSStefano Zampini }
17664cb006feSStefano Zampini 
1767d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1768d71ae5a4SJacob Faibussowitsch {
1769be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1770be14dc20SKerry Key 
1771be14dc20SKerry Key   PetscFunctionBegin;
1772be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1773be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1774be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1775be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
17763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1777be14dc20SKerry Key }
1778be14dc20SKerry Key 
1779be14dc20SKerry Key /*@
1780f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1781be14dc20SKerry Key 
1782c3339decSBarry Smith    Collective
1783be14dc20SKerry Key 
1784be14dc20SKerry Key    Input Parameters:
1785be14dc20SKerry Key +  pc - the preconditioning context
1786be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1787be14dc20SKerry Key 
1788be14dc20SKerry Key    Level: intermediate
1789be14dc20SKerry Key 
1790be14dc20SKerry Key    Note:
1791f1580f4eSBarry Smith    This calls `HYPRE_AMSSetInteriorNodes()`
1792f1580f4eSBarry Smith 
1793f1580f4eSBarry Smith    Developer Note:
1794f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1795f1580f4eSBarry Smith 
1796f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1797be14dc20SKerry Key @*/
1798d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1799d71ae5a4SJacob Faibussowitsch {
1800be14dc20SKerry Key   PetscFunctionBegin;
1801be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1802be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1803be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1804be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
18053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1806be14dc20SKerry Key }
1807be14dc20SKerry Key 
1808d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1809d71ae5a4SJacob Faibussowitsch {
18104cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18114cb006feSStefano Zampini   Vec       tv;
18124cb006feSStefano Zampini   PetscInt  i;
18134cb006feSStefano Zampini 
18144cb006feSStefano Zampini   PetscFunctionBegin;
18154cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
18169566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
18179566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
18189566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
18195ac14e1cSStefano Zampini   jac->dim = dim;
18205ac14e1cSStefano Zampini 
18214cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18229566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
18239566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
18249566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
18254cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
18264cb006feSStefano Zampini     PetscScalar *array;
18274cb006feSStefano Zampini     PetscInt     j;
18284cb006feSStefano Zampini 
18299566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
18309566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
18316ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
18329566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
18339566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
18344cb006feSStefano Zampini   }
18359566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
18363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18374cb006feSStefano Zampini }
18384cb006feSStefano Zampini 
1839d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1840d71ae5a4SJacob Faibussowitsch {
184116d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
184216d9e3a6SLisandro Dalcin 
184316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
184416d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
18453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
184616d9e3a6SLisandro Dalcin }
184716d9e3a6SLisandro Dalcin 
1848d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1849d71ae5a4SJacob Faibussowitsch {
185016d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1851ace3abfcSBarry Smith   PetscBool flag;
185216d9e3a6SLisandro Dalcin 
185316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
185416d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
18559566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
18565f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
18573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
185816d9e3a6SLisandro Dalcin   } else {
18599566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
186016d9e3a6SLisandro Dalcin   }
186116d9e3a6SLisandro Dalcin 
186216d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
186316d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
186416d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
186516d9e3a6SLisandro Dalcin 
18669566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
186716d9e3a6SLisandro Dalcin   if (flag) {
18689566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1869792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
187016d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
187116d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
187216d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
187316d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
187416d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
187516d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
18763ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
187716d9e3a6SLisandro Dalcin   }
18789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1879db966c6cSHong Zhang   if (flag) {
18804e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
18817de69702SBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64-bit indices");
18828bf83915SBarry Smith #endif
18839566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1884792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1885db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1886db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1887db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1888db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1889db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1890db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1891db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
18923ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1893db966c6cSHong Zhang   }
18949566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
189516d9e3a6SLisandro Dalcin   if (flag) {
18969566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1897792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
189816d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
189916d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
190016d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
190116d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
190216d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
190316d9e3a6SLisandro Dalcin     /* initialize */
190416d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
19058966356dSPierre Jolivet     jac->threshold = .1;
190616d9e3a6SLisandro Dalcin     jac->filter    = .1;
190716d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
19082fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
19092fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
19102fa5cd67SKarl Rupp 
191116d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
191216d9e3a6SLisandro Dalcin     jac->symt = 0;
1913792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1914792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1915792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1916792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1917792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1918792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
19193ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
192016d9e3a6SLisandro Dalcin   }
19219566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
192216d9e3a6SLisandro Dalcin   if (flag) {
1923792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
192416d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
192516d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
192616d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
192716d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
192885245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
19299566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
19309566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
193116d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
193216d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
193316d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
193416d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
193516d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
193616d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
193716d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
193816d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
19398f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
194016d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
194116d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
194216d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
194316d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
194416d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
19450f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
19466a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1947b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
19481810e44eSEike Mueller     jac->eu_level                                                = 0;
19491810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
19501810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1951589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
19520f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
195316d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
195416d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
195516d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
19560f1074feSSatish Balay     jac->interptype                       = 0;
1957589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1958589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1959589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1960589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1961589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
19620f1074feSSatish Balay     jac->agg_nl                           = 0;
19636ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
19640f1074feSSatish Balay     jac->pmax                             = 0;
19650f1074feSSatish Balay     jac->truncfactor                      = 0.0;
19660f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1967589dcaf0SStefano Zampini     jac->maxc                             = 9;
1968589dcaf0SStefano Zampini     jac->minc                             = 1;
196922e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
197022e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
197122e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
197222e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
197322e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
197422e51d31SStefano Zampini     jac->interp_refine                    = 0;
19758f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
19768f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
19776ea7df73SStefano Zampini     jac->rap2                             = 0;
19786ea7df73SStefano Zampini 
19796ea7df73SStefano Zampini     /* GPU defaults
19806ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
19816ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
19826ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
19836ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
19846ea7df73SStefano Zampini     jac->mod_rap2       = 1;
19856ea7df73SStefano Zampini     jac->coarsentype    = 8;
19866ea7df73SStefano Zampini     jac->relaxorder     = 0;
19876ea7df73SStefano Zampini     jac->interptype     = 6;
19886ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
19896ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
19906ea7df73SStefano Zampini     jac->agg_interptype = 7;
19916ea7df73SStefano Zampini #else
19926ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
19936ea7df73SStefano Zampini     jac->mod_rap2      = 0;
19946ea7df73SStefano Zampini #endif
1995792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
1996792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
1997792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
1998792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1999792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
2000792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
2001792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
2002792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
2003792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
2004792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
2005792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
2006792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
2007792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2008792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2009792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2010792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2011792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2012792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2013792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
20146ea7df73SStefano Zampini     /* GPU */
20156ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2016792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2017792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2018792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
20196ea7df73SStefano Zampini #endif
20206ea7df73SStefano Zampini 
2021589dcaf0SStefano Zampini     /* AIR */
20226ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2023792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2024792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2025792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2026792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2027792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
20286ea7df73SStefano Zampini #endif
20293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
203016d9e3a6SLisandro Dalcin   }
20319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
20324cb006feSStefano Zampini   if (flag) {
20333ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
20344cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
20354cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
20364cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
20374cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
20384cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
20394cb006feSStefano Zampini     jac->coords[0]          = NULL;
20404cb006feSStefano Zampini     jac->coords[1]          = NULL;
20414cb006feSStefano Zampini     jac->coords[2]          = NULL;
2042be14dc20SKerry Key     jac->interior           = NULL;
20434cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2044863406b8SStefano Zampini     jac->as_print       = 0;
2045863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2046863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
20474cb006feSStefano Zampini     jac->ams_cycle_type = 13;
20484cb006feSStefano Zampini     /* Smoothing options */
2049863406b8SStefano Zampini     jac->as_relax_type   = 2;
2050863406b8SStefano Zampini     jac->as_relax_times  = 1;
2051863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2052863406b8SStefano Zampini     jac->as_omega        = 1.0;
20534cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2054863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2055863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
20560bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2057863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2058863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2059863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20604cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2061863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2062863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20630bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2064863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2065863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2066863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2067792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2068792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2069792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2070792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
20719371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2072792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2073863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2074863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
20759371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2076a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2077792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2078863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2079863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
20809371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2081a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
208223df4f25SStefano Zampini     /* Zero conductivity */
208323df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
208423df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
20853ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
20864cb006feSStefano Zampini   }
20879566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2088863406b8SStefano Zampini   if (flag) {
20893ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2090863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2091863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2092863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2093863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2094863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2095863406b8SStefano Zampini     jac->coords[0]          = NULL;
2096863406b8SStefano Zampini     jac->coords[1]          = NULL;
2097863406b8SStefano Zampini     jac->coords[2]          = NULL;
2098863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2099863406b8SStefano Zampini     jac->as_print       = 0;
2100863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2101863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2102863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2103863406b8SStefano Zampini     /* Smoothing options */
2104863406b8SStefano Zampini     jac->as_relax_type   = 2;
2105863406b8SStefano Zampini     jac->as_relax_times  = 1;
2106863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2107863406b8SStefano Zampini     jac->as_omega        = 1.0;
2108863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2109863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2110863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2111863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2112863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2113863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2114863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2115863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2116863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2117863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2118863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2119863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2120863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2121863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2122863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2123792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2124792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2125792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2126792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
21279371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2128792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2129863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2130863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2131863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
21329371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2133a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2134792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2135863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2136863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
21379371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2138a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
21393ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2140863406b8SStefano Zampini   }
21419566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
21422fa5cd67SKarl Rupp 
21430298fd71SBarry Smith   jac->hypre_type = NULL;
214498921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
214516d9e3a6SLisandro Dalcin }
214616d9e3a6SLisandro Dalcin 
214716d9e3a6SLisandro Dalcin /*
214816d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
214916d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
215016d9e3a6SLisandro Dalcin */
2151d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2152d71ae5a4SJacob Faibussowitsch {
21534ddd07fcSJed Brown   PetscInt    indx;
2154db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2155ace3abfcSBarry Smith   PetscBool   flg;
215616d9e3a6SLisandro Dalcin 
215716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2158d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2159dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
216016d9e3a6SLisandro Dalcin   if (flg) {
21619566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
216202a17cd4SBarry Smith   } else {
21639566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
216416d9e3a6SLisandro Dalcin   }
2165dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2166d0609cedSBarry Smith   PetscOptionsHeadEnd();
21673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216816d9e3a6SLisandro Dalcin }
216916d9e3a6SLisandro Dalcin 
217016d9e3a6SLisandro Dalcin /*@C
217116d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
217216d9e3a6SLisandro Dalcin 
217316d9e3a6SLisandro Dalcin    Input Parameters:
217416d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2175db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
217616d9e3a6SLisandro Dalcin 
2177f1580f4eSBarry Smith    Options Database Key:
2178db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
217916d9e3a6SLisandro Dalcin 
218016d9e3a6SLisandro Dalcin    Level: intermediate
218116d9e3a6SLisandro Dalcin 
2182f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
218316d9e3a6SLisandro Dalcin @*/
2184d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2185d71ae5a4SJacob Faibussowitsch {
218616d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21870700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
218816d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2189cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
21903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219116d9e3a6SLisandro Dalcin }
219216d9e3a6SLisandro Dalcin 
219316d9e3a6SLisandro Dalcin /*@C
219416d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
219516d9e3a6SLisandro Dalcin 
219616d9e3a6SLisandro Dalcin    Input Parameter:
219716d9e3a6SLisandro Dalcin .     pc - the preconditioner context
219816d9e3a6SLisandro Dalcin 
219916d9e3a6SLisandro Dalcin    Output Parameter:
2200db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
220116d9e3a6SLisandro Dalcin 
220216d9e3a6SLisandro Dalcin    Level: intermediate
220316d9e3a6SLisandro Dalcin 
2204f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
220516d9e3a6SLisandro Dalcin @*/
2206d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2207d71ae5a4SJacob Faibussowitsch {
220816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22090700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
221016d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2211cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
22123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221316d9e3a6SLisandro Dalcin }
221416d9e3a6SLisandro Dalcin 
2215db6f9c32SMark Adams /*@C
2216f1580f4eSBarry Smith    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2217db6f9c32SMark Adams 
2218c3339decSBarry Smith    Logically Collective
2219db6f9c32SMark Adams 
2220db6f9c32SMark Adams    Input Parameters:
2221db6f9c32SMark Adams +  pc - the hypre context
2222db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2223db6f9c32SMark Adams 
2224db6f9c32SMark Adams    Options Database Key:
222567b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2226db6f9c32SMark Adams 
2227db6f9c32SMark Adams    Level: intermediate
2228db6f9c32SMark Adams 
2229f1580f4eSBarry Smith    Developer Note:
2230f1580f4eSBarry Smith    How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2231db6f9c32SMark Adams 
2232f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2233db6f9c32SMark Adams @*/
2234d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2235d71ae5a4SJacob Faibussowitsch {
2236db6f9c32SMark Adams   PetscFunctionBegin;
2237db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2238cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
22393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2240db6f9c32SMark Adams }
2241db6f9c32SMark Adams 
2242db6f9c32SMark Adams /*@C
2243f1580f4eSBarry Smith    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2244db6f9c32SMark Adams 
2245db6f9c32SMark Adams    Not Collective
2246db6f9c32SMark Adams 
2247db6f9c32SMark Adams    Input Parameter:
2248db6f9c32SMark Adams .  pc - the multigrid context
2249db6f9c32SMark Adams 
2250db6f9c32SMark Adams    Output Parameter:
2251db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2252db6f9c32SMark Adams 
2253db6f9c32SMark Adams    Level: intermediate
2254db6f9c32SMark Adams 
2255f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2256db6f9c32SMark Adams @*/
2257d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2258d71ae5a4SJacob Faibussowitsch {
2259db6f9c32SMark Adams   PetscFunctionBegin;
2260db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2261cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
22623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2263db6f9c32SMark Adams }
2264db6f9c32SMark Adams 
226516d9e3a6SLisandro Dalcin /*MC
2266f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
226716d9e3a6SLisandro Dalcin 
226816d9e3a6SLisandro Dalcin    Options Database Keys:
2269db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2270f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2271f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2272ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
227316d9e3a6SLisandro Dalcin 
227416d9e3a6SLisandro Dalcin    Level: intermediate
227516d9e3a6SLisandro Dalcin 
227695452b02SPatrick Sanan    Notes:
2277f1580f4eSBarry Smith     Apart from pc_hypre_type (for which there is `PCHYPRESetType()`),
227816d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
227949567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
228016d9e3a6SLisandro Dalcin 
2281c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
22820f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
22830f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2284c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
22858f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
22860f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
22870f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
228816d9e3a6SLisandro Dalcin 
22890f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
22900f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
22910f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
229216d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
229316d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
229416d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
229516d9e3a6SLisandro Dalcin 
2296f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
229749567fc5SPierre Jolivet           the following two options: ``-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>``
22980b1a5bd9SEric Chamberland 
2299f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2300f1580f4eSBarry Smith 
2301f1580f4eSBarry Smith           For `PCHYPRE` type of ams or ads auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2302f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
230349567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2304f1580f4eSBarry Smith 
2305f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
23069e5bc791SBarry Smith 
2307ead8c081SBarry Smith    GPU Notes:
2308ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2309f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2310ead8c081SBarry Smith 
2311ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2312f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2313ead8c081SBarry Smith 
2314f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2315f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2316f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
231716d9e3a6SLisandro Dalcin M*/
231816d9e3a6SLisandro Dalcin 
2319d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2320d71ae5a4SJacob Faibussowitsch {
232116d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
232216d9e3a6SLisandro Dalcin 
232316d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23244dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
23252fa5cd67SKarl Rupp 
232616d9e3a6SLisandro Dalcin   pc->data                = jac;
23278695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
232816d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
232916d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
233016d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
233116d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
233216d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
23349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
23359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
23369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
23379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
23389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
23399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2340be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
23419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
23429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
23439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
23446ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23456ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
23469566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
23476ea7df73SStefano Zampini   #endif
23486ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
23499566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
23506ea7df73SStefano Zampini   #endif
23516ea7df73SStefano Zampini #endif
2352*ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
23533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
235416d9e3a6SLisandro Dalcin }
2355ebc551c0SBarry Smith 
2356ebc551c0SBarry Smith typedef struct {
235768326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2358f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23599e5bc791SBarry Smith 
23609e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23614ddd07fcSJed Brown   PetscInt  its;
23629e5bc791SBarry Smith   double    tol;
23634ddd07fcSJed Brown   PetscInt  relax_type;
23644ddd07fcSJed Brown   PetscInt  rap_type;
23654ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
23664ddd07fcSJed Brown   PetscInt  max_levels;
23670be8cd64Sftrigaux   PetscInt  skip_relax;
23680be8cd64Sftrigaux   PetscBool print_statistics;
2369ebc551c0SBarry Smith } PC_PFMG;
2370ebc551c0SBarry Smith 
2371d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_PFMG(PC pc)
2372d71ae5a4SJacob Faibussowitsch {
2373f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2374ebc551c0SBarry Smith 
2375ebc551c0SBarry Smith   PetscFunctionBegin;
2376792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
23779566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
23789566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
23793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2380ebc551c0SBarry Smith }
2381ebc551c0SBarry Smith 
23829e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
23839e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
23849e5bc791SBarry Smith 
2385d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2386d71ae5a4SJacob Faibussowitsch {
2387ace3abfcSBarry Smith   PetscBool iascii;
2388f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2389ebc551c0SBarry Smith 
2390ebc551c0SBarry Smith   PetscFunctionBegin;
23919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
23929e5bc791SBarry Smith   if (iascii) {
23939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
239463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
23959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
23969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
23979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
239863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
239963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
24000be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
24019e5bc791SBarry Smith   }
24023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2403ebc551c0SBarry Smith }
2404ebc551c0SBarry Smith 
2405d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2406d71ae5a4SJacob Faibussowitsch {
2407f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2408ebc551c0SBarry Smith 
2409ebc551c0SBarry Smith   PetscFunctionBegin;
2410d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
24110be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
24129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2413792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24149566063dSJacob 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));
2415792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24169566063dSJacob 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));
2417792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24189e5bc791SBarry Smith 
24199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2420792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24213b46a515SGlenn Hammond 
24229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2423792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2424dd39110bSPierre 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));
2425792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2426dd39110bSPierre 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));
2427792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24280be8cd64Sftrigaux   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));
24290be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2430d0609cedSBarry Smith   PetscOptionsHeadEnd();
24313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2432ebc551c0SBarry Smith }
2433ebc551c0SBarry Smith 
2434d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2435d71ae5a4SJacob Faibussowitsch {
2436f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2437d9ca1df4SBarry Smith   PetscScalar       *yy;
2438d9ca1df4SBarry Smith   const PetscScalar *xx;
24394ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
24402cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
244168326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2442f91d8e95SBarry Smith 
2443f91d8e95SBarry Smith   PetscFunctionBegin;
24449566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
24459566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
24462cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2447f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2448f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2449f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
24502cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
24512cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
24522cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
24532cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
24542cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
24552cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2456f91d8e95SBarry Smith 
2457f91d8e95SBarry Smith   /* copy x values over to hypre */
2458792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
24599566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2460792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
24619566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2462792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2463792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2464f91d8e95SBarry Smith 
2465f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24669566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2467792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
24689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
24693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2470f91d8e95SBarry Smith }
2471f91d8e95SBarry Smith 
2472d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_PFMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
2473d71ae5a4SJacob Faibussowitsch {
24749e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
24752cf14000SStefano Zampini   HYPRE_Int oits;
24769e5bc791SBarry Smith 
24779e5bc791SBarry Smith   PetscFunctionBegin;
24789566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2479792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2480792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
24819e5bc791SBarry Smith 
24829566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2483792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
24849e5bc791SBarry Smith   *outits = oits;
24859e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
24869e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2487792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2488792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
24893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24909e5bc791SBarry Smith }
24919e5bc791SBarry Smith 
2492d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_PFMG(PC pc)
2493d71ae5a4SJacob Faibussowitsch {
24943a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
24953a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2496ace3abfcSBarry Smith   PetscBool        flg;
24973a32d3dbSGlenn Hammond 
24983a32d3dbSGlenn Hammond   PetscFunctionBegin;
24999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
250028b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
25013a32d3dbSGlenn Hammond 
25023a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2503792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2504792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25050be8cd64Sftrigaux 
25060be8cd64Sftrigaux   // Print Hypre statistics about the solve process
25070be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
25080be8cd64Sftrigaux 
25090be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25100be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
25110be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
25120be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
25130be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
25140be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
25150be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
25160be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
25170be8cd64Sftrigaux 
2518792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2519792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
25203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25213a32d3dbSGlenn Hammond }
25223a32d3dbSGlenn Hammond 
2523ebc551c0SBarry Smith /*MC
2524ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2525ebc551c0SBarry Smith 
2526f1580f4eSBarry Smith    Options Database Keys:
252767b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
252867b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
252967b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
253067b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25319e5bc791SBarry 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
25320be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2533f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2534f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2535f1580f4eSBarry Smith 
2536f1580f4eSBarry Smith    Level: advanced
2537f91d8e95SBarry Smith 
253895452b02SPatrick Sanan    Notes:
253995452b02SPatrick Sanan    This is for CELL-centered descretizations
25409e5bc791SBarry Smith 
2541f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
25429e5bc791SBarry Smith 
2543f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2544f1580f4eSBarry Smith 
2545f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2546f1580f4eSBarry Smith 
2547f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2548f1580f4eSBarry Smith 
2549f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2550ebc551c0SBarry Smith M*/
2551ebc551c0SBarry Smith 
2552d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2553d71ae5a4SJacob Faibussowitsch {
2554ebc551c0SBarry Smith   PC_PFMG *ex;
2555ebc551c0SBarry Smith 
2556ebc551c0SBarry Smith   PetscFunctionBegin;
25579371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
255868326731SBarry Smith   pc->data = ex;
2559ebc551c0SBarry Smith 
25609e5bc791SBarry Smith   ex->its              = 1;
25619e5bc791SBarry Smith   ex->tol              = 1.e-8;
25629e5bc791SBarry Smith   ex->relax_type       = 1;
25639e5bc791SBarry Smith   ex->rap_type         = 0;
25649e5bc791SBarry Smith   ex->num_pre_relax    = 1;
25659e5bc791SBarry Smith   ex->num_post_relax   = 1;
25663b46a515SGlenn Hammond   ex->max_levels       = 0;
25670be8cd64Sftrigaux   ex->skip_relax       = 0;
25680be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25699e5bc791SBarry Smith 
2570ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2571ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2572ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2573f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
25749e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
257568326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
25762fa5cd67SKarl Rupp 
25779566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2578*ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2579792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2581ebc551c0SBarry Smith }
2582d851a50bSGlenn Hammond 
2583d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2584d851a50bSGlenn Hammond typedef struct {
2585d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2586d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2587d851a50bSGlenn Hammond 
2588d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
25894ddd07fcSJed Brown   PetscInt its;
2590d851a50bSGlenn Hammond   double   tol;
25914ddd07fcSJed Brown   PetscInt relax_type;
25924ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2593d851a50bSGlenn Hammond } PC_SysPFMG;
2594d851a50bSGlenn Hammond 
2595d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SysPFMG(PC pc)
2596d71ae5a4SJacob Faibussowitsch {
2597d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2598d851a50bSGlenn Hammond 
2599d851a50bSGlenn Hammond   PetscFunctionBegin;
2600792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
26019566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
26029566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
26033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2604d851a50bSGlenn Hammond }
2605d851a50bSGlenn Hammond 
2606d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2607d851a50bSGlenn Hammond 
2608d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2609d71ae5a4SJacob Faibussowitsch {
2610ace3abfcSBarry Smith   PetscBool   iascii;
2611d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2612d851a50bSGlenn Hammond 
2613d851a50bSGlenn Hammond   PetscFunctionBegin;
26149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2615d851a50bSGlenn Hammond   if (iascii) {
26169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
261763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
26189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
26199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
262063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2621d851a50bSGlenn Hammond   }
26223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2623d851a50bSGlenn Hammond }
2624d851a50bSGlenn Hammond 
2625d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2626d71ae5a4SJacob Faibussowitsch {
2627d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2628ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2629d851a50bSGlenn Hammond 
2630d851a50bSGlenn Hammond   PetscFunctionBegin;
2631d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
26329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
263348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
26349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2635792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
26369566063dSJacob 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));
2637792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
26389566063dSJacob 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));
2639792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2640d851a50bSGlenn Hammond 
26419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2642792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2643dd39110bSPierre 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));
2644792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2645d0609cedSBarry Smith   PetscOptionsHeadEnd();
26463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2647d851a50bSGlenn Hammond }
2648d851a50bSGlenn Hammond 
2649d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2650d71ae5a4SJacob Faibussowitsch {
2651d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2652d9ca1df4SBarry Smith   PetscScalar       *yy;
2653d9ca1df4SBarry Smith   const PetscScalar *xx;
26544ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
26552cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2656d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
26574ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
26584ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
26594ddd07fcSJed Brown   PetscInt           part     = 0;
26604ddd07fcSJed Brown   PetscInt           size;
26614ddd07fcSJed Brown   PetscInt           i;
2662d851a50bSGlenn Hammond 
2663d851a50bSGlenn Hammond   PetscFunctionBegin;
26649566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
26659566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
26662cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2667d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2668d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2669d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
26702cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
26712cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
26722cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
26732cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
26742cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
26752cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2676d851a50bSGlenn Hammond 
2677d851a50bSGlenn Hammond   size = 1;
26782fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
26792fa5cd67SKarl Rupp 
2680d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2681d851a50bSGlenn Hammond   if (ordering) {
2682792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26839566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2684792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
26859566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2686792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2687792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2688792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2689d851a50bSGlenn Hammond 
2690d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26919566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2692792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
26939566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2694a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2695d851a50bSGlenn Hammond     PetscScalar *z;
26964ddd07fcSJed Brown     PetscInt     j, k;
2697d851a50bSGlenn Hammond 
26989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2699792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
27009566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2701d851a50bSGlenn Hammond 
2702d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2703d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2704d851a50bSGlenn Hammond       k = i * nvars;
27052fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2706d851a50bSGlenn Hammond     }
2707792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
27089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2709792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2710792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2711d851a50bSGlenn Hammond 
2712d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27139566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2714792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2715d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2716d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2717d851a50bSGlenn Hammond       k = i * nvars;
27182fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2719d851a50bSGlenn Hammond     }
27209566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
27219566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2722d851a50bSGlenn Hammond   }
27233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2724d851a50bSGlenn Hammond }
2725d851a50bSGlenn Hammond 
2726d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_SysPFMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
2727d71ae5a4SJacob Faibussowitsch {
2728d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
27292cf14000SStefano Zampini   HYPRE_Int   oits;
2730d851a50bSGlenn Hammond 
2731d851a50bSGlenn Hammond   PetscFunctionBegin;
27329566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2733792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2734792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
27359566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2736792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2737d851a50bSGlenn Hammond   *outits = oits;
2738d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2739d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2740792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2741792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
27423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2743d851a50bSGlenn Hammond }
2744d851a50bSGlenn Hammond 
2745d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SysPFMG(PC pc)
2746d71ae5a4SJacob Faibussowitsch {
2747d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2748d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2749ace3abfcSBarry Smith   PetscBool         flg;
2750d851a50bSGlenn Hammond 
2751d851a50bSGlenn Hammond   PetscFunctionBegin;
27529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
275328b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2754d851a50bSGlenn Hammond 
2755d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2756792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2757792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2758792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2759792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
27603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2761d851a50bSGlenn Hammond }
2762d851a50bSGlenn Hammond 
2763d851a50bSGlenn Hammond /*MC
2764f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2765d851a50bSGlenn Hammond 
2766d851a50bSGlenn Hammond    Level: advanced
2767d851a50bSGlenn Hammond 
2768f1580f4eSBarry Smith    Options Database Keys:
276967b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
277067b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
277167b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
277267b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
277367b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2774d851a50bSGlenn Hammond 
277595452b02SPatrick Sanan    Notes:
2776f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2777f1580f4eSBarry Smith 
2778f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2779f1580f4eSBarry Smith 
278095452b02SPatrick Sanan    This is for CELL-centered descretizations
2781d851a50bSGlenn Hammond 
2782f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2783d851a50bSGlenn Hammond 
2784f1580f4eSBarry Smith    This does not give access to all the functionality of hypres SysPFMG, it supports only one part, and one block per process defined by a PETSc `DMDA`.
2785f1580f4eSBarry Smith 
2786f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2787d851a50bSGlenn Hammond M*/
2788d851a50bSGlenn Hammond 
2789d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2790d71ae5a4SJacob Faibussowitsch {
2791d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2792d851a50bSGlenn Hammond 
2793d851a50bSGlenn Hammond   PetscFunctionBegin;
27949371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2795d851a50bSGlenn Hammond   pc->data = ex;
2796d851a50bSGlenn Hammond 
2797d851a50bSGlenn Hammond   ex->its            = 1;
2798d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2799d851a50bSGlenn Hammond   ex->relax_type     = 1;
2800d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2801d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2802d851a50bSGlenn Hammond 
2803d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2804d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2805d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2806d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2807d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2808d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
28092fa5cd67SKarl Rupp 
28109566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2811*ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
2812792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
28133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2814d851a50bSGlenn Hammond }
28151c188c59Sftrigaux 
2816f1580f4eSBarry Smith /* PC SMG */
28171c188c59Sftrigaux typedef struct {
28181c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28191c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28201c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
28211c188c59Sftrigaux   double             tol;
28221c188c59Sftrigaux   PetscBool          print_statistics;
28231c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
28241c188c59Sftrigaux } PC_SMG;
28251c188c59Sftrigaux 
2826d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SMG(PC pc)
2827d71ae5a4SJacob Faibussowitsch {
28281c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28291c188c59Sftrigaux 
28301c188c59Sftrigaux   PetscFunctionBegin;
28311c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
28321c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28331c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28351c188c59Sftrigaux }
28361c188c59Sftrigaux 
2837d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2838d71ae5a4SJacob Faibussowitsch {
28391c188c59Sftrigaux   PetscBool iascii;
28401c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
28411c188c59Sftrigaux 
28421c188c59Sftrigaux   PetscFunctionBegin;
28431c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
28441c188c59Sftrigaux   if (iascii) {
28451c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
28461c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
28471c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
28481c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
28491c188c59Sftrigaux   }
28503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28511c188c59Sftrigaux }
28521c188c59Sftrigaux 
2853d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2854d71ae5a4SJacob Faibussowitsch {
28551c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28561c188c59Sftrigaux 
28571c188c59Sftrigaux   PetscFunctionBegin;
28581c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
28591c188c59Sftrigaux 
28601c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
28611c188c59Sftrigaux   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));
28621c188c59Sftrigaux   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));
28631c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
28641c188c59Sftrigaux 
28651c188c59Sftrigaux   PetscOptionsHeadEnd();
28663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28671c188c59Sftrigaux }
28681c188c59Sftrigaux 
2869d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2870d71ae5a4SJacob Faibussowitsch {
28711c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
28721c188c59Sftrigaux   PetscScalar       *yy;
28731c188c59Sftrigaux   const PetscScalar *xx;
28741c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
28751c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
28761c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28771c188c59Sftrigaux 
28781c188c59Sftrigaux   PetscFunctionBegin;
28791c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28801c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28811c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
28821c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
28831c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
28841c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
28851c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
28861c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
28871c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
28881c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
28891c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
28901c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
28911c188c59Sftrigaux 
28921c188c59Sftrigaux   /* copy x values over to hypre */
28931c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28941c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
28951c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28961c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
28971c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
28981c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28991c188c59Sftrigaux 
29001c188c59Sftrigaux   /* copy solution values back to PETSc */
29011c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
29021c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
29031c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
29043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29051c188c59Sftrigaux }
29061c188c59Sftrigaux 
2907d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyRichardson_SMG(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
2908d71ae5a4SJacob Faibussowitsch {
29091c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
29101c188c59Sftrigaux   HYPRE_Int oits;
29111c188c59Sftrigaux 
29121c188c59Sftrigaux   PetscFunctionBegin;
29131c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29141c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
29151c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
29161c188c59Sftrigaux 
29171c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
29181c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
29191c188c59Sftrigaux   *outits = oits;
29201c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29211c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
29221c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
29231c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
29243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29251c188c59Sftrigaux }
29261c188c59Sftrigaux 
2927d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SMG(PC pc)
2928d71ae5a4SJacob Faibussowitsch {
29291c188c59Sftrigaux   PetscInt         i, dim;
29301c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
29311c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29321c188c59Sftrigaux   PetscBool        flg;
29331c188c59Sftrigaux   DMBoundaryType   p[3];
29341c188c59Sftrigaux   PetscInt         M[3];
29351c188c59Sftrigaux 
29361c188c59Sftrigaux   PetscFunctionBegin;
29371c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
29381c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
29391c188c59Sftrigaux 
29401c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
29411c188c59Sftrigaux   // Check if power of 2 in periodic directions
29421c188c59Sftrigaux   for (i = 0; i < dim; i++) {
29431c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
29441c188c59Sftrigaux       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]);
29451c188c59Sftrigaux     }
29461c188c59Sftrigaux   }
29471c188c59Sftrigaux 
29481c188c59Sftrigaux   /* create the hypre solver object and set its information */
29491c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
29501c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29511c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
29521c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
29531c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
29541c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
29551c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
29561c188c59Sftrigaux 
29571c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29581c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
29593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29601c188c59Sftrigaux }
29611c188c59Sftrigaux 
29621c188c59Sftrigaux /*MC
29635cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29641c188c59Sftrigaux 
29651c188c59Sftrigaux    Level: advanced
29661c188c59Sftrigaux 
2967f1580f4eSBarry Smith    Options Database Keys:
29685cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
29695cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
29705cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
29715cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
29721c188c59Sftrigaux 
29731c188c59Sftrigaux    Notes:
29741c188c59Sftrigaux    This is for CELL-centered descretizations
29751c188c59Sftrigaux 
29765cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
29771c188c59Sftrigaux 
2978f1580f4eSBarry Smith    This does not provide all the functionality of  hypre's SMG solver, it supports only one block per process defined by a PETSc `DMDA`.
2979f1580f4eSBarry Smith 
2980f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
2981f1580f4eSBarry Smith 
2982f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
29831c188c59Sftrigaux M*/
29841c188c59Sftrigaux 
2985d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
2986d71ae5a4SJacob Faibussowitsch {
29871c188c59Sftrigaux   PC_SMG *ex;
29881c188c59Sftrigaux 
29891c188c59Sftrigaux   PetscFunctionBegin;
29909371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
29911c188c59Sftrigaux   pc->data = ex;
29921c188c59Sftrigaux 
29931c188c59Sftrigaux   ex->its            = 1;
29941c188c59Sftrigaux   ex->tol            = 1.e-8;
29951c188c59Sftrigaux   ex->num_pre_relax  = 1;
29961c188c59Sftrigaux   ex->num_post_relax = 1;
29971c188c59Sftrigaux 
29981c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
29991c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
30001c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
30011c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
30021c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
30031c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
30041c188c59Sftrigaux 
30051c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
3006*ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
30071c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
30083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30091c188c59Sftrigaux }
3010