xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 852456159132bc30c5b87b2987f335ad79febdd0)
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);
419792fecdfSBarry Smith   PetscCallExternal(jac->setup, jac->hsolver, hmat, bv, xv);
4203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42116d9e3a6SLisandro Dalcin }
42216d9e3a6SLisandro Dalcin 
423d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_HYPRE(PC pc, Vec b, Vec x)
424d71ae5a4SJacob Faibussowitsch {
42516d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
42649a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
42716d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
42816d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
42916d9e3a6SLisandro Dalcin 
43016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
4319566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
4329566063dSJacob Faibussowitsch   if (!jac->applyrichardson) PetscCall(VecSet(x, 0.0));
4339566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->b, b));
4349566063dSJacob Faibussowitsch   if (jac->applyrichardson) PetscCall(VecHYPRE_IJVectorPushVec(hjac->x, x));
4359566063dSJacob Faibussowitsch   else PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->x, x));
436792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
437792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
438792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
4399371c9d4SSatish Balay   PetscStackCallExternalVoid(
4409371c9d4SSatish Balay     "Hypre solve", do {
4415f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, hmat, jbv, jxv);
4425f80ce2aSJacob Faibussowitsch       if (hierr) {
4435f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
444*85245615SPierre Jolivet         HYPRE_ClearAllErrors();
4455f80ce2aSJacob Faibussowitsch       }
4465f80ce2aSJacob Faibussowitsch     } while (0));
44716d9e3a6SLisandro Dalcin 
44848a46eb9SPierre Jolivet   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) PetscCallExternal(HYPRE_AMSProjectOutGradients, jac->hsolver, jxv);
4499566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
4509566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
4513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45216d9e3a6SLisandro Dalcin }
45316d9e3a6SLisandro Dalcin 
454*85245615SPierre Jolivet static PetscErrorCode PCMatApply_HYPRE_BoomerAMG(PC pc, Mat B, Mat X)
455*85245615SPierre Jolivet {
456*85245615SPierre Jolivet   PC_HYPRE           *jac  = (PC_HYPRE *)pc->data;
457*85245615SPierre Jolivet   Mat_HYPRE          *hjac = (Mat_HYPRE *)(jac->hpmat->data);
458*85245615SPierre Jolivet   hypre_ParCSRMatrix *par_matrix;
459*85245615SPierre Jolivet   HYPRE_ParVector     hb, hx;
460*85245615SPierre Jolivet   const PetscScalar  *b;
461*85245615SPierre Jolivet   PetscScalar        *x;
462*85245615SPierre Jolivet   PetscInt            m, N, lda;
463*85245615SPierre Jolivet   hypre_Vector       *x_local;
464*85245615SPierre Jolivet   PetscMemType        type;
465*85245615SPierre Jolivet 
466*85245615SPierre Jolivet   PetscFunctionBegin;
467*85245615SPierre Jolivet   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
468*85245615SPierre Jolivet   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&par_matrix);
469*85245615SPierre Jolivet   PetscCall(MatGetLocalSize(B, &m, NULL));
470*85245615SPierre Jolivet   PetscCall(MatGetSize(B, NULL, &N));
471*85245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hb);
472*85245615SPierre Jolivet   PetscCallExternal(HYPRE_ParMultiVectorCreate, hypre_ParCSRMatrixComm(par_matrix), hypre_ParCSRMatrixGlobalNumRows(par_matrix), hypre_ParCSRMatrixRowStarts(par_matrix), N, &hx);
473*85245615SPierre Jolivet   PetscCall(MatZeroEntries(X));
474*85245615SPierre Jolivet   PetscCall(MatDenseGetArrayReadAndMemType(B, &b, &type));
475*85245615SPierre Jolivet   PetscCall(MatDenseGetLDA(B, &lda));
476*85245615SPierre 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);
477*85245615SPierre Jolivet   PetscCall(MatDenseGetLDA(X, &lda));
478*85245615SPierre 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);
479*85245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hb);
480*85245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
481*85245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)b;
482*85245615SPierre Jolivet   PetscCall(MatDenseGetArrayWriteAndMemType(X, &x, NULL));
483*85245615SPierre Jolivet   x_local = hypre_ParVectorLocalVector(hx);
484*85245615SPierre Jolivet   PetscCallExternal(hypre_SeqVectorSetDataOwner, x_local, 0);
485*85245615SPierre Jolivet   hypre_VectorData(x_local) = (HYPRE_Complex *)x;
486*85245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hb, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
487*85245615SPierre Jolivet   PetscCallExternal(hypre_ParVectorInitialize_v2, hx, type == PETSC_MEMTYPE_HOST ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
488*85245615SPierre Jolivet   PetscStackCallExternalVoid(
489*85245615SPierre Jolivet     "Hypre solve", do {
490*85245615SPierre Jolivet       HYPRE_Int hierr = (*jac->solve)(jac->hsolver, par_matrix, hb, hx);
491*85245615SPierre Jolivet       if (hierr) {
492*85245615SPierre Jolivet         PetscCheck(hierr == HYPRE_ERROR_CONV, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
493*85245615SPierre Jolivet         HYPRE_ClearAllErrors();
494*85245615SPierre Jolivet       }
495*85245615SPierre Jolivet     } while (0));
496*85245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hb);
497*85245615SPierre Jolivet   PetscCallExternal(HYPRE_ParVectorDestroy, hx);
498*85245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayReadAndMemType(B, &b));
499*85245615SPierre Jolivet   PetscCall(MatDenseRestoreArrayWriteAndMemType(X, &x));
500*85245615SPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
501*85245615SPierre Jolivet }
502*85245615SPierre Jolivet 
503d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_HYPRE(PC pc)
504d71ae5a4SJacob Faibussowitsch {
5058695de01SBarry Smith   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
5068695de01SBarry Smith 
5078695de01SBarry Smith   PetscFunctionBegin;
5089566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->hpmat));
5099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->G));
5109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->C));
5119566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->alpha_Poisson));
5129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->beta_Poisson));
5139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
5149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[0]));
5159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[1]));
5169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_Pi[2]));
5179566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
5189566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[0]));
5199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[1]));
5209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_Pi[2]));
5219566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
5229566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
5239566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
5249566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
5259566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
5269566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
527be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
5289566063dSJacob Faibussowitsch   PetscCall(PCHYPREResetNearNullSpace_Private(pc));
5295ac14e1cSStefano Zampini   jac->ams_beta_is_zero      = PETSC_FALSE;
530be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_FALSE;
5315ac14e1cSStefano Zampini   jac->dim                   = 0;
5323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5338695de01SBarry Smith }
5348695de01SBarry Smith 
535d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_HYPRE(PC pc)
536d71ae5a4SJacob Faibussowitsch {
53716d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
53816d9e3a6SLisandro Dalcin 
53916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5409566063dSJacob Faibussowitsch   PetscCall(PCReset_HYPRE(pc));
541792fecdfSBarry Smith   if (jac->destroy) PetscCallExternal(jac->destroy, jac->hsolver);
5429566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
543db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
5449566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->spgemm_type));
545db6f9c32SMark Adams #endif
5469566063dSJacob Faibussowitsch   if (jac->comm_hypre != MPI_COMM_NULL) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
5479566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
54816d9e3a6SLisandro Dalcin 
5499566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, 0));
5509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", NULL));
5519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", NULL));
5529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", NULL));
5539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", NULL));
5549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", NULL));
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetConstantEdgeVectors_C", NULL));
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", NULL));
5572e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", NULL));
558be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", NULL));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", NULL));
5609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", NULL));
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", NULL));
5629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", NULL));
5632e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56516d9e3a6SLisandro Dalcin }
56616d9e3a6SLisandro Dalcin 
567d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc, PetscOptionItems *PetscOptionsObject)
568d71ae5a4SJacob Faibussowitsch {
56916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
570ace3abfcSBarry Smith   PetscBool flag;
57116d9e3a6SLisandro Dalcin 
57216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
573d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Pilut Options");
5749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_maxiter", "Number of iterations", "None", jac->maxiter, &jac->maxiter, &flag));
575792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetMaxIter, jac->hsolver, jac->maxiter);
5769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_pilut_tol", "Drop tolerance", "None", jac->tol, &jac->tol, &flag));
577792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetDropTolerance, jac->hsolver, jac->tol);
5789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_pilut_factorrowsize", "FactorRowSize", "None", jac->factorrowsize, &jac->factorrowsize, &flag));
579792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParCSRPilutSetFactorRowSize, jac->hsolver, jac->factorrowsize);
580d0609cedSBarry Smith   PetscOptionsHeadEnd();
5813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58216d9e3a6SLisandro Dalcin }
58316d9e3a6SLisandro Dalcin 
584d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Pilut(PC pc, PetscViewer viewer)
585d71ae5a4SJacob Faibussowitsch {
58616d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
587ace3abfcSBarry Smith   PetscBool iascii;
58816d9e3a6SLisandro Dalcin 
58916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
5909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
59116d9e3a6SLisandro Dalcin   if (iascii) {
5929566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Pilut preconditioning\n"));
59316d9e3a6SLisandro Dalcin     if (jac->maxiter != PETSC_DEFAULT) {
59463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    maximum number of iterations %" PetscInt_FMT "\n", jac->maxiter));
59516d9e3a6SLisandro Dalcin     } else {
5969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default maximum number of iterations \n"));
59716d9e3a6SLisandro Dalcin     }
59816d9e3a6SLisandro Dalcin     if (jac->tol != PETSC_DEFAULT) {
5999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->tol));
60016d9e3a6SLisandro Dalcin     } else {
6019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default drop tolerance \n"));
60216d9e3a6SLisandro Dalcin     }
60316d9e3a6SLisandro Dalcin     if (jac->factorrowsize != PETSC_DEFAULT) {
60463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factor row size %" PetscInt_FMT "\n", jac->factorrowsize));
60516d9e3a6SLisandro Dalcin     } else {
6069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factor row size \n"));
60716d9e3a6SLisandro Dalcin     }
60816d9e3a6SLisandro Dalcin   }
6093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61016d9e3a6SLisandro Dalcin }
61116d9e3a6SLisandro Dalcin 
612d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc, PetscOptionItems *PetscOptionsObject)
613d71ae5a4SJacob Faibussowitsch {
614db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
6158bf83915SBarry Smith   PetscBool flag, eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
616db966c6cSHong Zhang 
617db966c6cSHong Zhang   PetscFunctionBegin;
618d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE Euclid Options");
6199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_euclid_level", "Factorization levels", "None", jac->eu_level, &jac->eu_level, &flag));
620792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_EuclidSetLevel, jac->hsolver, jac->eu_level);
6218bf83915SBarry Smith 
6229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_euclid_droptolerance", "Drop tolerance for ILU(k) in Euclid", "None", jac->eu_droptolerance, &jac->eu_droptolerance, &flag));
6238bf83915SBarry Smith   if (flag) {
6248bf83915SBarry Smith     PetscMPIInt size;
6258bf83915SBarry Smith 
6269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
6277827d75bSBarry Smith     PetscCheck(size == 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "hypre's Euclid does not support a parallel drop tolerance");
628792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetILUT, jac->hsolver, jac->eu_droptolerance);
6298bf83915SBarry Smith   }
6308bf83915SBarry Smith 
6319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj, &eu_bj, &flag));
6328bf83915SBarry Smith   if (flag) {
6338bf83915SBarry Smith     jac->eu_bj = eu_bj ? 1 : 0;
634792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidSetBJ, jac->hsolver, jac->eu_bj);
6358bf83915SBarry Smith   }
636d0609cedSBarry Smith   PetscOptionsHeadEnd();
6373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
638db966c6cSHong Zhang }
639db966c6cSHong Zhang 
640d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_Euclid(PC pc, PetscViewer viewer)
641d71ae5a4SJacob Faibussowitsch {
642db966c6cSHong Zhang   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
643db966c6cSHong Zhang   PetscBool iascii;
644db966c6cSHong Zhang 
645db966c6cSHong Zhang   PetscFunctionBegin;
6469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
647db966c6cSHong Zhang   if (iascii) {
6489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE Euclid preconditioning\n"));
649db966c6cSHong Zhang     if (jac->eu_level != PETSC_DEFAULT) {
65063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    factorization levels %" PetscInt_FMT "\n", jac->eu_level));
651db966c6cSHong Zhang     } else {
6529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    default factorization levels \n"));
653db966c6cSHong Zhang     }
6549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    drop tolerance %g\n", (double)jac->eu_droptolerance));
65563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
656db966c6cSHong Zhang   }
6573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
658db966c6cSHong Zhang }
659db966c6cSHong Zhang 
660d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc, Vec b, Vec x)
661d71ae5a4SJacob Faibussowitsch {
66216d9e3a6SLisandro Dalcin   PC_HYPRE          *jac  = (PC_HYPRE *)pc->data;
66349a781f5SStefano Zampini   Mat_HYPRE         *hjac = (Mat_HYPRE *)(jac->hpmat->data);
66416d9e3a6SLisandro Dalcin   HYPRE_ParCSRMatrix hmat;
66516d9e3a6SLisandro Dalcin   HYPRE_ParVector    jbv, jxv;
66616d9e3a6SLisandro Dalcin 
66716d9e3a6SLisandro Dalcin   PetscFunctionBegin;
6689566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
6699566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0.0));
6709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecRead(hjac->x, b));
6719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPushVecWrite(hjac->b, x));
67216d9e3a6SLisandro Dalcin 
673792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hjac->ij, (void **)&hmat);
674792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->b->ij, (void **)&jbv);
675792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJVectorGetObject, hjac->x->ij, (void **)&jxv);
67616d9e3a6SLisandro Dalcin 
6779371c9d4SSatish Balay   PetscStackCallExternalVoid(
6789371c9d4SSatish Balay     "Hypre Transpose solve", do {
6795f80ce2aSJacob Faibussowitsch       HYPRE_Int hierr = HYPRE_BoomerAMGSolveT(jac->hsolver, hmat, jbv, jxv);
6805f80ce2aSJacob Faibussowitsch       if (hierr) {
68116d9e3a6SLisandro Dalcin         /* error code of 1 in BoomerAMG merely means convergence not achieved */
6825f80ce2aSJacob Faibussowitsch         PetscCheck(hierr == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in HYPRE solver, error code %d", (int)hierr);
683*85245615SPierre Jolivet         HYPRE_ClearAllErrors();
6845f80ce2aSJacob Faibussowitsch       }
6855f80ce2aSJacob Faibussowitsch     } while (0));
68616d9e3a6SLisandro Dalcin 
6879566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->x));
6889566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hjac->b));
6893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69016d9e3a6SLisandro Dalcin }
69116d9e3a6SLisandro Dalcin 
692d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char name[])
693d71ae5a4SJacob Faibussowitsch {
694db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
695db6f9c32SMark Adams   PetscBool flag;
696db6f9c32SMark Adams 
697db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
698db6f9c32SMark Adams   PetscFunctionBegin;
699db6f9c32SMark Adams   if (jac->spgemm_type) {
7009566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->spgemm_type, name, &flag));
70128b400f6SJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE SpGEMM (really we can)");
7023ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
703db6f9c32SMark Adams   } else {
7049566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->spgemm_type));
705db6f9c32SMark Adams   }
7069566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("cusparse", jac->spgemm_type, &flag));
707db6f9c32SMark Adams   if (flag) {
708792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 1);
7093ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
710db6f9c32SMark Adams   }
7119566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("hypre", jac->spgemm_type, &flag));
712db6f9c32SMark Adams   if (flag) {
713792fecdfSBarry Smith     PetscCallExternal(HYPRE_SetSpGemmUseCusparse, 0);
7143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
715db6f9c32SMark Adams   }
716db6f9c32SMark Adams   jac->spgemm_type = NULL;
71798921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE SpGEM type %s; Choices are cusparse, hypre", name);
718db6f9c32SMark Adams #endif
719db6f9c32SMark Adams }
720db6f9c32SMark Adams 
721d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG(PC pc, const char *spgemm[])
722d71ae5a4SJacob Faibussowitsch {
723db6f9c32SMark Adams   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
724db6f9c32SMark Adams 
725db6f9c32SMark Adams   PetscFunctionBegin;
726db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
727db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
728db6f9c32SMark Adams   *spgemm = jac->spgemm_type;
729db6f9c32SMark Adams #endif
7303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
731db6f9c32SMark Adams }
732db6f9c32SMark Adams 
73316d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGCycleType[]   = {"", "V", "W"};
7340f1074feSSatish Balay static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP", "Ruge-Stueben", "", "modifiedRuge-Stueben", "", "", "Falgout", "", "PMIS", "", "HMIS"};
73516d9e3a6SLisandro Dalcin static const char *HYPREBoomerAMGMeasureType[] = {"local", "global"};
73665de4495SJed Brown /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
7376a251517SEike Mueller static const char *HYPREBoomerAMGSmoothType[] = {"Schwarz-smoothers", "Pilut", "ParaSails", "Euclid"};
7389371c9d4SSatish 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"};
7399371c9d4SSatish 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"};
740d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc, PetscOptionItems *PetscOptionsObject)
741d71ae5a4SJacob Faibussowitsch {
74216d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
74322e51d31SStefano Zampini   PetscInt    bs, n, indx, level;
744ace3abfcSBarry Smith   PetscBool   flg, tmp_truth;
74516d9e3a6SLisandro Dalcin   double      tmpdbl, twodbl[2];
746589dcaf0SStefano Zampini   const char *symtlist[]           = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
747db6f9c32SMark Adams   const char *PCHYPRESpgemmTypes[] = {"cusparse", "hypre"};
74816d9e3a6SLisandro Dalcin 
74916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
750d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE BoomerAMG Options");
7519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_cycle_type", "Cycle type", "None", HYPREBoomerAMGCycleType + 1, 2, HYPREBoomerAMGCycleType[jac->cycletype], &indx, &flg));
75216d9e3a6SLisandro Dalcin   if (flg) {
7534336a9eeSBarry Smith     jac->cycletype = indx + 1;
754792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
75516d9e3a6SLisandro Dalcin   }
7569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_levels", "Number of levels (of grids) allowed", "None", jac->maxlevels, &jac->maxlevels, &flg));
75716d9e3a6SLisandro Dalcin   if (flg) {
75863a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxlevels >= 2, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of levels %" PetscInt_FMT " must be at least two", jac->maxlevels);
759792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
76016d9e3a6SLisandro Dalcin   }
7619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_iter", "Maximum iterations used PER hypre call", "None", jac->maxiter, &jac->maxiter, &flg));
76216d9e3a6SLisandro Dalcin   if (flg) {
76363a3b9bcSJacob Faibussowitsch     PetscCheck(jac->maxiter >= 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Number of iterations %" PetscInt_FMT " must be at least one", jac->maxiter);
764792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
76516d9e3a6SLisandro Dalcin   }
7669566063dSJacob 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));
76716d9e3a6SLisandro Dalcin   if (flg) {
76808401ef6SPierre 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);
769792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
77016d9e3a6SLisandro Dalcin   }
77122e51d31SStefano Zampini   bs = 1;
77248a46eb9SPierre Jolivet   if (pc->pmat) PetscCall(MatGetBlockSize(pc->pmat, &bs));
7739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_numfunctions", "Number of functions", "HYPRE_BoomerAMGSetNumFunctions", bs, &bs, &flg));
77448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNumFunctions, jac->hsolver, bs);
77516d9e3a6SLisandro Dalcin 
7769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_truncfactor", "Truncation factor for interpolation (0=no truncation)", "None", jac->truncfactor, &jac->truncfactor, &flg));
77716d9e3a6SLisandro Dalcin   if (flg) {
77808401ef6SPierre 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);
779792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
78016d9e3a6SLisandro Dalcin   }
78116d9e3a6SLisandro Dalcin 
7829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_P_max", "Max elements per row for interpolation operator (0=unlimited)", "None", jac->pmax, &jac->pmax, &flg));
7830f1074feSSatish Balay   if (flg) {
78463a3b9bcSJacob 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);
785792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
7860f1074feSSatish Balay   }
7870f1074feSSatish Balay 
7889566063dSJacob 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));
789792fecdfSBarry Smith   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
7900f1074feSSatish Balay 
7919566063dSJacob 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));
7920f1074feSSatish Balay   if (flg) {
79363a3b9bcSJacob 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);
794792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
7950f1074feSSatish Balay   }
7960f1074feSSatish Balay 
7979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold", "Threshold for being strongly connected", "None", jac->strongthreshold, &jac->strongthreshold, &flg));
79816d9e3a6SLisandro Dalcin   if (flg) {
79908401ef6SPierre 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);
800792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
80116d9e3a6SLisandro Dalcin   }
8029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum", "Maximum row sum", "None", jac->maxrowsum, &jac->maxrowsum, &flg));
80316d9e3a6SLisandro Dalcin   if (flg) {
80408401ef6SPierre 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);
80508401ef6SPierre 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);
806792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
80716d9e3a6SLisandro Dalcin   }
80816d9e3a6SLisandro Dalcin 
80916d9e3a6SLisandro Dalcin   /* Grid sweeps */
8109566063dSJacob 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));
81116d9e3a6SLisandro Dalcin   if (flg) {
812792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, indx);
81316d9e3a6SLisandro Dalcin     /* modify the jac structure so we can view the updated options with PC_View */
81416d9e3a6SLisandro Dalcin     jac->gridsweeps[0] = indx;
8150f1074feSSatish Balay     jac->gridsweeps[1] = indx;
8160f1074feSSatish Balay     /*defaults coarse to 1 */
8170f1074feSSatish Balay     jac->gridsweeps[2] = 1;
81816d9e3a6SLisandro Dalcin   }
8199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen", "Use a nodal based coarsening 1-6", "HYPRE_BoomerAMGSetNodal", jac->nodal_coarsening, &jac->nodal_coarsening, &flg));
82048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodal, jac->hsolver, jac->nodal_coarsening);
8219566063dSJacob 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));
82248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetNodalDiag, jac->hsolver, jac->nodal_coarsening_diag);
8239566063dSJacob 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));
82448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecVariant, jac->hsolver, jac->vec_interp_variant);
8259566063dSJacob 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));
82648a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpVecQMax, jac->hsolver, jac->vec_interp_qmax);
8279566063dSJacob 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));
82848a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetSmoothInterpVectors, jac->hsolver, jac->vec_interp_smooth);
8299566063dSJacob 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));
83048a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetInterpRefine, jac->hsolver, jac->interp_refine);
8319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down", "Number of sweeps for the down cycles", "None", jac->gridsweeps[0], &indx, &flg));
83216d9e3a6SLisandro Dalcin   if (flg) {
833792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 1);
8340f1074feSSatish Balay     jac->gridsweeps[0] = indx;
83516d9e3a6SLisandro Dalcin   }
8369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up", "Number of sweeps for the up cycles", "None", jac->gridsweeps[1], &indx, &flg));
83716d9e3a6SLisandro Dalcin   if (flg) {
838792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 2);
8390f1074feSSatish Balay     jac->gridsweeps[1] = indx;
84016d9e3a6SLisandro Dalcin   }
8419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse", "Number of sweeps for the coarse level", "None", jac->gridsweeps[2], &indx, &flg));
84216d9e3a6SLisandro Dalcin   if (flg) {
843792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleNumSweeps, jac->hsolver, indx, 3);
8440f1074feSSatish Balay     jac->gridsweeps[2] = indx;
84516d9e3a6SLisandro Dalcin   }
84616d9e3a6SLisandro Dalcin 
8476a251517SEike Mueller   /* Smooth type */
848dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_smooth_type", "Enable more complex smoothers", "None", HYPREBoomerAMGSmoothType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGSmoothType), HYPREBoomerAMGSmoothType[0], &indx, &flg));
8496a251517SEike Mueller   if (flg) {
8506a251517SEike Mueller     jac->smoothtype = indx;
851792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, indx + 6);
8528131ecf7SEike Mueller     jac->smoothnumlevels = 25;
853792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, 25);
8548131ecf7SEike Mueller   }
8558131ecf7SEike Mueller 
8568131ecf7SEike Mueller   /* Number of smoothing levels */
8579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels", "Number of levels on which more complex smoothers are used", "None", 25, &indx, &flg));
8588131ecf7SEike Mueller   if (flg && (jac->smoothtype != -1)) {
8598131ecf7SEike Mueller     jac->smoothnumlevels = indx;
860792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, indx);
8616a251517SEike Mueller   }
8626a251517SEike Mueller 
8631810e44eSEike Mueller   /* Number of levels for ILU(k) for Euclid */
8649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_eu_level", "Number of levels for ILU(k) in Euclid smoother", "None", 0, &indx, &flg));
8651810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8661810e44eSEike Mueller     jac->eu_level = indx;
867792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, indx);
8681810e44eSEike Mueller   }
8691810e44eSEike Mueller 
8701810e44eSEike Mueller   /* Filter for ILU(k) for Euclid */
8711810e44eSEike Mueller   double droptolerance;
8729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance", "Drop tolerance for ILU(k) in Euclid smoother", "None", 0, &droptolerance, &flg));
8731810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8741810e44eSEike Mueller     jac->eu_droptolerance = droptolerance;
875792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuLevel, jac->hsolver, droptolerance);
8761810e44eSEike Mueller   }
8771810e44eSEike Mueller 
8781810e44eSEike Mueller   /* Use Block Jacobi ILUT for Euclid */
8799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg));
8801810e44eSEike Mueller   if (flg && (jac->smoothtype == 3)) {
8811810e44eSEike Mueller     jac->eu_bj = tmp_truth;
882792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetEuBJ, jac->hsolver, jac->eu_bj);
8831810e44eSEike Mueller   }
8841810e44eSEike Mueller 
88516d9e3a6SLisandro Dalcin   /* Relax type */
886dd39110bSPierre 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));
88716d9e3a6SLisandro Dalcin   if (flg) {
8880f1074feSSatish Balay     jac->relaxtype[0] = jac->relaxtype[1] = indx;
889792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, indx);
8900f1074feSSatish Balay     /* by default, coarse type set to 9 */
8910f1074feSSatish Balay     jac->relaxtype[2] = 9;
892792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, 9, 3);
89316d9e3a6SLisandro Dalcin   }
894dd39110bSPierre 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));
89516d9e3a6SLisandro Dalcin   if (flg) {
89616d9e3a6SLisandro Dalcin     jac->relaxtype[0] = indx;
897792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 1);
89816d9e3a6SLisandro Dalcin   }
899dd39110bSPierre 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));
90016d9e3a6SLisandro Dalcin   if (flg) {
9010f1074feSSatish Balay     jac->relaxtype[1] = indx;
902792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 2);
90316d9e3a6SLisandro Dalcin   }
904dd39110bSPierre 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));
90516d9e3a6SLisandro Dalcin   if (flg) {
9060f1074feSSatish Balay     jac->relaxtype[2] = indx;
907792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleRelaxType, jac->hsolver, indx, 3);
90816d9e3a6SLisandro Dalcin   }
90916d9e3a6SLisandro Dalcin 
91016d9e3a6SLisandro Dalcin   /* Relaxation Weight */
9119566063dSJacob 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));
91216d9e3a6SLisandro Dalcin   if (flg) {
913792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxWt, jac->hsolver, tmpdbl);
91416d9e3a6SLisandro Dalcin     jac->relaxweight = tmpdbl;
91516d9e3a6SLisandro Dalcin   }
91616d9e3a6SLisandro Dalcin 
91716d9e3a6SLisandro Dalcin   n         = 2;
91816d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level", "Set the relaxation weight for a particular level (weight,level)", "None", twodbl, &n, &flg));
92016d9e3a6SLisandro Dalcin   if (flg) {
9210fdf79fbSJacob 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);
92216d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
923792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelRelaxWt, jac->hsolver, twodbl[0], indx);
92416d9e3a6SLisandro Dalcin   }
92516d9e3a6SLisandro Dalcin 
92616d9e3a6SLisandro Dalcin   /* Outer relaxation Weight */
9279566063dSJacob 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));
92816d9e3a6SLisandro Dalcin   if (flg) {
929792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOuterWt, jac->hsolver, tmpdbl);
93016d9e3a6SLisandro Dalcin     jac->outerrelaxweight = tmpdbl;
93116d9e3a6SLisandro Dalcin   }
93216d9e3a6SLisandro Dalcin 
93316d9e3a6SLisandro Dalcin   n         = 2;
93416d9e3a6SLisandro Dalcin   twodbl[0] = twodbl[1] = 1.0;
9359566063dSJacob 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));
93616d9e3a6SLisandro Dalcin   if (flg) {
9370fdf79fbSJacob 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);
93816d9e3a6SLisandro Dalcin     indx = (int)PetscAbsReal(twodbl[1]);
939792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetLevelOuterWt, jac->hsolver, twodbl[0], indx);
94016d9e3a6SLisandro Dalcin   }
94116d9e3a6SLisandro Dalcin 
94216d9e3a6SLisandro Dalcin   /* the Relax Order */
9439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg));
94416d9e3a6SLisandro Dalcin 
9458afaa268SBarry Smith   if (flg && tmp_truth) {
94616d9e3a6SLisandro Dalcin     jac->relaxorder = 0;
947792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
94816d9e3a6SLisandro Dalcin   }
949dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_measure_type", "Measure type", "None", HYPREBoomerAMGMeasureType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGMeasureType), HYPREBoomerAMGMeasureType[0], &indx, &flg));
95016d9e3a6SLisandro Dalcin   if (flg) {
95116d9e3a6SLisandro Dalcin     jac->measuretype = indx;
952792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
95316d9e3a6SLisandro Dalcin   }
9540f1074feSSatish Balay   /* update list length 3/07 */
955dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type", "Coarsen type", "None", HYPREBoomerAMGCoarsenType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGCoarsenType), HYPREBoomerAMGCoarsenType[6], &indx, &flg));
95616d9e3a6SLisandro Dalcin   if (flg) {
95716d9e3a6SLisandro Dalcin     jac->coarsentype = indx;
958792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
95916d9e3a6SLisandro Dalcin   }
9600f1074feSSatish Balay 
9619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg));
96248a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
9639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg));
96448a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
965db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
966db6f9c32SMark Adams   // global parameter but is closely associated with BoomerAMG
967dd39110bSPierre 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));
968db6f9c32SMark Adams   if (!flg) indx = 0;
9699566063dSJacob Faibussowitsch   PetscCall(PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG(pc, PCHYPRESpgemmTypes[indx]));
970db6f9c32SMark Adams #endif
971589dcaf0SStefano Zampini   /* AIR */
972589dcaf0SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
9739566063dSJacob 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));
974792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
975589dcaf0SStefano Zampini   if (jac->Rtype) {
976589dcaf0SStefano 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 */
977589dcaf0SStefano Zampini 
9789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR", "Threshold for R", "None", jac->Rstrongthreshold, &jac->Rstrongthreshold, NULL));
979792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
980589dcaf0SStefano Zampini 
9819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR", "Filter threshold for R", "None", jac->Rfilterthreshold, &jac->Rfilterthreshold, NULL));
982792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
983589dcaf0SStefano Zampini 
9849566063dSJacob 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));
985792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
986589dcaf0SStefano Zampini 
9879566063dSJacob 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));
988792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
989589dcaf0SStefano Zampini   }
990589dcaf0SStefano Zampini #endif
991589dcaf0SStefano Zampini 
992ecae95adSPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LE(9, 9, 9)
99363a3b9bcSJacob 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);
994ecae95adSPierre Jolivet #endif
995ecae95adSPierre Jolivet 
9960f1074feSSatish Balay   /* new 3/07 */
997dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_interp_type", "Interpolation type", "None", HYPREBoomerAMGInterpType, PETSC_STATIC_ARRAY_LENGTH(HYPREBoomerAMGInterpType), HYPREBoomerAMGInterpType[0], &indx, &flg));
998589dcaf0SStefano Zampini   if (flg || jac->Rtype) {
999589dcaf0SStefano Zampini     if (flg) jac->interptype = indx;
1000792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
10010f1074feSSatish Balay   }
10020f1074feSSatish Balay 
10039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", &flg));
100416d9e3a6SLisandro Dalcin   if (flg) {
1005b96a4a96SBarry Smith     level = 3;
10069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_statistics", "Print statistics", "None", level, &level, NULL));
10072fa5cd67SKarl Rupp 
1008b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1009792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPrintLevel, jac->hsolver, level);
10102ae77aedSBarry Smith   }
10112ae77aedSBarry Smith 
10129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", &flg));
10132ae77aedSBarry Smith   if (flg) {
1014b96a4a96SBarry Smith     level = 3;
10159566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_print_debug", "Print debug information", "None", level, &level, NULL));
10162fa5cd67SKarl Rupp 
1017b96a4a96SBarry Smith     jac->printstatistics = PETSC_TRUE;
1018792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDebugFlag, jac->hsolver, level);
101916d9e3a6SLisandro Dalcin   }
10208f87f92bSBarry Smith 
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg));
10228f87f92bSBarry Smith   if (flg && tmp_truth) {
10238f87f92bSBarry Smith     PetscInt tmp_int;
10249566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", jac->nodal_relax_levels, &tmp_int, &flg));
10258f87f92bSBarry Smith     if (flg) jac->nodal_relax_levels = tmp_int;
1026792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothType, jac->hsolver, 6);
1027792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetDomainType, jac->hsolver, 1);
1028792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetOverlap, jac->hsolver, 0);
1029792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSmoothNumLevels, jac->hsolver, jac->nodal_relax_levels);
10308f87f92bSBarry Smith   }
10318f87f92bSBarry Smith 
10329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL));
1033792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
1034589dcaf0SStefano Zampini 
1035589dcaf0SStefano Zampini   /* options for ParaSails solvers */
1036dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flg));
1037589dcaf0SStefano Zampini   if (flg) {
1038589dcaf0SStefano Zampini     jac->symt = indx;
1039792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetSym, jac->hsolver, jac->symt);
1040589dcaf0SStefano Zampini   }
1041589dcaf0SStefano Zampini 
1042d0609cedSBarry Smith   PetscOptionsHeadEnd();
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104416d9e3a6SLisandro Dalcin }
104516d9e3a6SLisandro Dalcin 
1046d71ae5a4SJacob 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)
1047d71ae5a4SJacob Faibussowitsch {
104816d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
10492cf14000SStefano Zampini   HYPRE_Int oits;
105016d9e3a6SLisandro Dalcin 
105116d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10529566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
1053792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, its * jac->maxiter);
1054792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, rtol);
105516d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_TRUE;
10569566063dSJacob Faibussowitsch   PetscCall(PCApply_HYPRE(pc, b, y));
105716d9e3a6SLisandro Dalcin   jac->applyrichardson = PETSC_FALSE;
1058792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGGetNumIterations, jac->hsolver, &oits);
10594d0a8057SBarry Smith   *outits = oits;
10604d0a8057SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
10614d0a8057SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
1062792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1063792fecdfSBarry Smith   PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
10643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106516d9e3a6SLisandro Dalcin }
106616d9e3a6SLisandro Dalcin 
1067d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc, PetscViewer viewer)
1068d71ae5a4SJacob Faibussowitsch {
106916d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1070ace3abfcSBarry Smith   PetscBool iascii;
107116d9e3a6SLisandro Dalcin 
107216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
10739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
107416d9e3a6SLisandro Dalcin   if (iascii) {
10759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE BoomerAMG preconditioning\n"));
10769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Cycle type %s\n", HYPREBoomerAMGCycleType[jac->cycletype]));
107763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of levels %" PetscInt_FMT "\n", jac->maxlevels));
107863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum number of iterations PER hypre call %" PetscInt_FMT "\n", jac->maxiter));
10799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Convergence tolerance PER hypre call %g\n", (double)jac->tol));
10809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Threshold for strong coupling %g\n", (double)jac->strongthreshold));
10819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation truncation factor %g\n", (double)jac->truncfactor));
108263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: max elements per row %" PetscInt_FMT "\n", jac->pmax));
108348a46eb9SPierre Jolivet     if (jac->interp_refine) PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation: number of steps of weighted refinement %" PetscInt_FMT "\n", jac->interp_refine));
108463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of levels of aggressive coarsening %" PetscInt_FMT "\n", jac->agg_nl));
108563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of paths for aggressive coarsening %" PetscInt_FMT "\n", jac->agg_num_paths));
10860f1074feSSatish Balay 
10879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Maximum row sums %g\n", (double)jac->maxrowsum));
108816d9e3a6SLisandro Dalcin 
108963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps down         %" PetscInt_FMT "\n", jac->gridsweeps[0]));
109063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps up           %" PetscInt_FMT "\n", jac->gridsweeps[1]));
109163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Sweeps on coarse    %" PetscInt_FMT "\n", jac->gridsweeps[2]));
109216d9e3a6SLisandro Dalcin 
10939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax down          %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[0]]));
10949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax up            %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[1]]));
10959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax on coarse     %s\n", HYPREBoomerAMGRelaxType[jac->relaxtype[2]]));
109616d9e3a6SLisandro Dalcin 
10979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Relax weight  (all)      %g\n", (double)jac->relaxweight));
10989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Outer relax weight (all) %g\n", (double)jac->outerrelaxweight));
109916d9e3a6SLisandro Dalcin 
110016d9e3a6SLisandro Dalcin     if (jac->relaxorder) {
11019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using CF-relaxation\n"));
110216d9e3a6SLisandro Dalcin     } else {
11039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using CF-relaxation\n"));
110416d9e3a6SLisandro Dalcin     }
11056a251517SEike Mueller     if (jac->smoothtype != -1) {
11069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth type          %s\n", HYPREBoomerAMGSmoothType[jac->smoothtype]));
110763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Smooth num levels    %" PetscInt_FMT "\n", jac->smoothnumlevels));
11087e352d70SEike Mueller     } else {
11099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Not using more complex smoothers.\n"));
11101810e44eSEike Mueller     }
11111810e44eSEike Mueller     if (jac->smoothtype == 3) {
111263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) levels %" PetscInt_FMT "\n", jac->eu_level));
11139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU(k) drop tolerance %g\n", (double)jac->eu_droptolerance));
111463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Euclid ILU use Block-Jacobi? %" PetscInt_FMT "\n", jac->eu_bj));
11156a251517SEike Mueller     }
11169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Measure type        %s\n", HYPREBoomerAMGMeasureType[jac->measuretype]));
11179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Coarsen type        %s\n", HYPREBoomerAMGCoarsenType[jac->coarsentype]));
11189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    Interpolation type  %s\n", jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt"));
111948a46eb9SPierre Jolivet     if (jac->nodal_coarsening) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %" PetscInt_FMT "\n", jac->nodal_coarsening));
11205272c319SBarry Smith     if (jac->vec_interp_variant) {
112163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecVariant() %" PetscInt_FMT "\n", jac->vec_interp_variant));
112263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetInterpVecQMax() %" PetscInt_FMT "\n", jac->vec_interp_qmax));
11239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n", jac->vec_interp_smooth));
11248f87f92bSBarry Smith     }
112548a46eb9SPierre Jolivet     if (jac->nodal_relax) PetscCall(PetscViewerASCIIPrintf(viewer, "    Using nodal relaxation via Schwarz smoothing on levels %" PetscInt_FMT "\n", jac->nodal_relax_levels));
1126db6f9c32SMark Adams #if PETSC_PKG_HYPRE_VERSION_GE(2, 23, 0)
11279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    SpGEMM type         %s\n", jac->spgemm_type));
1128db6f9c32SMark Adams #endif
1129589dcaf0SStefano Zampini     /* AIR */
1130589dcaf0SStefano Zampini     if (jac->Rtype) {
113163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    Using approximate ideal restriction type %" PetscInt_FMT "\n", jac->Rtype));
11329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Threshold for R %g\n", (double)jac->Rstrongthreshold));
11339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      Filter for R %g\n", (double)jac->Rfilterthreshold));
11349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop tolerance %g\n", (double)jac->Adroptol));
113563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "      A drop type %" PetscInt_FMT "\n", jac->Adroptype));
1136589dcaf0SStefano Zampini     }
113716d9e3a6SLisandro Dalcin   }
11383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
113916d9e3a6SLisandro Dalcin }
114016d9e3a6SLisandro Dalcin 
1141d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc, PetscOptionItems *PetscOptionsObject)
1142d71ae5a4SJacob Faibussowitsch {
114316d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
11444ddd07fcSJed Brown   PetscInt    indx;
1145ace3abfcSBarry Smith   PetscBool   flag;
114616d9e3a6SLisandro Dalcin   const char *symtlist[] = {"nonsymmetric", "SPD", "nonsymmetric,SPD"};
114716d9e3a6SLisandro Dalcin 
114816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
1149d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ParaSails Options");
11509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_parasails_nlevels", "Number of number of levels", "None", jac->nlevels, &jac->nlevels, 0));
11519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_thresh", "Threshold", "None", jac->threshold, &jac->threshold, &flag));
1152792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
115316d9e3a6SLisandro Dalcin 
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_filter", "filter", "None", jac->filter, &jac->filter, &flag));
1155792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
115616d9e3a6SLisandro Dalcin 
11579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_parasails_loadbal", "Load balance", "None", jac->loadbal, &jac->loadbal, &flag));
1158792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
115916d9e3a6SLisandro Dalcin 
11609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_logging", "Print info to screen", "None", (PetscBool)jac->logging, (PetscBool *)&jac->logging, &flag));
1161792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
116216d9e3a6SLisandro Dalcin 
11639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_hypre_parasails_reuse", "Reuse nonzero pattern in preconditioner", "None", (PetscBool)jac->ruse, (PetscBool *)&jac->ruse, &flag));
1164792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
116516d9e3a6SLisandro Dalcin 
1166dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_parasails_sym", "Symmetry of matrix and preconditioner", "None", symtlist, PETSC_STATIC_ARRAY_LENGTH(symtlist), symtlist[0], &indx, &flag));
116716d9e3a6SLisandro Dalcin   if (flag) {
116816d9e3a6SLisandro Dalcin     jac->symt = indx;
1169792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
117016d9e3a6SLisandro Dalcin   }
117116d9e3a6SLisandro Dalcin 
1172d0609cedSBarry Smith   PetscOptionsHeadEnd();
11733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
117416d9e3a6SLisandro Dalcin }
117516d9e3a6SLisandro Dalcin 
1176d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ParaSails(PC pc, PetscViewer viewer)
1177d71ae5a4SJacob Faibussowitsch {
117816d9e3a6SLisandro Dalcin   PC_HYPRE   *jac = (PC_HYPRE *)pc->data;
1179ace3abfcSBarry Smith   PetscBool   iascii;
1180feb237baSPierre Jolivet   const char *symt = 0;
118116d9e3a6SLisandro Dalcin 
118216d9e3a6SLisandro Dalcin   PetscFunctionBegin;
11839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
118416d9e3a6SLisandro Dalcin   if (iascii) {
11859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ParaSails preconditioning\n"));
118663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    nlevels %" PetscInt_FMT "\n", jac->nlevels));
11879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    threshold %g\n", (double)jac->threshold));
11889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    filter %g\n", (double)jac->filter));
11899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    load balance %g\n", (double)jac->loadbal));
11909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    reuse nonzero structure %s\n", PetscBools[jac->ruse]));
11919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    print info to screen %s\n", PetscBools[jac->logging]));
11922fa5cd67SKarl Rupp     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
11932fa5cd67SKarl Rupp     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
11942fa5cd67SKarl Rupp     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
119563a3b9bcSJacob Faibussowitsch     else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown HYPRE ParaSails symmetric option %" PetscInt_FMT, jac->symt);
11969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    %s\n", symt));
119716d9e3a6SLisandro Dalcin   }
11983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119916d9e3a6SLisandro Dalcin }
1200f1580f4eSBarry Smith 
1201d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PC pc, PetscOptionItems *PetscOptionsObject)
1202d71ae5a4SJacob Faibussowitsch {
12034cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12044cb006feSStefano Zampini   PetscInt  n;
12054cb006feSStefano Zampini   PetscBool flag, flag2, flag3, flag4;
12064cb006feSStefano Zampini 
12074cb006feSStefano Zampini   PetscFunctionBegin;
1208d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE AMS Options");
12099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_print_level", "Debugging output level for AMS", "None", jac->as_print, &jac->as_print, &flag));
1210792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
12119566063dSJacob 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));
1212792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
12139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_cycle_type", "Cycle type for AMS multigrid", "None", jac->ams_cycle_type, &jac->ams_cycle_type, &flag));
1214792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
12159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_tol", "Error tolerance for AMS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1216792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
12179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ams_relax_type", "Relaxation type for AMS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
12189566063dSJacob 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));
12199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_relax_weight", "Relaxation weight for AMS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
12209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ams_omega", "SSOR coefficient for AMS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
122148a46eb9SPierre 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);
12229566063dSJacob 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));
12234cb006feSStefano Zampini   n = 5;
12249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options", "AMG options for vector Poisson", "None", jac->as_amg_alpha_opts, &n, &flag2));
12254cb006feSStefano Zampini   if (flag || flag2) {
1226792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
1227863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
1228863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
12299371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
1230a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
12314cb006feSStefano Zampini   }
12329566063dSJacob 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));
12334cb006feSStefano Zampini   n = 5;
12349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options", "AMG options for scalar Poisson solver", "None", jac->as_amg_beta_opts, &n, &flag2));
12354cb006feSStefano Zampini   if (flag || flag2) {
1236792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1237863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                           /* AMG agg_levels */
1238863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                           /* AMG relax_type */
12399371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                   /* AMG interp_type */
1240a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                          /* AMG Pmax */
12414cb006feSStefano Zampini   }
12429566063dSJacob 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));
124323df4f25SStefano Zampini   if (flag) { /* override HYPRE's default only if the options is used */
1244792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetProjectionFrequency, jac->hsolver, jac->ams_proj_freq);
124523df4f25SStefano Zampini   }
1246d0609cedSBarry Smith   PetscOptionsHeadEnd();
12473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12484cb006feSStefano Zampini }
12494cb006feSStefano Zampini 
1250d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_AMS(PC pc, PetscViewer viewer)
1251d71ae5a4SJacob Faibussowitsch {
12524cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
12534cb006feSStefano Zampini   PetscBool iascii;
12544cb006feSStefano Zampini 
12554cb006feSStefano Zampini   PetscFunctionBegin;
12569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
12574cb006feSStefano Zampini   if (iascii) {
12589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE AMS preconditioning\n"));
125963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
126063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
126163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
126263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
126363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
126463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
126563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
12664cb006feSStefano Zampini     if (jac->alpha_Poisson) {
12679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (passed in by user)\n"));
12684cb006feSStefano Zampini     } else {
12699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver (computed) \n"));
12704cb006feSStefano Zampini     }
127163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
127263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
127363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
127463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
127563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
127663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_alpha_theta));
12774cb006feSStefano Zampini     if (!jac->ams_beta_is_zero) {
12784cb006feSStefano Zampini       if (jac->beta_Poisson) {
12799566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (passed in by user)\n"));
12804cb006feSStefano Zampini       } else {
12819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver (computed) \n"));
12824cb006feSStefano Zampini       }
128363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
128463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
128563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
128663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
128763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
128863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "        boomerAMG strength threshold %g\n", (double)jac->as_amg_beta_theta));
128948a46eb9SPierre 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));
129023df4f25SStefano Zampini     } else {
12919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "    scalar Poisson solver not used (zero-conductivity everywhere) \n"));
12924cb006feSStefano Zampini     }
12934cb006feSStefano Zampini   }
12943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12954cb006feSStefano Zampini }
12964cb006feSStefano Zampini 
1297d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PC pc, PetscOptionItems *PetscOptionsObject)
1298d71ae5a4SJacob Faibussowitsch {
1299863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1300863406b8SStefano Zampini   PetscInt  n;
1301863406b8SStefano Zampini   PetscBool flag, flag2, flag3, flag4;
1302863406b8SStefano Zampini 
1303863406b8SStefano Zampini   PetscFunctionBegin;
1304d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE ADS Options");
13059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_print_level", "Debugging output level for ADS", "None", jac->as_print, &jac->as_print, &flag));
1306792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
13079566063dSJacob 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));
1308792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
13099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_cycle_type", "Cycle type for ADS multigrid", "None", jac->ads_cycle_type, &jac->ads_cycle_type, &flag));
1310792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ads_cycle_type);
13119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_tol", "Error tolerance for ADS multigrid", "None", jac->as_tol, &jac->as_tol, &flag));
1312792fecdfSBarry Smith   if (flag) PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
13139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_hypre_ads_relax_type", "Relaxation type for ADS smoother", "None", jac->as_relax_type, &jac->as_relax_type, &flag));
13149566063dSJacob 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));
13159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_relax_weight", "Relaxation weight for ADS smoother", "None", jac->as_relax_weight, &jac->as_relax_weight, &flag3));
13169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_hypre_ads_omega", "SSOR coefficient for ADS smoother", "None", jac->as_omega, &jac->as_omega, &flag4));
131748a46eb9SPierre 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);
13189566063dSJacob 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));
1319863406b8SStefano Zampini   n = 5;
13209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_ams_options", "AMG options for AMS solver inside ADS", "None", jac->as_amg_alpha_opts, &n, &flag2));
13219566063dSJacob 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));
1322863406b8SStefano Zampini   if (flag || flag2 || flag3) {
1323792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type, /* AMS cycle type */
1324863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                 /* AMG coarsen type */
1325863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                 /* AMG agg_levels */
1326863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                 /* AMG relax_type */
13279371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],        /* AMG interp_type */
1328a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                /* AMG Pmax */
1329863406b8SStefano Zampini   }
13309566063dSJacob 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));
1331863406b8SStefano Zampini   n = 5;
13329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-pc_hypre_ads_amg_options", "AMG options for vector AMG solver inside ADS", "None", jac->as_amg_beta_opts, &n, &flag2));
1333863406b8SStefano Zampini   if (flag || flag2) {
1334792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
1335863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
1336863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
13379371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
1338a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
1339863406b8SStefano Zampini   }
1340d0609cedSBarry Smith   PetscOptionsHeadEnd();
13413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1342863406b8SStefano Zampini }
1343863406b8SStefano Zampini 
1344d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_HYPRE_ADS(PC pc, PetscViewer viewer)
1345d71ae5a4SJacob Faibussowitsch {
1346863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1347863406b8SStefano Zampini   PetscBool iascii;
1348863406b8SStefano Zampini 
1349863406b8SStefano Zampini   PetscFunctionBegin;
13509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1351863406b8SStefano Zampini   if (iascii) {
13529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE ADS preconditioning\n"));
135363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iterations per application %" PetscInt_FMT "\n", jac->as_max_iter));
135463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace cycle type %" PetscInt_FMT "\n", jac->ads_cycle_type));
135563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    subspace iteration tolerance %g\n", (double)jac->as_tol));
135663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother type %" PetscInt_FMT "\n", jac->as_relax_type));
135763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number of smoothing steps %" PetscInt_FMT "\n", jac->as_relax_times));
135863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother weight %g\n", (double)jac->as_relax_weight));
135963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    smoother omega %g\n", (double)jac->as_omega));
13609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    AMS solver using boomerAMG\n"));
136163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        subspace cycle type %" PetscInt_FMT "\n", jac->ams_cycle_type));
136263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[0]));
136363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[1]));
136463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[2]));
136563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[3]));
136663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_alpha_opts[4]));
136763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_alpha_theta));
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    vector Poisson solver using boomerAMG\n"));
136963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        coarsening type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[0]));
137063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        levels of aggressive coarsening %" PetscInt_FMT "\n", jac->as_amg_beta_opts[1]));
137163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        relaxation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[2]));
137263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        interpolation type %" PetscInt_FMT "\n", jac->as_amg_beta_opts[3]));
137363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        max nonzero elements in interpolation rows %" PetscInt_FMT "\n", jac->as_amg_beta_opts[4]));
137463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "        strength threshold %g\n", (double)jac->as_amg_beta_theta));
1375863406b8SStefano Zampini   }
13763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1377863406b8SStefano Zampini }
1378863406b8SStefano Zampini 
1379d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1380d71ae5a4SJacob Faibussowitsch {
13814cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
13825ac14e1cSStefano Zampini   PetscBool ishypre;
13834cb006feSStefano Zampini 
13844cb006feSStefano Zampini   PetscFunctionBegin;
13859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)G, MATHYPRE, &ishypre));
13865ac14e1cSStefano Zampini   if (ishypre) {
13879566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)G));
13889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13895ac14e1cSStefano Zampini     jac->G = G;
13905ac14e1cSStefano Zampini   } else {
13919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->G));
13929566063dSJacob Faibussowitsch     PetscCall(MatConvert(G, MATHYPRE, MAT_INITIAL_MATRIX, &jac->G));
13935ac14e1cSStefano Zampini   }
13943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13954cb006feSStefano Zampini }
13964cb006feSStefano Zampini 
13974cb006feSStefano Zampini /*@
1398f1580f4eSBarry Smith    PCHYPRESetDiscreteGradient - Set discrete gradient matrix for `PCHYPRE` type of ams or ads
13994cb006feSStefano Zampini 
1400c3339decSBarry Smith    Collective
14014cb006feSStefano Zampini 
14024cb006feSStefano Zampini    Input Parameters:
14034cb006feSStefano Zampini +  pc - the preconditioning context
14044cb006feSStefano Zampini -  G - the discrete gradient
14054cb006feSStefano Zampini 
14064cb006feSStefano Zampini    Level: intermediate
14074cb006feSStefano Zampini 
140895452b02SPatrick Sanan    Notes:
140995452b02SPatrick Sanan     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1410147403d9SBarry Smith 
1411863406b8SStefano 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
14124cb006feSStefano Zampini 
1413f1580f4eSBarry Smith    Developer Note:
1414f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1415f1580f4eSBarry Smith 
1416f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteCurl()`
14174cb006feSStefano Zampini @*/
1418d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1419d71ae5a4SJacob Faibussowitsch {
14204cb006feSStefano Zampini   PetscFunctionBegin;
14214cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14224cb006feSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
14234cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
1424cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteGradient_C", (PC, Mat), (pc, G));
14253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14264cb006feSStefano Zampini }
14274cb006feSStefano Zampini 
1428d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1429d71ae5a4SJacob Faibussowitsch {
1430863406b8SStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14315ac14e1cSStefano Zampini   PetscBool ishypre;
1432863406b8SStefano Zampini 
1433863406b8SStefano Zampini   PetscFunctionBegin;
14349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATHYPRE, &ishypre));
14355ac14e1cSStefano Zampini   if (ishypre) {
14369566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)C));
14379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14385ac14e1cSStefano Zampini     jac->C = C;
14395ac14e1cSStefano Zampini   } else {
14409566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->C));
14419566063dSJacob Faibussowitsch     PetscCall(MatConvert(C, MATHYPRE, MAT_INITIAL_MATRIX, &jac->C));
14425ac14e1cSStefano Zampini   }
14433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1444863406b8SStefano Zampini }
1445863406b8SStefano Zampini 
1446863406b8SStefano Zampini /*@
1447f1580f4eSBarry Smith    PCHYPRESetDiscreteCurl - Set discrete curl matrx for `PCHYPRE` type of ads
1448863406b8SStefano Zampini 
1449c3339decSBarry Smith    Collective
1450863406b8SStefano Zampini 
1451863406b8SStefano Zampini    Input Parameters:
1452863406b8SStefano Zampini +  pc - the preconditioning context
1453863406b8SStefano Zampini -  C - the discrete curl
1454863406b8SStefano Zampini 
1455863406b8SStefano Zampini    Level: intermediate
1456863406b8SStefano Zampini 
145795452b02SPatrick Sanan    Notes:
145895452b02SPatrick Sanan     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1459147403d9SBarry Smith 
1460863406b8SStefano 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
1461863406b8SStefano Zampini 
1462f1580f4eSBarry Smith    Developer Note:
1463f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1464f1580f4eSBarry Smith 
1465f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ads it should be called `PCHYPREADSSetDiscreteCurl()`
1466f1580f4eSBarry Smith 
1467f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`
1468863406b8SStefano Zampini @*/
1469d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1470d71ae5a4SJacob Faibussowitsch {
1471863406b8SStefano Zampini   PetscFunctionBegin;
1472863406b8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1473863406b8SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 2);
1474863406b8SStefano Zampini   PetscCheckSameComm(pc, 1, C, 2);
1475cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetDiscreteCurl_C", (PC, Mat), (pc, C));
14763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1477863406b8SStefano Zampini }
1478863406b8SStefano Zampini 
1479d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1480d71ae5a4SJacob Faibussowitsch {
14816bf688a0SCe Qin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
14826bf688a0SCe Qin   PetscBool ishypre;
14836bf688a0SCe Qin   PetscInt  i;
14846bf688a0SCe Qin   PetscFunctionBegin;
14856bf688a0SCe Qin 
14869566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->RT_PiFull));
14879566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->ND_PiFull));
14886bf688a0SCe Qin   for (i = 0; i < 3; ++i) {
14899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->RT_Pi[i]));
14909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&jac->ND_Pi[i]));
14916bf688a0SCe Qin   }
14926bf688a0SCe Qin 
14936bf688a0SCe Qin   jac->dim = dim;
14946bf688a0SCe Qin   if (RT_PiFull) {
14959566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)RT_PiFull, MATHYPRE, &ishypre));
14966bf688a0SCe Qin     if (ishypre) {
14979566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)RT_PiFull));
14986bf688a0SCe Qin       jac->RT_PiFull = RT_PiFull;
14996bf688a0SCe Qin     } else {
15009566063dSJacob Faibussowitsch       PetscCall(MatConvert(RT_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_PiFull));
15016bf688a0SCe Qin     }
15026bf688a0SCe Qin   }
15036bf688a0SCe Qin   if (RT_Pi) {
15046bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15056bf688a0SCe Qin       if (RT_Pi[i]) {
15069566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)RT_Pi[i], MATHYPRE, &ishypre));
15076bf688a0SCe Qin         if (ishypre) {
15089566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)RT_Pi[i]));
15096bf688a0SCe Qin           jac->RT_Pi[i] = RT_Pi[i];
15106bf688a0SCe Qin         } else {
15119566063dSJacob Faibussowitsch           PetscCall(MatConvert(RT_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->RT_Pi[i]));
15126bf688a0SCe Qin         }
15136bf688a0SCe Qin       }
15146bf688a0SCe Qin     }
15156bf688a0SCe Qin   }
15166bf688a0SCe Qin   if (ND_PiFull) {
15179566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)ND_PiFull, MATHYPRE, &ishypre));
15186bf688a0SCe Qin     if (ishypre) {
15199566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)ND_PiFull));
15206bf688a0SCe Qin       jac->ND_PiFull = ND_PiFull;
15216bf688a0SCe Qin     } else {
15229566063dSJacob Faibussowitsch       PetscCall(MatConvert(ND_PiFull, MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_PiFull));
15236bf688a0SCe Qin     }
15246bf688a0SCe Qin   }
15256bf688a0SCe Qin   if (ND_Pi) {
15266bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15276bf688a0SCe Qin       if (ND_Pi[i]) {
15289566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)ND_Pi[i], MATHYPRE, &ishypre));
15296bf688a0SCe Qin         if (ishypre) {
15309566063dSJacob Faibussowitsch           PetscCall(PetscObjectReference((PetscObject)ND_Pi[i]));
15316bf688a0SCe Qin           jac->ND_Pi[i] = ND_Pi[i];
15326bf688a0SCe Qin         } else {
15339566063dSJacob Faibussowitsch           PetscCall(MatConvert(ND_Pi[i], MATHYPRE, MAT_INITIAL_MATRIX, &jac->ND_Pi[i]));
15346bf688a0SCe Qin         }
15356bf688a0SCe Qin       }
15366bf688a0SCe Qin     }
15376bf688a0SCe Qin   }
15386bf688a0SCe Qin 
15393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15406bf688a0SCe Qin }
15416bf688a0SCe Qin 
15426bf688a0SCe Qin /*@
1543f1580f4eSBarry Smith    PCHYPRESetInterpolations - Set interpolation matrices for `PCHYPRE` type of ams or ads
15446bf688a0SCe Qin 
1545c3339decSBarry Smith    Collective
15466bf688a0SCe Qin 
15476bf688a0SCe Qin    Input Parameters:
15486bf688a0SCe Qin +  pc - the preconditioning context
15492fe279fdSBarry Smith .  dim - the dimension of the problem, only used in AMS
15502fe279fdSBarry Smith .  RT_PiFull - Raviart-Thomas interpolation matrix
15512fe279fdSBarry Smith .  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
15522fe279fdSBarry Smith .  ND_PiFull - Nedelec interpolation matrix
15536bf688a0SCe Qin -  ND_Pi - x/y/z component of Nedelec interpolation matrix
15546bf688a0SCe Qin 
1555f1580f4eSBarry Smith    Level: intermediate
1556f1580f4eSBarry Smith 
155795452b02SPatrick Sanan    Notes:
155895452b02SPatrick Sanan     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1559147403d9SBarry Smith 
15606bf688a0SCe Qin     For ADS, both type of interpolation matrices are needed.
1561147403d9SBarry Smith 
1562f1580f4eSBarry Smith    Developer Note:
1563f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
15646bf688a0SCe Qin 
1565f1580f4eSBarry Smith .seealso: `PCHYPRE`
15666bf688a0SCe Qin @*/
1567d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1568d71ae5a4SJacob Faibussowitsch {
15696bf688a0SCe Qin   PetscInt i;
15706bf688a0SCe Qin 
15716bf688a0SCe Qin   PetscFunctionBegin;
15726bf688a0SCe Qin   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
15736bf688a0SCe Qin   if (RT_PiFull) {
15746bf688a0SCe Qin     PetscValidHeaderSpecific(RT_PiFull, MAT_CLASSID, 3);
15756bf688a0SCe Qin     PetscCheckSameComm(pc, 1, RT_PiFull, 3);
15766bf688a0SCe Qin   }
15776bf688a0SCe Qin   if (RT_Pi) {
15786bf688a0SCe Qin     PetscValidPointer(RT_Pi, 4);
15796bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15806bf688a0SCe Qin       if (RT_Pi[i]) {
15816bf688a0SCe Qin         PetscValidHeaderSpecific(RT_Pi[i], MAT_CLASSID, 4);
15826bf688a0SCe Qin         PetscCheckSameComm(pc, 1, RT_Pi[i], 4);
15836bf688a0SCe Qin       }
15846bf688a0SCe Qin     }
15856bf688a0SCe Qin   }
15866bf688a0SCe Qin   if (ND_PiFull) {
15876bf688a0SCe Qin     PetscValidHeaderSpecific(ND_PiFull, MAT_CLASSID, 5);
15886bf688a0SCe Qin     PetscCheckSameComm(pc, 1, ND_PiFull, 5);
15896bf688a0SCe Qin   }
15906bf688a0SCe Qin   if (ND_Pi) {
15916bf688a0SCe Qin     PetscValidPointer(ND_Pi, 6);
15926bf688a0SCe Qin     for (i = 0; i < dim; ++i) {
15936bf688a0SCe Qin       if (ND_Pi[i]) {
15946bf688a0SCe Qin         PetscValidHeaderSpecific(ND_Pi[i], MAT_CLASSID, 6);
15956bf688a0SCe Qin         PetscCheckSameComm(pc, 1, ND_Pi[i], 6);
15966bf688a0SCe Qin       }
15976bf688a0SCe Qin     }
15986bf688a0SCe Qin   }
1599cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetInterpolations_C", (PC, PetscInt, Mat, Mat[], Mat, Mat[]), (pc, dim, RT_PiFull, RT_Pi, ND_PiFull, ND_Pi));
16003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16016bf688a0SCe Qin }
16026bf688a0SCe Qin 
1603d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1604d71ae5a4SJacob Faibussowitsch {
16054cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
16065ac14e1cSStefano Zampini   PetscBool ishypre;
16074cb006feSStefano Zampini 
16084cb006feSStefano Zampini   PetscFunctionBegin;
16099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
16105ac14e1cSStefano Zampini   if (ishypre) {
16115ac14e1cSStefano Zampini     if (isalpha) {
16129566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
16139566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16145ac14e1cSStefano Zampini       jac->alpha_Poisson = A;
16155ac14e1cSStefano Zampini     } else {
16165ac14e1cSStefano Zampini       if (A) {
16179566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)A));
16185ac14e1cSStefano Zampini       } else {
16195ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16205ac14e1cSStefano Zampini       }
16219566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->beta_Poisson));
16225ac14e1cSStefano Zampini       jac->beta_Poisson = A;
16235ac14e1cSStefano Zampini     }
16245ac14e1cSStefano Zampini   } else {
16255ac14e1cSStefano Zampini     if (isalpha) {
16269566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&jac->alpha_Poisson));
16279566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->alpha_Poisson));
16285ac14e1cSStefano Zampini     } else {
16295ac14e1cSStefano Zampini       if (A) {
16309566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16319566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &jac->beta_Poisson));
16325ac14e1cSStefano Zampini       } else {
16339566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&jac->beta_Poisson));
16345ac14e1cSStefano Zampini         jac->ams_beta_is_zero = PETSC_TRUE;
16355ac14e1cSStefano Zampini       }
16365ac14e1cSStefano Zampini     }
16375ac14e1cSStefano Zampini   }
16383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16394cb006feSStefano Zampini }
16404cb006feSStefano Zampini 
16414cb006feSStefano Zampini /*@
1642f1580f4eSBarry Smith    PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix for `PCHYPRE` of type ams
16434cb006feSStefano Zampini 
1644c3339decSBarry Smith    Collective
16454cb006feSStefano Zampini 
16464cb006feSStefano Zampini    Input Parameters:
16474cb006feSStefano Zampini +  pc - the preconditioning context
16484cb006feSStefano Zampini -  A - the matrix
16494cb006feSStefano Zampini 
16504cb006feSStefano Zampini    Level: intermediate
16514cb006feSStefano Zampini 
1652f1580f4eSBarry Smith    Note:
165395452b02SPatrick Sanan     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
16544cb006feSStefano Zampini 
1655f1580f4eSBarry Smith    Developer Note:
1656f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1657f1580f4eSBarry Smith 
1658f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetAlphaPoissonMatrix()`
1659f1580f4eSBarry Smith 
1660f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetBetaPoissonMatrix()`
16614cb006feSStefano Zampini @*/
1662d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1663d71ae5a4SJacob Faibussowitsch {
16644cb006feSStefano Zampini   PetscFunctionBegin;
16654cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16664cb006feSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16674cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, A, 2);
1668cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_TRUE));
16693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16704cb006feSStefano Zampini }
16714cb006feSStefano Zampini 
16724cb006feSStefano Zampini /*@
1673f1580f4eSBarry Smith    PCHYPRESetBetaPoissonMatrix - Set Poisson matrix for `PCHYPRE` of type ams
16744cb006feSStefano Zampini 
1675c3339decSBarry Smith    Collective
16764cb006feSStefano Zampini 
16774cb006feSStefano Zampini    Input Parameters:
16784cb006feSStefano Zampini +  pc - the preconditioning context
1679f1580f4eSBarry Smith -  A - the matrix, or NULL to turn it off
16804cb006feSStefano Zampini 
16814cb006feSStefano Zampini    Level: intermediate
16824cb006feSStefano Zampini 
1683f1580f4eSBarry Smith    Note:
168495452b02SPatrick Sanan    A should be obtained by discretizing the Poisson problem with linear finite elements.
16854cb006feSStefano Zampini 
1686f1580f4eSBarry Smith    Developer Note:
1687f1580f4eSBarry Smith    This automatically converts the matrix to `MATHYPRE` if it is not already of that type
1688f1580f4eSBarry Smith 
1689f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSPCHYPRESetBetaPoissonMatrix()`
1690f1580f4eSBarry Smith 
1691f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
16924cb006feSStefano Zampini @*/
1693d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1694d71ae5a4SJacob Faibussowitsch {
16954cb006feSStefano Zampini   PetscFunctionBegin;
16964cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
16974cb006feSStefano Zampini   if (A) {
16984cb006feSStefano Zampini     PetscValidHeaderSpecific(A, MAT_CLASSID, 2);
16994cb006feSStefano Zampini     PetscCheckSameComm(pc, 1, A, 2);
17004cb006feSStefano Zampini   }
1701cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetPoissonMatrix_C", (PC, Mat, PetscBool), (pc, A, PETSC_FALSE));
17023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17034cb006feSStefano Zampini }
17044cb006feSStefano Zampini 
1705d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc, Vec ozz, Vec zoz, Vec zzo)
1706d71ae5a4SJacob Faibussowitsch {
17074cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
17084cb006feSStefano Zampini 
17094cb006feSStefano Zampini   PetscFunctionBegin;
17104cb006feSStefano Zampini   /* throw away any vector if already set */
17119566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[0]));
17129566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[1]));
17139566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->constants[2]));
17149566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(ozz->map, &jac->constants[0]));
17159566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(ozz, jac->constants[0]));
17169566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCreate(zoz->map, &jac->constants[1]));
17179566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorCopy(zoz, jac->constants[1]));
17185ac14e1cSStefano Zampini   jac->dim = 2;
17194cb006feSStefano Zampini   if (zzo) {
17209566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(zzo->map, &jac->constants[2]));
17219566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(zzo, jac->constants[2]));
17225ac14e1cSStefano Zampini     jac->dim++;
17234cb006feSStefano Zampini   }
17243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17254cb006feSStefano Zampini }
17264cb006feSStefano Zampini 
17274cb006feSStefano Zampini /*@
1728f1580f4eSBarry Smith    PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in the edge element basis for `PCHYPRE` of type ams
17294cb006feSStefano Zampini 
1730c3339decSBarry Smith    Collective
17314cb006feSStefano Zampini 
17324cb006feSStefano Zampini    Input Parameters:
17334cb006feSStefano Zampini +  pc - the preconditioning context
17342fe279fdSBarry Smith .  ozz - vector representing (1,0,0) (or (1,0) in 2D)
17352fe279fdSBarry Smith .  zoz - vector representing (0,1,0) (or (0,1) in 2D)
17364cb006feSStefano Zampini -  zzo - vector representing (0,0,1) (use NULL in 2D)
17374cb006feSStefano Zampini 
17384cb006feSStefano Zampini    Level: intermediate
17394cb006feSStefano Zampini 
1740f1580f4eSBarry Smith    Developer Note:
1741f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetEdgeConstantVectors()`
1742f1580f4eSBarry Smith 
1743f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
17444cb006feSStefano Zampini @*/
1745d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1746d71ae5a4SJacob Faibussowitsch {
17474cb006feSStefano Zampini   PetscFunctionBegin;
17484cb006feSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
17494cb006feSStefano Zampini   PetscValidHeaderSpecific(ozz, VEC_CLASSID, 2);
17504cb006feSStefano Zampini   PetscValidHeaderSpecific(zoz, VEC_CLASSID, 3);
17514cb006feSStefano Zampini   if (zzo) PetscValidHeaderSpecific(zzo, VEC_CLASSID, 4);
17524cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, ozz, 2);
17534cb006feSStefano Zampini   PetscCheckSameComm(pc, 1, zoz, 3);
17544cb006feSStefano Zampini   if (zzo) PetscCheckSameComm(pc, 1, zzo, 4);
1755cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetEdgeConstantVectors_C", (PC, Vec, Vec, Vec), (pc, ozz, zoz, zzo));
17563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17574cb006feSStefano Zampini }
17584cb006feSStefano Zampini 
1759d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREAMSSetInteriorNodes_HYPRE(PC pc, Vec interior)
1760d71ae5a4SJacob Faibussowitsch {
1761be14dc20SKerry Key   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1762be14dc20SKerry Key 
1763be14dc20SKerry Key   PetscFunctionBegin;
1764be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorDestroy(&jac->interior));
1765be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCreate(interior->map, &jac->interior));
1766be14dc20SKerry Key   PetscCall(VecHYPRE_IJVectorCopy(interior, jac->interior));
1767be14dc20SKerry Key   jac->ams_beta_is_zero_part = PETSC_TRUE;
17683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1769be14dc20SKerry Key }
1770be14dc20SKerry Key 
1771be14dc20SKerry Key /*@
1772f1580f4eSBarry Smith   PCHYPREAMSSetInteriorNodes - Set the list of interior nodes to a zero-conductivity region for `PCHYPRE` of type ams
1773be14dc20SKerry Key 
1774c3339decSBarry Smith    Collective
1775be14dc20SKerry Key 
1776be14dc20SKerry Key    Input Parameters:
1777be14dc20SKerry Key +  pc - the preconditioning context
1778be14dc20SKerry Key -  interior - vector. node is interior if its entry in the array is 1.0.
1779be14dc20SKerry Key 
1780be14dc20SKerry Key    Level: intermediate
1781be14dc20SKerry Key 
1782be14dc20SKerry Key    Note:
1783f1580f4eSBarry Smith    This calls `HYPRE_AMSSetInteriorNodes()`
1784f1580f4eSBarry Smith 
1785f1580f4eSBarry Smith    Developer Note:
1786f1580f4eSBarry Smith    If this is only for  `PCHYPRE` type of ams it should be called `PCHYPREAMSSetInteriorNodes()`
1787f1580f4eSBarry Smith 
1788f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCHYPRESetDiscreteGradient()`, `PCHYPRESetDiscreteCurl()`, `PCHYPRESetAlphaPoissonMatrix()`
1789be14dc20SKerry Key @*/
1790d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREAMSSetInteriorNodes(PC pc, Vec interior)
1791d71ae5a4SJacob Faibussowitsch {
1792be14dc20SKerry Key   PetscFunctionBegin;
1793be14dc20SKerry Key   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1794be14dc20SKerry Key   PetscValidHeaderSpecific(interior, VEC_CLASSID, 2);
1795be14dc20SKerry Key   PetscCheckSameComm(pc, 1, interior, 2);
1796be14dc20SKerry Key   PetscTryMethod(pc, "PCHYPREAMSSetInteriorNodes_C", (PC, Vec), (pc, interior));
17973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1798be14dc20SKerry Key }
1799be14dc20SKerry Key 
1800d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1801d71ae5a4SJacob Faibussowitsch {
18024cb006feSStefano Zampini   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
18034cb006feSStefano Zampini   Vec       tv;
18044cb006feSStefano Zampini   PetscInt  i;
18054cb006feSStefano Zampini 
18064cb006feSStefano Zampini   PetscFunctionBegin;
18074cb006feSStefano Zampini   /* throw away any coordinate vector if already set */
18089566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[0]));
18099566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[1]));
18109566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&jac->coords[2]));
18115ac14e1cSStefano Zampini   jac->dim = dim;
18125ac14e1cSStefano Zampini 
18134cb006feSStefano Zampini   /* compute IJ vector for coordinates */
18149566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &tv));
18159566063dSJacob Faibussowitsch   PetscCall(VecSetType(tv, VECSTANDARD));
18169566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(tv, nloc, PETSC_DECIDE));
18174cb006feSStefano Zampini   for (i = 0; i < dim; i++) {
18184cb006feSStefano Zampini     PetscScalar *array;
18194cb006feSStefano Zampini     PetscInt     j;
18204cb006feSStefano Zampini 
18219566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCreate(tv->map, &jac->coords[i]));
18229566063dSJacob Faibussowitsch     PetscCall(VecGetArrayWrite(tv, &array));
18236ea7df73SStefano Zampini     for (j = 0; j < nloc; j++) array[j] = coords[j * dim + i];
18249566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayWrite(tv, &array));
18259566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorCopy(tv, jac->coords[i]));
18264cb006feSStefano Zampini   }
18279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tv));
18283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18294cb006feSStefano Zampini }
18304cb006feSStefano Zampini 
1831d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPREGetType_HYPRE(PC pc, const char *name[])
1832d71ae5a4SJacob Faibussowitsch {
183316d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
183416d9e3a6SLisandro Dalcin 
183516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
183616d9e3a6SLisandro Dalcin   *name = jac->hypre_type;
18373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
183816d9e3a6SLisandro Dalcin }
183916d9e3a6SLisandro Dalcin 
1840d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCHYPRESetType_HYPRE(PC pc, const char name[])
1841d71ae5a4SJacob Faibussowitsch {
184216d9e3a6SLisandro Dalcin   PC_HYPRE *jac = (PC_HYPRE *)pc->data;
1843ace3abfcSBarry Smith   PetscBool flag;
184416d9e3a6SLisandro Dalcin 
184516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
184616d9e3a6SLisandro Dalcin   if (jac->hypre_type) {
18479566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(jac->hypre_type, name, &flag));
18485f80ce2aSJacob Faibussowitsch     PetscCheck(flag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ORDER, "Cannot reset the HYPRE preconditioner type once it has been set");
18493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
185016d9e3a6SLisandro Dalcin   } else {
18519566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &jac->hypre_type));
185216d9e3a6SLisandro Dalcin   }
185316d9e3a6SLisandro Dalcin 
185416d9e3a6SLisandro Dalcin   jac->maxiter         = PETSC_DEFAULT;
185516d9e3a6SLisandro Dalcin   jac->tol             = PETSC_DEFAULT;
185616d9e3a6SLisandro Dalcin   jac->printstatistics = PetscLogPrintInfo;
185716d9e3a6SLisandro Dalcin 
18589566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("pilut", jac->hypre_type, &flag));
185916d9e3a6SLisandro Dalcin   if (flag) {
18609566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1861792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParCSRPilutCreate, jac->comm_hypre, &jac->hsolver);
186216d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
186316d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_Pilut;
186416d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParCSRPilutDestroy;
186516d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParCSRPilutSetup;
186616d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParCSRPilutSolve;
186716d9e3a6SLisandro Dalcin     jac->factorrowsize      = PETSC_DEFAULT;
18683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
186916d9e3a6SLisandro Dalcin   }
18709566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("euclid", jac->hypre_type, &flag));
1871db966c6cSHong Zhang   if (flag) {
18724e3c431bSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
18734e3c431bSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Hypre Euclid does not support 64 bit indices");
18748bf83915SBarry Smith #endif
18759566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1876792fecdfSBarry Smith     PetscCallExternal(HYPRE_EuclidCreate, jac->comm_hypre, &jac->hsolver);
1877db966c6cSHong Zhang     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1878db966c6cSHong Zhang     pc->ops->view           = PCView_HYPRE_Euclid;
1879db966c6cSHong Zhang     jac->destroy            = HYPRE_EuclidDestroy;
1880db966c6cSHong Zhang     jac->setup              = HYPRE_EuclidSetup;
1881db966c6cSHong Zhang     jac->solve              = HYPRE_EuclidSolve;
1882db966c6cSHong Zhang     jac->factorrowsize      = PETSC_DEFAULT;
1883db966c6cSHong Zhang     jac->eu_level           = PETSC_DEFAULT; /* default */
18843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1885db966c6cSHong Zhang   }
18869566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("parasails", jac->hypre_type, &flag));
188716d9e3a6SLisandro Dalcin   if (flag) {
18889566063dSJacob Faibussowitsch     PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &jac->comm_hypre));
1889792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsCreate, jac->comm_hypre, &jac->hsolver);
189016d9e3a6SLisandro Dalcin     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
189116d9e3a6SLisandro Dalcin     pc->ops->view           = PCView_HYPRE_ParaSails;
189216d9e3a6SLisandro Dalcin     jac->destroy            = HYPRE_ParaSailsDestroy;
189316d9e3a6SLisandro Dalcin     jac->setup              = HYPRE_ParaSailsSetup;
189416d9e3a6SLisandro Dalcin     jac->solve              = HYPRE_ParaSailsSolve;
189516d9e3a6SLisandro Dalcin     /* initialize */
189616d9e3a6SLisandro Dalcin     jac->nlevels   = 1;
18978966356dSPierre Jolivet     jac->threshold = .1;
189816d9e3a6SLisandro Dalcin     jac->filter    = .1;
189916d9e3a6SLisandro Dalcin     jac->loadbal   = 0;
19002fa5cd67SKarl Rupp     if (PetscLogPrintInfo) jac->logging = (int)PETSC_TRUE;
19012fa5cd67SKarl Rupp     else jac->logging = (int)PETSC_FALSE;
19022fa5cd67SKarl Rupp 
190316d9e3a6SLisandro Dalcin     jac->ruse = (int)PETSC_FALSE;
190416d9e3a6SLisandro Dalcin     jac->symt = 0;
1905792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetParams, jac->hsolver, jac->threshold, jac->nlevels);
1906792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetFilter, jac->hsolver, jac->filter);
1907792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLoadbal, jac->hsolver, jac->loadbal);
1908792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetLogging, jac->hsolver, jac->logging);
1909792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetReuse, jac->hsolver, jac->ruse);
1910792fecdfSBarry Smith     PetscCallExternal(HYPRE_ParaSailsSetSym, jac->hsolver, jac->symt);
19113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
191216d9e3a6SLisandro Dalcin   }
19139566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("boomeramg", jac->hypre_type, &flag));
191416d9e3a6SLisandro Dalcin   if (flag) {
1915792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGCreate, &jac->hsolver);
191616d9e3a6SLisandro Dalcin     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
191716d9e3a6SLisandro Dalcin     pc->ops->view            = PCView_HYPRE_BoomerAMG;
191816d9e3a6SLisandro Dalcin     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
191916d9e3a6SLisandro Dalcin     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
1920*85245615SPierre Jolivet     pc->ops->matapply        = PCMatApply_HYPRE_BoomerAMG;
19219566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetInterpolations_C", PCGetInterpolations_BoomerAMG));
19229566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGetCoarseOperators_C", PCGetCoarseOperators_BoomerAMG));
192316d9e3a6SLisandro Dalcin     jac->destroy         = HYPRE_BoomerAMGDestroy;
192416d9e3a6SLisandro Dalcin     jac->setup           = HYPRE_BoomerAMGSetup;
192516d9e3a6SLisandro Dalcin     jac->solve           = HYPRE_BoomerAMGSolve;
192616d9e3a6SLisandro Dalcin     jac->applyrichardson = PETSC_FALSE;
192716d9e3a6SLisandro Dalcin     /* these defaults match the hypre defaults */
192816d9e3a6SLisandro Dalcin     jac->cycletype       = 1;
192916d9e3a6SLisandro Dalcin     jac->maxlevels       = 25;
193016d9e3a6SLisandro Dalcin     jac->maxiter         = 1;
19318f87f92bSBarry Smith     jac->tol             = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
193216d9e3a6SLisandro Dalcin     jac->truncfactor     = 0.0;
193316d9e3a6SLisandro Dalcin     jac->strongthreshold = .25;
193416d9e3a6SLisandro Dalcin     jac->maxrowsum       = .9;
193516d9e3a6SLisandro Dalcin     jac->coarsentype     = 6;
193616d9e3a6SLisandro Dalcin     jac->measuretype     = 0;
19370f1074feSSatish Balay     jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
19386a251517SEike Mueller     jac->smoothtype                                              = -1; /* Not set by default */
1939b9eb5777SEike Mueller     jac->smoothnumlevels                                         = 25;
19401810e44eSEike Mueller     jac->eu_level                                                = 0;
19411810e44eSEike Mueller     jac->eu_droptolerance                                        = 0;
19421810e44eSEike Mueller     jac->eu_bj                                                   = 0;
1943589dcaf0SStefano Zampini     jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
19440f1074feSSatish Balay     jac->relaxtype[2]                     = 9; /*G.E. */
194516d9e3a6SLisandro Dalcin     jac->relaxweight                      = 1.0;
194616d9e3a6SLisandro Dalcin     jac->outerrelaxweight                 = 1.0;
194716d9e3a6SLisandro Dalcin     jac->relaxorder                       = 1;
19480f1074feSSatish Balay     jac->interptype                       = 0;
1949589dcaf0SStefano Zampini     jac->Rtype                            = 0;
1950589dcaf0SStefano Zampini     jac->Rstrongthreshold                 = 0.25;
1951589dcaf0SStefano Zampini     jac->Rfilterthreshold                 = 0.0;
1952589dcaf0SStefano Zampini     jac->Adroptype                        = -1;
1953589dcaf0SStefano Zampini     jac->Adroptol                         = 0.0;
19540f1074feSSatish Balay     jac->agg_nl                           = 0;
19556ea7df73SStefano Zampini     jac->agg_interptype                   = 4;
19560f1074feSSatish Balay     jac->pmax                             = 0;
19570f1074feSSatish Balay     jac->truncfactor                      = 0.0;
19580f1074feSSatish Balay     jac->agg_num_paths                    = 1;
1959589dcaf0SStefano Zampini     jac->maxc                             = 9;
1960589dcaf0SStefano Zampini     jac->minc                             = 1;
196122e51d31SStefano Zampini     jac->nodal_coarsening                 = 0;
196222e51d31SStefano Zampini     jac->nodal_coarsening_diag            = 0;
196322e51d31SStefano Zampini     jac->vec_interp_variant               = 0;
196422e51d31SStefano Zampini     jac->vec_interp_qmax                  = 0;
196522e51d31SStefano Zampini     jac->vec_interp_smooth                = PETSC_FALSE;
196622e51d31SStefano Zampini     jac->interp_refine                    = 0;
19678f87f92bSBarry Smith     jac->nodal_relax                      = PETSC_FALSE;
19688f87f92bSBarry Smith     jac->nodal_relax_levels               = 1;
19696ea7df73SStefano Zampini     jac->rap2                             = 0;
19706ea7df73SStefano Zampini 
19716ea7df73SStefano Zampini     /* GPU defaults
19726ea7df73SStefano Zampini          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
19736ea7df73SStefano Zampini          and /src/parcsr_ls/par_amg.c */
19746ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
19756ea7df73SStefano Zampini     jac->keeptranspose  = PETSC_TRUE;
19766ea7df73SStefano Zampini     jac->mod_rap2       = 1;
19776ea7df73SStefano Zampini     jac->coarsentype    = 8;
19786ea7df73SStefano Zampini     jac->relaxorder     = 0;
19796ea7df73SStefano Zampini     jac->interptype     = 6;
19806ea7df73SStefano Zampini     jac->relaxtype[0]   = 18;
19816ea7df73SStefano Zampini     jac->relaxtype[1]   = 18;
19826ea7df73SStefano Zampini     jac->agg_interptype = 7;
19836ea7df73SStefano Zampini #else
19846ea7df73SStefano Zampini     jac->keeptranspose = PETSC_FALSE;
19856ea7df73SStefano Zampini     jac->mod_rap2      = 0;
19866ea7df73SStefano Zampini #endif
1987792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCycleType, jac->hsolver, jac->cycletype);
1988792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxLevels, jac->hsolver, jac->maxlevels);
1989792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxIter, jac->hsolver, jac->maxiter);
1990792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTol, jac->hsolver, jac->tol);
1991792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetTruncFactor, jac->hsolver, jac->truncfactor);
1992792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThreshold, jac->hsolver, jac->strongthreshold);
1993792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxRowSum, jac->hsolver, jac->maxrowsum);
1994792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetCoarsenType, jac->hsolver, jac->coarsentype);
1995792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMeasureType, jac->hsolver, jac->measuretype);
1996792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxOrder, jac->hsolver, jac->relaxorder);
1997792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetInterpType, jac->hsolver, jac->interptype);
1998792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggNumLevels, jac->hsolver, jac->agg_nl);
1999792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetAggInterpType, jac->hsolver, jac->agg_interptype);
2000792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetPMaxElmts, jac->hsolver, jac->pmax);
2001792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumPaths, jac->hsolver, jac->agg_num_paths);
2002792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRelaxType, jac->hsolver, jac->relaxtype[0]);  /* defaults coarse to 9 */
2003792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetNumSweeps, jac->hsolver, jac->gridsweeps[0]); /* defaults coarse to 1 */
2004792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMaxCoarseSize, jac->hsolver, jac->maxc);
2005792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetMinCoarseSize, jac->hsolver, jac->minc);
20066ea7df73SStefano Zampini     /* GPU */
20076ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2008792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetKeepTranspose, jac->hsolver, jac->keeptranspose ? 1 : 0);
2009792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRAP2, jac->hsolver, jac->rap2);
2010792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetModuleRAP2, jac->hsolver, jac->mod_rap2);
20116ea7df73SStefano Zampini #endif
20126ea7df73SStefano Zampini 
2013589dcaf0SStefano Zampini     /* AIR */
20146ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 18, 0)
2015792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetRestriction, jac->hsolver, jac->Rtype);
2016792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetStrongThresholdR, jac->hsolver, jac->Rstrongthreshold);
2017792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetFilterThresholdR, jac->hsolver, jac->Rfilterthreshold);
2018792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropTol, jac->hsolver, jac->Adroptol);
2019792fecdfSBarry Smith     PetscCallExternal(HYPRE_BoomerAMGSetADropType, jac->hsolver, jac->Adroptype);
20206ea7df73SStefano Zampini #endif
20213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
202216d9e3a6SLisandro Dalcin   }
20239566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ams", jac->hypre_type, &flag));
20244cb006feSStefano Zampini   if (flag) {
20253ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_AMSCreate, &jac->hsolver);
20264cb006feSStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_AMS;
20274cb006feSStefano Zampini     pc->ops->view           = PCView_HYPRE_AMS;
20284cb006feSStefano Zampini     jac->destroy            = HYPRE_AMSDestroy;
20294cb006feSStefano Zampini     jac->setup              = HYPRE_AMSSetup;
20304cb006feSStefano Zampini     jac->solve              = HYPRE_AMSSolve;
20314cb006feSStefano Zampini     jac->coords[0]          = NULL;
20324cb006feSStefano Zampini     jac->coords[1]          = NULL;
20334cb006feSStefano Zampini     jac->coords[2]          = NULL;
2034be14dc20SKerry Key     jac->interior           = NULL;
20354cb006feSStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
2036863406b8SStefano Zampini     jac->as_print       = 0;
2037863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2038863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
20394cb006feSStefano Zampini     jac->ams_cycle_type = 13;
20404cb006feSStefano Zampini     /* Smoothing options */
2041863406b8SStefano Zampini     jac->as_relax_type   = 2;
2042863406b8SStefano Zampini     jac->as_relax_times  = 1;
2043863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2044863406b8SStefano Zampini     jac->as_omega        = 1.0;
20454cb006feSStefano Zampini     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2046863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2047863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
20480bdd8552SBarry Smith     jac->as_amg_alpha_opts[2] = 6;
2049863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2050863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2051863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
20524cb006feSStefano Zampini     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2053863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2054863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
20550bdd8552SBarry Smith     jac->as_amg_beta_opts[2] = 6;
2056863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2057863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2058863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2059792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetPrintLevel, jac->hsolver, jac->as_print);
2060792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetMaxIter, jac->hsolver, jac->as_max_iter);
2061792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2062792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetTol, jac->hsolver, jac->as_tol);
20639371c9d4SSatish Balay     PetscCallExternal(HYPRE_AMSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2064792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetAlphaAMGOptions, jac->hsolver, jac->as_amg_alpha_opts[0], /* AMG coarsen type */
2065863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                            /* AMG agg_levels */
2066863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                            /* AMG relax_type */
20679371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],                   /* AMG interp_type */
2068a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                           /* AMG Pmax */
2069792fecdfSBarry Smith     PetscCallExternal(HYPRE_AMSSetBetaAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0],   /* AMG coarsen type */
2070863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                             /* AMG agg_levels */
2071863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                             /* AMG relax_type */
20729371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],                     /* AMG interp_type */
2073a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                            /* AMG Pmax */
207423df4f25SStefano Zampini     /* Zero conductivity */
207523df4f25SStefano Zampini     jac->ams_beta_is_zero      = PETSC_FALSE;
207623df4f25SStefano Zampini     jac->ams_beta_is_zero_part = PETSC_FALSE;
20773ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
20784cb006feSStefano Zampini   }
20799566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp("ads", jac->hypre_type, &flag));
2080863406b8SStefano Zampini   if (flag) {
20813ba16761SJacob Faibussowitsch     PetscCallExternal(HYPRE_ADSCreate, &jac->hsolver);
2082863406b8SStefano Zampini     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ADS;
2083863406b8SStefano Zampini     pc->ops->view           = PCView_HYPRE_ADS;
2084863406b8SStefano Zampini     jac->destroy            = HYPRE_ADSDestroy;
2085863406b8SStefano Zampini     jac->setup              = HYPRE_ADSSetup;
2086863406b8SStefano Zampini     jac->solve              = HYPRE_ADSSolve;
2087863406b8SStefano Zampini     jac->coords[0]          = NULL;
2088863406b8SStefano Zampini     jac->coords[1]          = NULL;
2089863406b8SStefano Zampini     jac->coords[2]          = NULL;
2090863406b8SStefano Zampini     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2091863406b8SStefano Zampini     jac->as_print       = 0;
2092863406b8SStefano Zampini     jac->as_max_iter    = 1;  /* used as a preconditioner */
2093863406b8SStefano Zampini     jac->as_tol         = 0.; /* used as a preconditioner */
2094863406b8SStefano Zampini     jac->ads_cycle_type = 13;
2095863406b8SStefano Zampini     /* Smoothing options */
2096863406b8SStefano Zampini     jac->as_relax_type   = 2;
2097863406b8SStefano Zampini     jac->as_relax_times  = 1;
2098863406b8SStefano Zampini     jac->as_relax_weight = 1.0;
2099863406b8SStefano Zampini     jac->as_omega        = 1.0;
2100863406b8SStefano Zampini     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2101863406b8SStefano Zampini     jac->ams_cycle_type       = 14;
2102863406b8SStefano Zampini     jac->as_amg_alpha_opts[0] = 10;
2103863406b8SStefano Zampini     jac->as_amg_alpha_opts[1] = 1;
2104863406b8SStefano Zampini     jac->as_amg_alpha_opts[2] = 6;
2105863406b8SStefano Zampini     jac->as_amg_alpha_opts[3] = 6;
2106863406b8SStefano Zampini     jac->as_amg_alpha_opts[4] = 4;
2107863406b8SStefano Zampini     jac->as_amg_alpha_theta   = 0.25;
2108863406b8SStefano Zampini     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2109863406b8SStefano Zampini     jac->as_amg_beta_opts[0] = 10;
2110863406b8SStefano Zampini     jac->as_amg_beta_opts[1] = 1;
2111863406b8SStefano Zampini     jac->as_amg_beta_opts[2] = 6;
2112863406b8SStefano Zampini     jac->as_amg_beta_opts[3] = 6;
2113863406b8SStefano Zampini     jac->as_amg_beta_opts[4] = 4;
2114863406b8SStefano Zampini     jac->as_amg_beta_theta   = 0.25;
2115792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetPrintLevel, jac->hsolver, jac->as_print);
2116792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetMaxIter, jac->hsolver, jac->as_max_iter);
2117792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetCycleType, jac->hsolver, jac->ams_cycle_type);
2118792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetTol, jac->hsolver, jac->as_tol);
21199371c9d4SSatish Balay     PetscCallExternal(HYPRE_ADSSetSmoothingOptions, jac->hsolver, jac->as_relax_type, jac->as_relax_times, jac->as_relax_weight, jac->as_omega);
2120792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMSOptions, jac->hsolver, jac->ams_cycle_type,      /* AMG coarsen type */
2121863406b8SStefano Zampini                       jac->as_amg_alpha_opts[0],                                      /* AMG coarsen type */
2122863406b8SStefano Zampini                       jac->as_amg_alpha_opts[1],                                      /* AMG agg_levels */
2123863406b8SStefano Zampini                       jac->as_amg_alpha_opts[2],                                      /* AMG relax_type */
21249371c9d4SSatish Balay                       jac->as_amg_alpha_theta, jac->as_amg_alpha_opts[3],             /* AMG interp_type */
2125a74df02fSJacob Faibussowitsch                       jac->as_amg_alpha_opts[4]);                                     /* AMG Pmax */
2126792fecdfSBarry Smith     PetscCallExternal(HYPRE_ADSSetAMGOptions, jac->hsolver, jac->as_amg_beta_opts[0], /* AMG coarsen type */
2127863406b8SStefano Zampini                       jac->as_amg_beta_opts[1],                                       /* AMG agg_levels */
2128863406b8SStefano Zampini                       jac->as_amg_beta_opts[2],                                       /* AMG relax_type */
21299371c9d4SSatish Balay                       jac->as_amg_beta_theta, jac->as_amg_beta_opts[3],               /* AMG interp_type */
2130a74df02fSJacob Faibussowitsch                       jac->as_amg_beta_opts[4]);                                      /* AMG Pmax */
21313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2132863406b8SStefano Zampini   }
21339566063dSJacob Faibussowitsch   PetscCall(PetscFree(jac->hypre_type));
21342fa5cd67SKarl Rupp 
21350298fd71SBarry Smith   jac->hypre_type = NULL;
213698921bdaSJacob Faibussowitsch   SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams", name);
213716d9e3a6SLisandro Dalcin }
213816d9e3a6SLisandro Dalcin 
213916d9e3a6SLisandro Dalcin /*
214016d9e3a6SLisandro Dalcin     It only gets here if the HYPRE type has not been set before the call to
214116d9e3a6SLisandro Dalcin    ...SetFromOptions() which actually is most of the time
214216d9e3a6SLisandro Dalcin */
2143d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_HYPRE(PC pc, PetscOptionItems *PetscOptionsObject)
2144d71ae5a4SJacob Faibussowitsch {
21454ddd07fcSJed Brown   PetscInt    indx;
2146db966c6cSHong Zhang   const char *type[] = {"euclid", "pilut", "parasails", "boomeramg", "ams", "ads"};
2147ace3abfcSBarry Smith   PetscBool   flg;
214816d9e3a6SLisandro Dalcin 
214916d9e3a6SLisandro Dalcin   PetscFunctionBegin;
2150d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HYPRE preconditioner options");
2151dd39110bSPierre Jolivet   PetscCall(PetscOptionsEList("-pc_hypre_type", "HYPRE preconditioner type", "PCHYPRESetType", type, PETSC_STATIC_ARRAY_LENGTH(type), "boomeramg", &indx, &flg));
215216d9e3a6SLisandro Dalcin   if (flg) {
21539566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, type[indx]));
215402a17cd4SBarry Smith   } else {
21559566063dSJacob Faibussowitsch     PetscCall(PCHYPRESetType_HYPRE(pc, "boomeramg"));
215616d9e3a6SLisandro Dalcin   }
2157dbbe0bcdSBarry Smith   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
2158d0609cedSBarry Smith   PetscOptionsHeadEnd();
21593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216016d9e3a6SLisandro Dalcin }
216116d9e3a6SLisandro Dalcin 
216216d9e3a6SLisandro Dalcin /*@C
216316d9e3a6SLisandro Dalcin      PCHYPRESetType - Sets which hypre preconditioner you wish to use
216416d9e3a6SLisandro Dalcin 
216516d9e3a6SLisandro Dalcin    Input Parameters:
216616d9e3a6SLisandro Dalcin +     pc - the preconditioner context
2167db966c6cSHong Zhang -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
216816d9e3a6SLisandro Dalcin 
2169f1580f4eSBarry Smith    Options Database Key:
2170db966c6cSHong Zhang    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
217116d9e3a6SLisandro Dalcin 
217216d9e3a6SLisandro Dalcin    Level: intermediate
217316d9e3a6SLisandro Dalcin 
2174f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRE`
217516d9e3a6SLisandro Dalcin @*/
2176d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPRESetType(PC pc, const char name[])
2177d71ae5a4SJacob Faibussowitsch {
217816d9e3a6SLisandro Dalcin   PetscFunctionBegin;
21790700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
218016d9e3a6SLisandro Dalcin   PetscValidCharPointer(name, 2);
2181cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPRESetType_C", (PC, const char[]), (pc, name));
21823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218316d9e3a6SLisandro Dalcin }
218416d9e3a6SLisandro Dalcin 
218516d9e3a6SLisandro Dalcin /*@C
218616d9e3a6SLisandro Dalcin      PCHYPREGetType - Gets which hypre preconditioner you are using
218716d9e3a6SLisandro Dalcin 
218816d9e3a6SLisandro Dalcin    Input Parameter:
218916d9e3a6SLisandro Dalcin .     pc - the preconditioner context
219016d9e3a6SLisandro Dalcin 
219116d9e3a6SLisandro Dalcin    Output Parameter:
2192db966c6cSHong Zhang .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
219316d9e3a6SLisandro Dalcin 
219416d9e3a6SLisandro Dalcin    Level: intermediate
219516d9e3a6SLisandro Dalcin 
2196f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCHYPRESetType()`, `PCType`, `PC`, `PCHYPRE`
219716d9e3a6SLisandro Dalcin @*/
2198d71ae5a4SJacob Faibussowitsch PetscErrorCode PCHYPREGetType(PC pc, const char *name[])
2199d71ae5a4SJacob Faibussowitsch {
220016d9e3a6SLisandro Dalcin   PetscFunctionBegin;
22010700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
220216d9e3a6SLisandro Dalcin   PetscValidPointer(name, 2);
2203cac4c232SBarry Smith   PetscTryMethod(pc, "PCHYPREGetType_C", (PC, const char *[]), (pc, name));
22043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220516d9e3a6SLisandro Dalcin }
220616d9e3a6SLisandro Dalcin 
2207db6f9c32SMark Adams /*@C
2208f1580f4eSBarry Smith    PCMGGalerkinSetMatProductAlgorithm - Set type of SpGEMM for hypre to use on GPUs
2209db6f9c32SMark Adams 
2210c3339decSBarry Smith    Logically Collective
2211db6f9c32SMark Adams 
2212db6f9c32SMark Adams    Input Parameters:
2213db6f9c32SMark Adams +  pc - the hypre context
2214db6f9c32SMark Adams -  type - one of 'cusparse', 'hypre'
2215db6f9c32SMark Adams 
2216db6f9c32SMark Adams    Options Database Key:
221767b8a455SSatish Balay .  -pc_mg_galerkin_mat_product_algorithm <cusparse,hypre> - Type of SpGEMM to use in hypre
2218db6f9c32SMark Adams 
2219db6f9c32SMark Adams    Level: intermediate
2220db6f9c32SMark Adams 
2221f1580f4eSBarry Smith    Developer Note:
2222f1580f4eSBarry Smith    How the name starts with `PCMG`, should it not be `PCHYPREBoomerAMG`?
2223db6f9c32SMark Adams 
2224f1580f4eSBarry Smith .seealso: `PCHYPRE`, `PCMGGalerkinGetMatProductAlgorithm()`
2225db6f9c32SMark Adams @*/
2226d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinSetMatProductAlgorithm(PC pc, const char name[])
2227d71ae5a4SJacob Faibussowitsch {
2228db6f9c32SMark Adams   PetscFunctionBegin;
2229db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2230cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinSetMatProductAlgorithm_C", (PC, const char[]), (pc, name));
22313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2232db6f9c32SMark Adams }
2233db6f9c32SMark Adams 
2234db6f9c32SMark Adams /*@C
2235f1580f4eSBarry Smith    PCMGGalerkinGetMatProductAlgorithm - Get type of SpGEMM for hypre to use on GPUs
2236db6f9c32SMark Adams 
2237db6f9c32SMark Adams    Not Collective
2238db6f9c32SMark Adams 
2239db6f9c32SMark Adams    Input Parameter:
2240db6f9c32SMark Adams .  pc - the multigrid context
2241db6f9c32SMark Adams 
2242db6f9c32SMark Adams    Output Parameter:
2243db6f9c32SMark Adams .  name - one of 'cusparse', 'hypre'
2244db6f9c32SMark Adams 
2245db6f9c32SMark Adams    Level: intermediate
2246db6f9c32SMark Adams 
2247f1580f4eSBarry Smith .seealso: `PCHYPRE`, ``PCMGGalerkinSetMatProductAlgorithm()`
2248db6f9c32SMark Adams @*/
2249d71ae5a4SJacob Faibussowitsch PetscErrorCode PCMGGalerkinGetMatProductAlgorithm(PC pc, const char *name[])
2250d71ae5a4SJacob Faibussowitsch {
2251db6f9c32SMark Adams   PetscFunctionBegin;
2252db6f9c32SMark Adams   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2253cac4c232SBarry Smith   PetscTryMethod(pc, "PCMGGalerkinGetMatProductAlgorithm_C", (PC, const char *[]), (pc, name));
22543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2255db6f9c32SMark Adams }
2256db6f9c32SMark Adams 
225716d9e3a6SLisandro Dalcin /*MC
2258f1580f4eSBarry Smith      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre as PETSc `PC`
225916d9e3a6SLisandro Dalcin 
226016d9e3a6SLisandro Dalcin    Options Database Keys:
2261db966c6cSHong Zhang +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2262f1580f4eSBarry Smith .   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see `HYPRE_BOOMERAMGSetNodal()`)
2263f1580f4eSBarry Smith .   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see `HYPRE_BoomerAMGSetInterpVecVariant()`)
2264ead8c081SBarry Smith -   Many others, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX preconditioner
226516d9e3a6SLisandro Dalcin 
226616d9e3a6SLisandro Dalcin    Level: intermediate
226716d9e3a6SLisandro Dalcin 
226895452b02SPatrick Sanan    Notes:
2269f1580f4eSBarry Smith     Apart from pc_hypre_type (for which there is `PCHYPRESetType()`),
227016d9e3a6SLisandro Dalcin           the many hypre options can ONLY be set via the options database (e.g. the command line
227149567fc5SPierre Jolivet           or with `PetscOptionsSetValue()`, there are no functions to set them)
227216d9e3a6SLisandro Dalcin 
2273c231f9e3SBarryFSmith           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
22740f1074feSSatish Balay           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
22750f1074feSSatish Balay           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2276c231f9e3SBarryFSmith           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
22778f87f92bSBarry Smith           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
22780f1074feSSatish Balay           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
22790f1074feSSatish Balay           then AT MOST twenty V-cycles of boomeramg will be called.
228016d9e3a6SLisandro Dalcin 
22810f1074feSSatish Balay            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
22820f1074feSSatish Balay            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
22830f1074feSSatish Balay            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
228416d9e3a6SLisandro Dalcin           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
228516d9e3a6SLisandro Dalcin           and use -ksp_max_it to control the number of V-cycles.
228616d9e3a6SLisandro Dalcin           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
228716d9e3a6SLisandro Dalcin 
2288f1580f4eSBarry Smith           `MatSetNearNullSpace()` - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
228949567fc5SPierre Jolivet           the following two options: ``-pc_hypre_boomeramg_nodal_coarsen <n> -pc_hypre_boomeramg_vec_interp_variant <v>``
22900b1a5bd9SEric Chamberland 
2291f1580f4eSBarry Smith           See `PCPFMG`, `PCSMG`, and `PCSYSPFMG` for access to hypre's other (nonalgebraic) multigrid solvers
2292f1580f4eSBarry Smith 
2293f1580f4eSBarry Smith           For `PCHYPRE` type of ams or ads auxiliary data must be provided to the preconditioner with `PCHYPRESetDiscreteGradient()`,
2294f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
229549567fc5SPierre Jolivet           `PCHYPREAMSSetInteriorNodes()`
2296f1580f4eSBarry Smith 
2297f1580f4eSBarry Smith    PETSc provides its own geometric and algebraic multigrid solvers `PCMG` and `PCGAMG`, also see `PCHMG` which is useful for certain multicomponent problems
22989e5bc791SBarry Smith 
2299ead8c081SBarry Smith    GPU Notes:
2300ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize NVIDIA GPUs run ./configure --download-hypre --with-cuda
2301f1580f4eSBarry Smith      Then pass `VECCUDA` vectors and `MATAIJCUSPARSE` matrices to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2302ead8c081SBarry Smith 
2303ead8c081SBarry Smith      To configure hypre BoomerAMG so that it can utilize AMD GPUs run ./configure --download-hypre --with-hip
2304f1580f4eSBarry Smith      Then pass `VECHIP` vectors to the solvers and PETSc will automatically utilize hypre's GPU solvers.
2305ead8c081SBarry Smith 
2306f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCHYPRESetType()`, `PCPFMG`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`, `PCHYPRESetDiscreteGradient()`,
2307f1580f4eSBarry Smith           `PCHYPRESetDiscreteCurl()`, `PCHYPRESetInterpolations()`, `PCHYPRESetAlphaPoissonMatrix()`, `PCHYPRESetBetaPoissonMatrix()`, `PCHYPRESetEdgeConstantVectors()`,
2308f1580f4eSBarry Smith           PCHYPREAMSSetInteriorNodes()
230916d9e3a6SLisandro Dalcin M*/
231016d9e3a6SLisandro Dalcin 
2311d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2312d71ae5a4SJacob Faibussowitsch {
231316d9e3a6SLisandro Dalcin   PC_HYPRE *jac;
231416d9e3a6SLisandro Dalcin 
231516d9e3a6SLisandro Dalcin   PetscFunctionBegin;
23164dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
23172fa5cd67SKarl Rupp 
231816d9e3a6SLisandro Dalcin   pc->data                = jac;
23198695de01SBarry Smith   pc->ops->reset          = PCReset_HYPRE;
232016d9e3a6SLisandro Dalcin   pc->ops->destroy        = PCDestroy_HYPRE;
232116d9e3a6SLisandro Dalcin   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
232216d9e3a6SLisandro Dalcin   pc->ops->setup          = PCSetUp_HYPRE;
232316d9e3a6SLisandro Dalcin   pc->ops->apply          = PCApply_HYPRE;
232416d9e3a6SLisandro Dalcin   jac->comm_hypre         = MPI_COMM_NULL;
23259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetType_C", PCHYPRESetType_HYPRE));
23269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREGetType_C", PCHYPREGetType_HYPRE));
23279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_HYPRE));
23289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteGradient_C", PCHYPRESetDiscreteGradient_HYPRE));
23299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetDiscreteCurl_C", PCHYPRESetDiscreteCurl_HYPRE));
23309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetInterpolations_C", PCHYPRESetInterpolations_HYPRE));
23319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetEdgeConstantVectors_C", PCHYPRESetEdgeConstantVectors_HYPRE));
2332be14dc20SKerry Key   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPREAMSSetInteriorNodes_C", PCHYPREAMSSetInteriorNodes_HYPRE));
23339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCHYPRESetPoissonMatrix_C", PCHYPRESetPoissonMatrix_HYPRE));
23349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinSetMatProductAlgorithm_C", PCMGGalerkinSetMatProductAlgorithm_HYPRE_BoomerAMG));
23359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCMGGalerkinGetMatProductAlgorithm_C", PCMGGalerkinGetMatProductAlgorithm_HYPRE_BoomerAMG));
23366ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23376ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
23389566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
23396ea7df73SStefano Zampini   #endif
23406ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
23419566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
23426ea7df73SStefano Zampini   #endif
23436ea7df73SStefano Zampini #endif
23443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
234516d9e3a6SLisandro Dalcin }
2346ebc551c0SBarry Smith 
2347ebc551c0SBarry Smith typedef struct {
234868326731SBarry Smith   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2349f91d8e95SBarry Smith   HYPRE_StructSolver hsolver;
23509e5bc791SBarry Smith 
23519e5bc791SBarry Smith   /* keep copy of PFMG options used so may view them */
23524ddd07fcSJed Brown   PetscInt  its;
23539e5bc791SBarry Smith   double    tol;
23544ddd07fcSJed Brown   PetscInt  relax_type;
23554ddd07fcSJed Brown   PetscInt  rap_type;
23564ddd07fcSJed Brown   PetscInt  num_pre_relax, num_post_relax;
23574ddd07fcSJed Brown   PetscInt  max_levels;
23580be8cd64Sftrigaux   PetscInt  skip_relax;
23590be8cd64Sftrigaux   PetscBool print_statistics;
2360ebc551c0SBarry Smith } PC_PFMG;
2361ebc551c0SBarry Smith 
2362d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_PFMG(PC pc)
2363d71ae5a4SJacob Faibussowitsch {
2364f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2365ebc551c0SBarry Smith 
2366ebc551c0SBarry Smith   PetscFunctionBegin;
2367792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
23689566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
23699566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
23703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2371ebc551c0SBarry Smith }
2372ebc551c0SBarry Smith 
23739e5bc791SBarry Smith static const char *PFMGRelaxType[] = {"Jacobi", "Weighted-Jacobi", "symmetric-Red/Black-Gauss-Seidel", "Red/Black-Gauss-Seidel"};
23749e5bc791SBarry Smith static const char *PFMGRAPType[]   = {"Galerkin", "non-Galerkin"};
23759e5bc791SBarry Smith 
2376d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_PFMG(PC pc, PetscViewer viewer)
2377d71ae5a4SJacob Faibussowitsch {
2378ace3abfcSBarry Smith   PetscBool iascii;
2379f91d8e95SBarry Smith   PC_PFMG  *ex = (PC_PFMG *)pc->data;
2380ebc551c0SBarry Smith 
2381ebc551c0SBarry Smith   PetscFunctionBegin;
23829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
23839e5bc791SBarry Smith   if (iascii) {
23849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE PFMG preconditioning\n"));
238563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
23869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
23879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    relax type %s\n", PFMGRelaxType[ex->relax_type]));
23889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    RAP type %s\n", PFMGRAPType[ex->rap_type]));
238963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
239063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    max levels %" PetscInt_FMT "\n", ex->max_levels));
23910be8cd64Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    skip relax %" PetscInt_FMT "\n", ex->skip_relax));
23929e5bc791SBarry Smith   }
23933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2394ebc551c0SBarry Smith }
2395ebc551c0SBarry Smith 
2396d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_PFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2397d71ae5a4SJacob Faibussowitsch {
2398f91d8e95SBarry Smith   PC_PFMG *ex = (PC_PFMG *)pc->data;
2399ebc551c0SBarry Smith 
2400ebc551c0SBarry Smith   PetscFunctionBegin;
2401d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PFMG options");
24020be8cd64Sftrigaux   PetscCall(PetscOptionsBool("-pc_pfmg_print_statistics", "Print statistics", "HYPRE_StructPFMGSetPrintLevel", ex->print_statistics, &ex->print_statistics, NULL));
24039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_its", "Number of iterations of PFMG to use as preconditioner", "HYPRE_StructPFMGSetMaxIter", ex->its, &ex->its, NULL));
2404792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
24059566063dSJacob 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));
2406792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
24079566063dSJacob 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));
2408792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
24099e5bc791SBarry Smith 
24109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_pfmg_max_levels", "Max Levels for MG hierarchy", "HYPRE_StructPFMGSetMaxLevels", ex->max_levels, &ex->max_levels, NULL));
2411792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
24123b46a515SGlenn Hammond 
24139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_pfmg_tol", "Tolerance of PFMG", "HYPRE_StructPFMGSetTol", ex->tol, &ex->tol, NULL));
2414792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
2415dd39110bSPierre 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));
2416792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
2417dd39110bSPierre 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));
2418792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
24190be8cd64Sftrigaux   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));
24200be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetSkipRelax, ex->hsolver, ex->skip_relax);
2421d0609cedSBarry Smith   PetscOptionsHeadEnd();
24223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2423ebc551c0SBarry Smith }
2424ebc551c0SBarry Smith 
2425d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_PFMG(PC pc, Vec x, Vec y)
2426d71ae5a4SJacob Faibussowitsch {
2427f91d8e95SBarry Smith   PC_PFMG           *ex = (PC_PFMG *)pc->data;
2428d9ca1df4SBarry Smith   PetscScalar       *yy;
2429d9ca1df4SBarry Smith   const PetscScalar *xx;
24304ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
24312cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
243268326731SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2433f91d8e95SBarry Smith 
2434f91d8e95SBarry Smith   PetscFunctionBegin;
24359566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
24369566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
24372cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2438f91d8e95SBarry Smith   iupper[0] += ilower[0] - 1;
2439f91d8e95SBarry Smith   iupper[1] += ilower[1] - 1;
2440f91d8e95SBarry Smith   iupper[2] += ilower[2] - 1;
24412cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
24422cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
24432cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
24442cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
24452cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
24462cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2447f91d8e95SBarry Smith 
2448f91d8e95SBarry Smith   /* copy x values over to hypre */
2449792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
24509566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
2451792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
24529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
2453792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
2454792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2455f91d8e95SBarry Smith 
2456f91d8e95SBarry Smith   /* copy solution values back to PETSc */
24579566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
2458792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
24599566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
24603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2461f91d8e95SBarry Smith }
2462f91d8e95SBarry Smith 
2463d71ae5a4SJacob 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)
2464d71ae5a4SJacob Faibussowitsch {
24659e5bc791SBarry Smith   PC_PFMG  *jac = (PC_PFMG *)pc->data;
24662cf14000SStefano Zampini   HYPRE_Int oits;
24679e5bc791SBarry Smith 
24689e5bc791SBarry Smith   PetscFunctionBegin;
24699566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2470792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, its * jac->its);
2471792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, rtol);
24729e5bc791SBarry Smith 
24739566063dSJacob Faibussowitsch   PetscCall(PCApply_PFMG(pc, b, y));
2474792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGGetNumIterations, jac->hsolver, &oits);
24759e5bc791SBarry Smith   *outits = oits;
24769e5bc791SBarry Smith   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
24779e5bc791SBarry Smith   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2478792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetTol, jac->hsolver, jac->tol);
2479792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, jac->hsolver, jac->its);
24803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24819e5bc791SBarry Smith }
24829e5bc791SBarry Smith 
2483d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_PFMG(PC pc)
2484d71ae5a4SJacob Faibussowitsch {
24853a32d3dbSGlenn Hammond   PC_PFMG         *ex = (PC_PFMG *)pc->data;
24863a32d3dbSGlenn Hammond   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
2487ace3abfcSBarry Smith   PetscBool        flg;
24883a32d3dbSGlenn Hammond 
24893a32d3dbSGlenn Hammond   PetscFunctionBegin;
24909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
249128b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
24923a32d3dbSGlenn Hammond 
24933a32d3dbSGlenn Hammond   /* create the hypre solver object and set its information */
2494792fecdfSBarry Smith   if (ex->hsolver) PetscCallExternal(HYPRE_StructPFMGDestroy, ex->hsolver);
2495792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
24960be8cd64Sftrigaux 
24970be8cd64Sftrigaux   // Print Hypre statistics about the solve process
24980be8cd64Sftrigaux   if (ex->print_statistics) PetscCallExternal(HYPRE_StructPFMGSetPrintLevel, ex->hsolver, 3);
24990be8cd64Sftrigaux 
25000be8cd64Sftrigaux   // The hypre options must be repeated here because the StructPFMG was destroyed and recreated
25010be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxIter, ex->hsolver, ex->its);
25020be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
25030be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
25040be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetMaxLevels, ex->hsolver, ex->max_levels);
25050be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetTol, ex->hsolver, ex->tol);
25060be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRelaxType, ex->hsolver, ex->relax_type);
25070be8cd64Sftrigaux   PetscCallExternal(HYPRE_StructPFMGSetRAPType, ex->hsolver, ex->rap_type);
25080be8cd64Sftrigaux 
2509792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
2510792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGSetZeroGuess, ex->hsolver);
25113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25123a32d3dbSGlenn Hammond }
25133a32d3dbSGlenn Hammond 
2514ebc551c0SBarry Smith /*MC
2515ebc551c0SBarry Smith      PCPFMG - the hypre PFMG multigrid solver
2516ebc551c0SBarry Smith 
2517f1580f4eSBarry Smith    Options Database Keys:
251867b8a455SSatish Balay + -pc_pfmg_its <its> - number of iterations of PFMG to use as preconditioner
251967b8a455SSatish Balay . -pc_pfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid solve
252067b8a455SSatish Balay . -pc_pfmg_num_post_relax <steps> - number of smoothing steps after coarse grid solve
252167b8a455SSatish Balay . -pc_pfmg_tol <tol> - tolerance of PFMG
25229e5bc791SBarry 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
25230be8cd64Sftrigaux . -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2524f1580f4eSBarry Smith - -pc_pfmg_skip_relax - skip relaxation on certain grids for isotropic problems. This can greatly improve efficiency by eliminating unnecessary relaxations
2525f1580f4eSBarry Smith                         when the underlying problem is isotropic, one of 0,1
2526f1580f4eSBarry Smith 
2527f1580f4eSBarry Smith    Level: advanced
2528f91d8e95SBarry Smith 
252995452b02SPatrick Sanan    Notes:
253095452b02SPatrick Sanan    This is for CELL-centered descretizations
25319e5bc791SBarry Smith 
2532f1580f4eSBarry Smith    See `PCSYSPFMG` for a version suitable for systems of PDEs, and `PCSMG`
25339e5bc791SBarry Smith 
2534f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2535f1580f4eSBarry Smith 
2536f1580f4eSBarry Smith    This must be used with the `MATHYPRESTRUCT` matrix type.
2537f1580f4eSBarry Smith 
2538f1580f4eSBarry Smith    This provides only some of the functionality of PFMG, it supports only one block per process defined by a PETSc `DMDA`.
2539f1580f4eSBarry Smith 
2540f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESTRUCT`, `PCHYPRE`, `PCGAMG`, `PCSYSPFMG`, `PCSMG`
2541ebc551c0SBarry Smith M*/
2542ebc551c0SBarry Smith 
2543d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2544d71ae5a4SJacob Faibussowitsch {
2545ebc551c0SBarry Smith   PC_PFMG *ex;
2546ebc551c0SBarry Smith 
2547ebc551c0SBarry Smith   PetscFunctionBegin;
25489371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
254968326731SBarry Smith   pc->data = ex;
2550ebc551c0SBarry Smith 
25519e5bc791SBarry Smith   ex->its              = 1;
25529e5bc791SBarry Smith   ex->tol              = 1.e-8;
25539e5bc791SBarry Smith   ex->relax_type       = 1;
25549e5bc791SBarry Smith   ex->rap_type         = 0;
25559e5bc791SBarry Smith   ex->num_pre_relax    = 1;
25569e5bc791SBarry Smith   ex->num_post_relax   = 1;
25573b46a515SGlenn Hammond   ex->max_levels       = 0;
25580be8cd64Sftrigaux   ex->skip_relax       = 0;
25590be8cd64Sftrigaux   ex->print_statistics = PETSC_FALSE;
25609e5bc791SBarry Smith 
2561ebc551c0SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2562ebc551c0SBarry Smith   pc->ops->view            = PCView_PFMG;
2563ebc551c0SBarry Smith   pc->ops->destroy         = PCDestroy_PFMG;
2564f91d8e95SBarry Smith   pc->ops->apply           = PCApply_PFMG;
25659e5bc791SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
256668326731SBarry Smith   pc->ops->setup           = PCSetUp_PFMG;
25672fa5cd67SKarl Rupp 
25689566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2569792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructPFMGCreate, ex->hcomm, &ex->hsolver);
25703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2571ebc551c0SBarry Smith }
2572d851a50bSGlenn Hammond 
2573d851a50bSGlenn Hammond /* we know we are working with a HYPRE_SStructMatrix */
2574d851a50bSGlenn Hammond typedef struct {
2575d851a50bSGlenn Hammond   MPI_Comm            hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2576d851a50bSGlenn Hammond   HYPRE_SStructSolver ss_solver;
2577d851a50bSGlenn Hammond 
2578d851a50bSGlenn Hammond   /* keep copy of SYSPFMG options used so may view them */
25794ddd07fcSJed Brown   PetscInt its;
2580d851a50bSGlenn Hammond   double   tol;
25814ddd07fcSJed Brown   PetscInt relax_type;
25824ddd07fcSJed Brown   PetscInt num_pre_relax, num_post_relax;
2583d851a50bSGlenn Hammond } PC_SysPFMG;
2584d851a50bSGlenn Hammond 
2585d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SysPFMG(PC pc)
2586d71ae5a4SJacob Faibussowitsch {
2587d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2588d851a50bSGlenn Hammond 
2589d851a50bSGlenn Hammond   PetscFunctionBegin;
2590792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
25919566063dSJacob Faibussowitsch   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
25929566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
25933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2594d851a50bSGlenn Hammond }
2595d851a50bSGlenn Hammond 
2596d851a50bSGlenn Hammond static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi", "Red/Black-Gauss-Seidel"};
2597d851a50bSGlenn Hammond 
2598d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SysPFMG(PC pc, PetscViewer viewer)
2599d71ae5a4SJacob Faibussowitsch {
2600ace3abfcSBarry Smith   PetscBool   iascii;
2601d851a50bSGlenn Hammond   PC_SysPFMG *ex = (PC_SysPFMG *)pc->data;
2602d851a50bSGlenn Hammond 
2603d851a50bSGlenn Hammond   PetscFunctionBegin;
26049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2605d851a50bSGlenn Hammond   if (iascii) {
26069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SysPFMG preconditioning\n"));
260763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  max iterations %" PetscInt_FMT "\n", ex->its));
26089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerance %g\n", ex->tol));
26099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  relax type %s\n", PFMGRelaxType[ex->relax_type]));
261063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
2611d851a50bSGlenn Hammond   }
26123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2613d851a50bSGlenn Hammond }
2614d851a50bSGlenn Hammond 
2615d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SysPFMG(PC pc, PetscOptionItems *PetscOptionsObject)
2616d71ae5a4SJacob Faibussowitsch {
2617d851a50bSGlenn Hammond   PC_SysPFMG *ex  = (PC_SysPFMG *)pc->data;
2618ace3abfcSBarry Smith   PetscBool   flg = PETSC_FALSE;
2619d851a50bSGlenn Hammond 
2620d851a50bSGlenn Hammond   PetscFunctionBegin;
2621d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SysPFMG options");
26229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_syspfmg_print_statistics", "Print statistics", "HYPRE_SStructSysPFMGSetPrintLevel", flg, &flg, NULL));
262348a46eb9SPierre Jolivet   if (flg) PetscCallExternal(HYPRE_SStructSysPFMGSetPrintLevel, ex->ss_solver, 3);
26249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_syspfmg_its", "Number of iterations of SysPFMG to use as preconditioner", "HYPRE_SStructSysPFMGSetMaxIter", ex->its, &ex->its, NULL));
2625792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, ex->ss_solver, ex->its);
26269566063dSJacob 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));
2627792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPreRelax, ex->ss_solver, ex->num_pre_relax);
26289566063dSJacob 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));
2629792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetNumPostRelax, ex->ss_solver, ex->num_post_relax);
2630d851a50bSGlenn Hammond 
26319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-pc_syspfmg_tol", "Tolerance of SysPFMG", "HYPRE_SStructSysPFMGSetTol", ex->tol, &ex->tol, NULL));
2632792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, ex->ss_solver, ex->tol);
2633dd39110bSPierre 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));
2634792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetRelaxType, ex->ss_solver, ex->relax_type);
2635d0609cedSBarry Smith   PetscOptionsHeadEnd();
26363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2637d851a50bSGlenn Hammond }
2638d851a50bSGlenn Hammond 
2639d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SysPFMG(PC pc, Vec x, Vec y)
2640d71ae5a4SJacob Faibussowitsch {
2641d851a50bSGlenn Hammond   PC_SysPFMG        *ex = (PC_SysPFMG *)pc->data;
2642d9ca1df4SBarry Smith   PetscScalar       *yy;
2643d9ca1df4SBarry Smith   const PetscScalar *xx;
26444ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
26452cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
2646d851a50bSGlenn Hammond   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(pc->pmat->data);
26474ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
26484ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
26494ddd07fcSJed Brown   PetscInt           part     = 0;
26504ddd07fcSJed Brown   PetscInt           size;
26514ddd07fcSJed Brown   PetscInt           i;
2652d851a50bSGlenn Hammond 
2653d851a50bSGlenn Hammond   PetscFunctionBegin;
26549566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
26559566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
26562cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2657d851a50bSGlenn Hammond   iupper[0] += ilower[0] - 1;
2658d851a50bSGlenn Hammond   iupper[1] += ilower[1] - 1;
2659d851a50bSGlenn Hammond   iupper[2] += ilower[2] - 1;
26602cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
26612cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
26622cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
26632cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
26642cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
26652cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
2666d851a50bSGlenn Hammond 
2667d851a50bSGlenn Hammond   size = 1;
26682fa5cd67SKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
26692fa5cd67SKarl Rupp 
2670d851a50bSGlenn Hammond   /* copy x values over to hypre for variable ordering */
2671d851a50bSGlenn Hammond   if (ordering) {
2672792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26739566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2674792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
26759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2676792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2677792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
2678792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2679d851a50bSGlenn Hammond 
2680d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
26819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2682792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
26839566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
2684a65764d7SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2685d851a50bSGlenn Hammond     PetscScalar *z;
26864ddd07fcSJed Brown     PetscInt     j, k;
2687d851a50bSGlenn Hammond 
26889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
2689792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
26909566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
2691d851a50bSGlenn Hammond 
2692d851a50bSGlenn Hammond     /* transform nodal to hypre's variable ordering for sys_pfmg */
2693d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2694d851a50bSGlenn Hammond       k = i * nvars;
26952fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
2696d851a50bSGlenn Hammond     }
2697792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
26989566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
2699792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
2700792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructSysPFMGSolve, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
2701d851a50bSGlenn Hammond 
2702d851a50bSGlenn Hammond     /* copy solution values back to PETSc */
27039566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
2704792fecdfSBarry Smith     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
2705d851a50bSGlenn Hammond     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2706d851a50bSGlenn Hammond     for (i = 0; i < size; i++) {
2707d851a50bSGlenn Hammond       k = i * nvars;
27082fa5cd67SKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
2709d851a50bSGlenn Hammond     }
27109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
27119566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
2712d851a50bSGlenn Hammond   }
27133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2714d851a50bSGlenn Hammond }
2715d851a50bSGlenn Hammond 
2716d71ae5a4SJacob 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)
2717d71ae5a4SJacob Faibussowitsch {
2718d851a50bSGlenn Hammond   PC_SysPFMG *jac = (PC_SysPFMG *)pc->data;
27192cf14000SStefano Zampini   HYPRE_Int   oits;
2720d851a50bSGlenn Hammond 
2721d851a50bSGlenn Hammond   PetscFunctionBegin;
27229566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
2723792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, its * jac->its);
2724792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, rtol);
27259566063dSJacob Faibussowitsch   PetscCall(PCApply_SysPFMG(pc, b, y));
2726792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGGetNumIterations, jac->ss_solver, &oits);
2727d851a50bSGlenn Hammond   *outits = oits;
2728d851a50bSGlenn Hammond   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2729d851a50bSGlenn Hammond   else *reason = PCRICHARDSON_CONVERGED_RTOL;
2730792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetTol, jac->ss_solver, jac->tol);
2731792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetMaxIter, jac->ss_solver, jac->its);
27323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2733d851a50bSGlenn Hammond }
2734d851a50bSGlenn Hammond 
2735d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SysPFMG(PC pc)
2736d71ae5a4SJacob Faibussowitsch {
2737d851a50bSGlenn Hammond   PC_SysPFMG       *ex = (PC_SysPFMG *)pc->data;
2738d851a50bSGlenn Hammond   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data);
2739ace3abfcSBarry Smith   PetscBool         flg;
2740d851a50bSGlenn Hammond 
2741d851a50bSGlenn Hammond   PetscFunctionBegin;
27429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESSTRUCT, &flg));
274328b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESSTRUCT with this preconditioner");
2744d851a50bSGlenn Hammond 
2745d851a50bSGlenn Hammond   /* create the hypre sstruct solver object and set its information */
2746792fecdfSBarry Smith   if (ex->ss_solver) PetscCallExternal(HYPRE_SStructSysPFMGDestroy, ex->ss_solver);
2747792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
2748792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetZeroGuess, ex->ss_solver);
2749792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGSetup, ex->ss_solver, mx->ss_mat, mx->ss_b, mx->ss_x);
27503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2751d851a50bSGlenn Hammond }
2752d851a50bSGlenn Hammond 
2753d851a50bSGlenn Hammond /*MC
2754f1580f4eSBarry Smith      PCSYSPFMG - the hypre SysPFMG multigrid solver
2755d851a50bSGlenn Hammond 
2756d851a50bSGlenn Hammond    Level: advanced
2757d851a50bSGlenn Hammond 
2758f1580f4eSBarry Smith    Options Database Keys:
275967b8a455SSatish Balay + -pc_syspfmg_its <its> - number of iterations of SysPFMG to use as preconditioner
276067b8a455SSatish Balay . -pc_syspfmg_num_pre_relax <steps> - number of smoothing steps before coarse grid
276167b8a455SSatish Balay . -pc_syspfmg_num_post_relax <steps> - number of smoothing steps after coarse grid
276267b8a455SSatish Balay . -pc_syspfmg_tol <tol> - tolerance of SysPFMG
276367b8a455SSatish Balay - -pc_syspfmg_relax_type <Weighted-Jacobi,Red/Black-Gauss-Seidel> - relaxation type for the up and down cycles
2764d851a50bSGlenn Hammond 
276595452b02SPatrick Sanan    Notes:
2766f1580f4eSBarry Smith    See `PCPFMG` for hypre's PFMG that works for a scalar PDE and `PCSMG`
2767f1580f4eSBarry Smith 
2768f1580f4eSBarry Smith    See `PCHYPRE` for hypre's BoomerAMG algebraic multigrid solver
2769f1580f4eSBarry Smith 
277095452b02SPatrick Sanan    This is for CELL-centered descretizations
2771d851a50bSGlenn Hammond 
2772f1580f4eSBarry Smith    This must be used with the `MATHYPRESSTRUCT` matrix type.
2773d851a50bSGlenn Hammond 
2774f1580f4eSBarry 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`.
2775f1580f4eSBarry Smith 
2776f1580f4eSBarry Smith .seealso: `PCMG`, `MATHYPRESSTRUCT`, `PCPFMG`, `PCHYPRE`, `PCGAMG`, `PCSMG`
2777d851a50bSGlenn Hammond M*/
2778d851a50bSGlenn Hammond 
2779d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2780d71ae5a4SJacob Faibussowitsch {
2781d851a50bSGlenn Hammond   PC_SysPFMG *ex;
2782d851a50bSGlenn Hammond 
2783d851a50bSGlenn Hammond   PetscFunctionBegin;
27849371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
2785d851a50bSGlenn Hammond   pc->data = ex;
2786d851a50bSGlenn Hammond 
2787d851a50bSGlenn Hammond   ex->its            = 1;
2788d851a50bSGlenn Hammond   ex->tol            = 1.e-8;
2789d851a50bSGlenn Hammond   ex->relax_type     = 1;
2790d851a50bSGlenn Hammond   ex->num_pre_relax  = 1;
2791d851a50bSGlenn Hammond   ex->num_post_relax = 1;
2792d851a50bSGlenn Hammond 
2793d851a50bSGlenn Hammond   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2794d851a50bSGlenn Hammond   pc->ops->view            = PCView_SysPFMG;
2795d851a50bSGlenn Hammond   pc->ops->destroy         = PCDestroy_SysPFMG;
2796d851a50bSGlenn Hammond   pc->ops->apply           = PCApply_SysPFMG;
2797d851a50bSGlenn Hammond   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2798d851a50bSGlenn Hammond   pc->ops->setup           = PCSetUp_SysPFMG;
27992fa5cd67SKarl Rupp 
28009566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
2801792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructSysPFMGCreate, ex->hcomm, &ex->ss_solver);
28023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2803d851a50bSGlenn Hammond }
28041c188c59Sftrigaux 
2805f1580f4eSBarry Smith /* PC SMG */
28061c188c59Sftrigaux typedef struct {
28071c188c59Sftrigaux   MPI_Comm           hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
28081c188c59Sftrigaux   HYPRE_StructSolver hsolver;
28091c188c59Sftrigaux   PetscInt           its; /* keep copy of SMG options used so may view them */
28101c188c59Sftrigaux   double             tol;
28111c188c59Sftrigaux   PetscBool          print_statistics;
28121c188c59Sftrigaux   PetscInt           num_pre_relax, num_post_relax;
28131c188c59Sftrigaux } PC_SMG;
28141c188c59Sftrigaux 
2815d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_SMG(PC pc)
2816d71ae5a4SJacob Faibussowitsch {
28171c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28181c188c59Sftrigaux 
28191c188c59Sftrigaux   PetscFunctionBegin;
28201c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, ex->hsolver);
28211c188c59Sftrigaux   PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
28221c188c59Sftrigaux   PetscCall(PetscFree(pc->data));
28233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28241c188c59Sftrigaux }
28251c188c59Sftrigaux 
2826d71ae5a4SJacob Faibussowitsch PetscErrorCode PCView_SMG(PC pc, PetscViewer viewer)
2827d71ae5a4SJacob Faibussowitsch {
28281c188c59Sftrigaux   PetscBool iascii;
28291c188c59Sftrigaux   PC_SMG   *ex = (PC_SMG *)pc->data;
28301c188c59Sftrigaux 
28311c188c59Sftrigaux   PetscFunctionBegin;
28321c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
28331c188c59Sftrigaux   if (iascii) {
28341c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "  HYPRE SMG preconditioning\n"));
28351c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    max iterations %" PetscInt_FMT "\n", ex->its));
28361c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    tolerance %g\n", ex->tol));
28371c188c59Sftrigaux     PetscCall(PetscViewerASCIIPrintf(viewer, "    number pre-relax %" PetscInt_FMT " post-relax %" PetscInt_FMT "\n", ex->num_pre_relax, ex->num_post_relax));
28381c188c59Sftrigaux   }
28393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28401c188c59Sftrigaux }
28411c188c59Sftrigaux 
2842d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_SMG(PC pc, PetscOptionItems *PetscOptionsObject)
2843d71ae5a4SJacob Faibussowitsch {
28441c188c59Sftrigaux   PC_SMG *ex = (PC_SMG *)pc->data;
28451c188c59Sftrigaux 
28461c188c59Sftrigaux   PetscFunctionBegin;
28471c188c59Sftrigaux   PetscOptionsHeadBegin(PetscOptionsObject, "SMG options");
28481c188c59Sftrigaux 
28491c188c59Sftrigaux   PetscCall(PetscOptionsInt("-pc_smg_its", "Number of iterations of SMG to use as preconditioner", "HYPRE_StructSMGSetMaxIter", ex->its, &ex->its, NULL));
28501c188c59Sftrigaux   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));
28511c188c59Sftrigaux   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));
28521c188c59Sftrigaux   PetscCall(PetscOptionsReal("-pc_smg_tol", "Tolerance of SMG", "HYPRE_StructSMGSetTol", ex->tol, &ex->tol, NULL));
28531c188c59Sftrigaux 
28541c188c59Sftrigaux   PetscOptionsHeadEnd();
28553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28561c188c59Sftrigaux }
28571c188c59Sftrigaux 
2858d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_SMG(PC pc, Vec x, Vec y)
2859d71ae5a4SJacob Faibussowitsch {
28601c188c59Sftrigaux   PC_SMG            *ex = (PC_SMG *)pc->data;
28611c188c59Sftrigaux   PetscScalar       *yy;
28621c188c59Sftrigaux   const PetscScalar *xx;
28631c188c59Sftrigaux   PetscInt           ilower[3], iupper[3];
28641c188c59Sftrigaux   HYPRE_Int          hlower[3], hupper[3];
28651c188c59Sftrigaux   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(pc->pmat->data);
28661c188c59Sftrigaux 
28671c188c59Sftrigaux   PetscFunctionBegin;
28681c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
28691c188c59Sftrigaux   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
28701c188c59Sftrigaux   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
28711c188c59Sftrigaux   iupper[0] += ilower[0] - 1;
28721c188c59Sftrigaux   iupper[1] += ilower[1] - 1;
28731c188c59Sftrigaux   iupper[2] += ilower[2] - 1;
28741c188c59Sftrigaux   hlower[0] = (HYPRE_Int)ilower[0];
28751c188c59Sftrigaux   hlower[1] = (HYPRE_Int)ilower[1];
28761c188c59Sftrigaux   hlower[2] = (HYPRE_Int)ilower[2];
28771c188c59Sftrigaux   hupper[0] = (HYPRE_Int)iupper[0];
28781c188c59Sftrigaux   hupper[1] = (HYPRE_Int)iupper[1];
28791c188c59Sftrigaux   hupper[2] = (HYPRE_Int)iupper[2];
28801c188c59Sftrigaux 
28811c188c59Sftrigaux   /* copy x values over to hypre */
28821c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
28831c188c59Sftrigaux   PetscCall(VecGetArrayRead(x, &xx));
28841c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
28851c188c59Sftrigaux   PetscCall(VecRestoreArrayRead(x, &xx));
28861c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
28871c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSolve, ex->hsolver, mx->hmat, mx->hb, mx->hx);
28881c188c59Sftrigaux 
28891c188c59Sftrigaux   /* copy solution values back to PETSc */
28901c188c59Sftrigaux   PetscCall(VecGetArray(y, &yy));
28911c188c59Sftrigaux   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
28921c188c59Sftrigaux   PetscCall(VecRestoreArray(y, &yy));
28933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28941c188c59Sftrigaux }
28951c188c59Sftrigaux 
2896d71ae5a4SJacob 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)
2897d71ae5a4SJacob Faibussowitsch {
28981c188c59Sftrigaux   PC_SMG   *jac = (PC_SMG *)pc->data;
28991c188c59Sftrigaux   HYPRE_Int oits;
29001c188c59Sftrigaux 
29011c188c59Sftrigaux   PetscFunctionBegin;
29021c188c59Sftrigaux   PetscCall(PetscCitationsRegister(hypreCitation, &cite));
29031c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, its * jac->its);
29041c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, rtol);
29051c188c59Sftrigaux 
29061c188c59Sftrigaux   PetscCall(PCApply_SMG(pc, b, y));
29071c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGGetNumIterations, jac->hsolver, &oits);
29081c188c59Sftrigaux   *outits = oits;
29091c188c59Sftrigaux   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
29101c188c59Sftrigaux   else *reason = PCRICHARDSON_CONVERGED_RTOL;
29111c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, jac->hsolver, jac->tol);
29121c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, jac->hsolver, jac->its);
29133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29141c188c59Sftrigaux }
29151c188c59Sftrigaux 
2916d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_SMG(PC pc)
2917d71ae5a4SJacob Faibussowitsch {
29181c188c59Sftrigaux   PetscInt         i, dim;
29191c188c59Sftrigaux   PC_SMG          *ex = (PC_SMG *)pc->data;
29201c188c59Sftrigaux   Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data);
29211c188c59Sftrigaux   PetscBool        flg;
29221c188c59Sftrigaux   DMBoundaryType   p[3];
29231c188c59Sftrigaux   PetscInt         M[3];
29241c188c59Sftrigaux 
29251c188c59Sftrigaux   PetscFunctionBegin;
29261c188c59Sftrigaux   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATHYPRESTRUCT, &flg));
29271c188c59Sftrigaux   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Must use MATHYPRESTRUCT with this preconditioner");
29281c188c59Sftrigaux 
29291c188c59Sftrigaux   PetscCall(DMDAGetInfo(mx->da, &dim, &M[0], &M[1], &M[2], 0, 0, 0, 0, 0, &p[0], &p[1], &p[2], 0));
29301c188c59Sftrigaux   // Check if power of 2 in periodic directions
29311c188c59Sftrigaux   for (i = 0; i < dim; i++) {
29321c188c59Sftrigaux     if (((M[i] & (M[i] - 1)) != 0) && (p[i] == DM_BOUNDARY_PERIODIC)) {
29331c188c59Sftrigaux       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]);
29341c188c59Sftrigaux     }
29351c188c59Sftrigaux   }
29361c188c59Sftrigaux 
29371c188c59Sftrigaux   /* create the hypre solver object and set its information */
29381c188c59Sftrigaux   if (ex->hsolver) PetscCallExternal(HYPRE_StructSMGDestroy, (ex->hsolver));
29391c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29401c188c59Sftrigaux   // The hypre options must be set here and not in SetFromOptions because it is created here!
29411c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetMaxIter, ex->hsolver, ex->its);
29421c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPreRelax, ex->hsolver, ex->num_pre_relax);
29431c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetNumPostRelax, ex->hsolver, ex->num_post_relax);
29441c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetTol, ex->hsolver, ex->tol);
29451c188c59Sftrigaux 
29461c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetup, ex->hsolver, mx->hmat, mx->hb, mx->hx);
29471c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGSetZeroGuess, ex->hsolver);
29483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29491c188c59Sftrigaux }
29501c188c59Sftrigaux 
29511c188c59Sftrigaux /*MC
29525cb80ecdSBarry Smith      PCSMG - the hypre (structured grid) SMG multigrid solver
29531c188c59Sftrigaux 
29541c188c59Sftrigaux    Level: advanced
29551c188c59Sftrigaux 
2956f1580f4eSBarry Smith    Options Database Keys:
29575cb80ecdSBarry Smith + -pc_smg_its <its> - number of iterations of SMG to use as preconditioner
29585cb80ecdSBarry Smith . -pc_smg_num_pre_relax <steps> - number of smoothing steps before coarse grid
29595cb80ecdSBarry Smith . -pc_smg_num_post_relax <steps> - number of smoothing steps after coarse grid
29605cb80ecdSBarry Smith - -pc_smg_tol <tol> - tolerance of SMG
29611c188c59Sftrigaux 
29621c188c59Sftrigaux    Notes:
29631c188c59Sftrigaux    This is for CELL-centered descretizations
29641c188c59Sftrigaux 
29655cb80ecdSBarry Smith    This must be used with the `MATHYPRESTRUCT` `MatType`.
29661c188c59Sftrigaux 
2967f1580f4eSBarry 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`.
2968f1580f4eSBarry Smith 
2969f1580f4eSBarry Smith    See `PCSYSPFMG`, `PCSMG`, `PCPFMG`, and `PCHYPRE` for access to hypre's other preconditioners
2970f1580f4eSBarry Smith 
2971f1580f4eSBarry Smith .seealso:  `PCMG`, `MATHYPRESTRUCT`, `PCPFMG`, `PCSYSPFMG`, `PCHYPRE`, `PCGAMG`
29721c188c59Sftrigaux M*/
29731c188c59Sftrigaux 
2974d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_SMG(PC pc)
2975d71ae5a4SJacob Faibussowitsch {
29761c188c59Sftrigaux   PC_SMG *ex;
29771c188c59Sftrigaux 
29781c188c59Sftrigaux   PetscFunctionBegin;
29799371c9d4SSatish Balay   PetscCall(PetscNew(&ex));
29801c188c59Sftrigaux   pc->data = ex;
29811c188c59Sftrigaux 
29821c188c59Sftrigaux   ex->its            = 1;
29831c188c59Sftrigaux   ex->tol            = 1.e-8;
29841c188c59Sftrigaux   ex->num_pre_relax  = 1;
29851c188c59Sftrigaux   ex->num_post_relax = 1;
29861c188c59Sftrigaux 
29871c188c59Sftrigaux   pc->ops->setfromoptions  = PCSetFromOptions_SMG;
29881c188c59Sftrigaux   pc->ops->view            = PCView_SMG;
29891c188c59Sftrigaux   pc->ops->destroy         = PCDestroy_SMG;
29901c188c59Sftrigaux   pc->ops->apply           = PCApply_SMG;
29911c188c59Sftrigaux   pc->ops->applyrichardson = PCApplyRichardson_SMG;
29921c188c59Sftrigaux   pc->ops->setup           = PCSetUp_SMG;
29931c188c59Sftrigaux 
29941c188c59Sftrigaux   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)pc), &ex->hcomm));
29951c188c59Sftrigaux   PetscCallExternal(HYPRE_StructSMGCreate, ex->hcomm, &ex->hsolver);
29963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29971c188c59Sftrigaux }
2998