xref: /petsc/src/ksp/pc/impls/hypre/hypre.c (revision 7d5fd1e4d9337468ad3f05b65b7facdcd2dfd2a4)
1 /*
2    Provides an interface to the LLNL package hypre
3 */
4 
5 #include <petscpkg_version.h>
6 #include <petsc/private/pcimpl.h>          /*I "petscpc.h" I*/
7 /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */
8 #include <petsc/private/matimpl.h>
9 #include <petsc/private/vecimpl.h>
10 #include <../src/vec/vec/impls/hypre/vhyp.h>
11 #include <../src/mat/impls/hypre/mhypre.h>
12 #include <../src/dm/impls/da/hypre/mhyp.h>
13 #include <_hypre_parcsr_ls.h>
14 #include <petscmathypre.h>
15 
16 static PetscBool cite = PETSC_FALSE;
17 static const char hypreCitation[] = "@manual{hypre-web-page,\n  title  = {{\\sl hypre}: High Performance Preconditioners},\n  organization = {Lawrence Livermore National Laboratory},\n  note  = {\\url{https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods}}\n}\n";
18 
19 /*
20    Private context (data structure) for the  preconditioner.
21 */
22 typedef struct {
23   HYPRE_Solver   hsolver;
24   Mat            hpmat; /* MatHYPRE */
25 
26   HYPRE_Int (*destroy)(HYPRE_Solver);
27   HYPRE_Int (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
28   HYPRE_Int (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector);
29 
30   MPI_Comm comm_hypre;
31   char     *hypre_type;
32 
33   /* options for Pilut and BoomerAMG*/
34   PetscInt  maxiter;
35   PetscReal tol;
36 
37   /* options for Pilut */
38   PetscInt factorrowsize;
39 
40   /* options for ParaSails */
41   PetscInt  nlevels;
42   PetscReal threshold;
43   PetscReal filter;
44   PetscReal loadbal;
45   PetscInt  logging;
46   PetscInt  ruse;
47   PetscInt  symt;
48 
49   /* options for BoomerAMG */
50   PetscBool printstatistics;
51 
52   /* options for BoomerAMG */
53   PetscInt  cycletype;
54   PetscInt  maxlevels;
55   PetscReal strongthreshold;
56   PetscReal maxrowsum;
57   PetscInt  gridsweeps[3];
58   PetscInt  coarsentype;
59   PetscInt  measuretype;
60   PetscInt  smoothtype;
61   PetscInt  smoothnumlevels;
62   PetscInt  eu_level;   /* Number of levels for ILU(k) in Euclid */
63   PetscReal eu_droptolerance; /* Drop tolerance for ILU(k) in Euclid */
64   PetscInt  eu_bj;      /* Defines use of Block Jacobi ILU in Euclid */
65   PetscInt  relaxtype[3];
66   PetscReal relaxweight;
67   PetscReal outerrelaxweight;
68   PetscInt  relaxorder;
69   PetscReal truncfactor;
70   PetscBool applyrichardson;
71   PetscInt  pmax;
72   PetscInt  interptype;
73   PetscInt  maxc;
74   PetscInt  minc;
75 
76   /* GPU */
77   PetscBool keeptranspose;
78   PetscInt  rap2;
79   PetscInt  mod_rap2;
80 
81   /* AIR */
82   PetscInt  Rtype;
83   PetscReal Rstrongthreshold;
84   PetscReal Rfilterthreshold;
85   PetscInt  Adroptype;
86   PetscReal Adroptol;
87 
88   PetscInt  agg_nl;
89   PetscInt  agg_interptype;
90   PetscInt  agg_num_paths;
91   PetscBool nodal_relax;
92   PetscInt  nodal_relax_levels;
93 
94   PetscInt  nodal_coarsening;
95   PetscInt  nodal_coarsening_diag;
96   PetscInt  vec_interp_variant;
97   PetscInt  vec_interp_qmax;
98   PetscBool vec_interp_smooth;
99   PetscInt  interp_refine;
100 
101   /* NearNullSpace support */
102   VecHYPRE_IJVector *hmnull;
103   HYPRE_ParVector   *phmnull;
104   PetscInt          n_hmnull;
105   Vec               hmnull_constant;
106 
107   /* options for AS (Auxiliary Space preconditioners) */
108   PetscInt  as_print;
109   PetscInt  as_max_iter;
110   PetscReal as_tol;
111   PetscInt  as_relax_type;
112   PetscInt  as_relax_times;
113   PetscReal as_relax_weight;
114   PetscReal as_omega;
115   PetscInt  as_amg_alpha_opts[5]; /* AMG coarsen type, agg_levels, relax_type, interp_type, Pmax for vector Poisson (AMS) or Curl problem (ADS) */
116   PetscReal as_amg_alpha_theta;   /* AMG strength for vector Poisson (AMS) or Curl problem (ADS) */
117   PetscInt  as_amg_beta_opts[5];  /* AMG coarsen type, agg_levels, relax_type, interp_type, Pmax for scalar Poisson (AMS) or vector Poisson (ADS) */
118   PetscReal as_amg_beta_theta;    /* AMG strength for scalar Poisson (AMS) or vector Poisson (ADS)  */
119   PetscInt  ams_cycle_type;
120   PetscInt  ads_cycle_type;
121 
122   /* additional data */
123   Mat G;             /* MatHYPRE */
124   Mat C;             /* MatHYPRE */
125   Mat alpha_Poisson; /* MatHYPRE */
126   Mat beta_Poisson;  /* MatHYPRE */
127 
128   /* extra information for AMS */
129   PetscInt          dim; /* geometrical dimension */
130   VecHYPRE_IJVector coords[3];
131   VecHYPRE_IJVector constants[3];
132   Mat               RT_PiFull, RT_Pi[3];
133   Mat               ND_PiFull, ND_Pi[3];
134   PetscBool         ams_beta_is_zero;
135   PetscBool         ams_beta_is_zero_part;
136   PetscInt          ams_proj_freq;
137 } PC_HYPRE;
138 
139 PetscErrorCode PCHYPREGetSolver(PC pc,HYPRE_Solver *hsolver)
140 {
141   PC_HYPRE *jac = (PC_HYPRE*)pc->data;
142 
143   PetscFunctionBegin;
144   *hsolver = jac->hsolver;
145   PetscFunctionReturn(0);
146 }
147 
148 /*
149   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
150   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
151   It is used in PCHMG. Other users should avoid using this function.
152 */
153 static PetscErrorCode PCGetCoarseOperators_BoomerAMG(PC pc,PetscInt *nlevels,Mat *operators[])
154 {
155   PC_HYPRE             *jac  = (PC_HYPRE*)pc->data;
156   PetscBool            same = PETSC_FALSE;
157   PetscErrorCode       ierr;
158   PetscInt             num_levels,l;
159   Mat                  *mattmp;
160   hypre_ParCSRMatrix   **A_array;
161 
162   PetscFunctionBegin;
163   ierr = PetscStrcmp(jac->hypre_type,"boomeramg",&same);CHKERRQ(ierr);
164   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_NOTSAMETYPE,"Hypre type is not BoomerAMG \n");
165   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData*) (jac->hsolver));
166   ierr = PetscMalloc1(num_levels,&mattmp);CHKERRQ(ierr);
167   A_array    = hypre_ParAMGDataAArray((hypre_ParAMGData*) (jac->hsolver));
168   for (l=1; l<num_levels; l++) {
169     ierr = MatCreateFromParCSR(A_array[l],MATAIJ,PETSC_OWN_POINTER, &(mattmp[num_levels-1-l]));CHKERRQ(ierr);
170     /* We want to own the data, and HYPRE can not touch this matrix any more */
171     A_array[l] = NULL;
172   }
173   *nlevels = num_levels;
174   *operators = mattmp;
175   PetscFunctionReturn(0);
176 }
177 
178 /*
179   Matrices with AIJ format are created IN PLACE with using (I,J,data) from BoomerAMG. Since the data format in hypre_ParCSRMatrix
180   is different from that used in PETSc, the original hypre_ParCSRMatrix can not be used any more after call this routine.
181   It is used in PCHMG. Other users should avoid using this function.
182 */
183 static PetscErrorCode PCGetInterpolations_BoomerAMG(PC pc,PetscInt *nlevels,Mat *interpolations[])
184 {
185   PC_HYPRE             *jac  = (PC_HYPRE*)pc->data;
186   PetscBool            same = PETSC_FALSE;
187   PetscErrorCode       ierr;
188   PetscInt             num_levels,l;
189   Mat                  *mattmp;
190   hypre_ParCSRMatrix   **P_array;
191 
192   PetscFunctionBegin;
193   ierr = PetscStrcmp(jac->hypre_type,"boomeramg",&same);CHKERRQ(ierr);
194   if (!same) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_NOTSAMETYPE,"Hypre type is not BoomerAMG \n");
195   num_levels = hypre_ParAMGDataNumLevels((hypre_ParAMGData*) (jac->hsolver));
196   ierr = PetscMalloc1(num_levels,&mattmp);CHKERRQ(ierr);
197   P_array  = hypre_ParAMGDataPArray((hypre_ParAMGData*) (jac->hsolver));
198   for (l=1; l<num_levels; l++) {
199     ierr = MatCreateFromParCSR(P_array[num_levels-1-l],MATAIJ,PETSC_OWN_POINTER, &(mattmp[l-1]));CHKERRQ(ierr);
200     /* We want to own the data, and HYPRE can not touch this matrix any more */
201     P_array[num_levels-1-l] = NULL;
202   }
203   *nlevels = num_levels;
204   *interpolations = mattmp;
205   PetscFunctionReturn(0);
206 }
207 
208 /* Resets (frees) Hypre's representation of the near null space */
209 static PetscErrorCode PCHYPREResetNearNullSpace_Private(PC pc)
210 {
211   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
212   PetscInt       i;
213   PetscErrorCode ierr;
214 
215   PetscFunctionBegin;
216   for (i=0; i<jac->n_hmnull; i++) {
217     ierr = VecHYPRE_IJVectorDestroy(&jac->hmnull[i]);CHKERRQ(ierr);
218   }
219   ierr = PetscFree(jac->hmnull);CHKERRQ(ierr);
220   ierr = PetscFree(jac->phmnull);CHKERRQ(ierr);
221   ierr = VecDestroy(&jac->hmnull_constant);CHKERRQ(ierr);
222   jac->n_hmnull = 0;
223   PetscFunctionReturn(0);
224 }
225 
226 static PetscErrorCode PCSetUp_HYPRE(PC pc)
227 {
228   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
229   Mat_HYPRE          *hjac;
230   HYPRE_ParCSRMatrix hmat;
231   HYPRE_ParVector    bv,xv;
232   PetscBool          ishypre;
233   PetscErrorCode     ierr;
234 
235   PetscFunctionBegin;
236   if (!jac->hypre_type) {
237     ierr = PCHYPRESetType(pc,"boomeramg");CHKERRQ(ierr);
238   }
239 
240   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRE,&ishypre);CHKERRQ(ierr);
241   if (!ishypre) {
242     ierr = MatDestroy(&jac->hpmat);CHKERRQ(ierr);
243     ierr = MatConvert(pc->pmat,MATHYPRE,MAT_INITIAL_MATRIX,&jac->hpmat);CHKERRQ(ierr);
244     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->hpmat);CHKERRQ(ierr);
245   } else {
246     ierr = PetscObjectReference((PetscObject)pc->pmat);CHKERRQ(ierr);
247     ierr = MatDestroy(&jac->hpmat);CHKERRQ(ierr);
248     jac->hpmat = pc->pmat;
249   }
250   /* allow debug */
251   ierr = MatViewFromOptions(jac->hpmat,NULL,"-pc_hypre_mat_view");CHKERRQ(ierr);
252   hjac = (Mat_HYPRE*)(jac->hpmat->data);
253 
254   /* special case for BoomerAMG */
255   if (jac->setup == HYPRE_BoomerAMGSetup) {
256     MatNullSpace mnull;
257     PetscBool    has_const;
258     PetscInt     bs,nvec,i;
259     const Vec    *vecs;
260 
261     ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
262     if (bs > 1) PetscStackCallStandard(HYPRE_BoomerAMGSetNumFunctions,(jac->hsolver,bs));
263     ierr = MatGetNearNullSpace(pc->mat, &mnull);CHKERRQ(ierr);
264     if (mnull) {
265       ierr = PCHYPREResetNearNullSpace_Private(pc);CHKERRQ(ierr);
266       ierr = MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs);CHKERRQ(ierr);
267       ierr = PetscMalloc1(nvec+1,&jac->hmnull);CHKERRQ(ierr);
268       ierr = PetscMalloc1(nvec+1,&jac->phmnull);CHKERRQ(ierr);
269       for (i=0; i<nvec; i++) {
270         ierr = VecHYPRE_IJVectorCreate(vecs[i]->map,&jac->hmnull[i]);CHKERRQ(ierr);
271         ierr = VecHYPRE_IJVectorCopy(vecs[i],jac->hmnull[i]);CHKERRQ(ierr);
272         PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->hmnull[i]->ij,(void**)&jac->phmnull[i]));
273       }
274       if (has_const) {
275         ierr = MatCreateVecs(pc->pmat,&jac->hmnull_constant,NULL);CHKERRQ(ierr);
276         ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->hmnull_constant);CHKERRQ(ierr);
277         ierr = VecSet(jac->hmnull_constant,1);CHKERRQ(ierr);
278         ierr = VecNormalize(jac->hmnull_constant,NULL);CHKERRQ(ierr);
279         ierr = VecHYPRE_IJVectorCreate(jac->hmnull_constant->map,&jac->hmnull[nvec]);CHKERRQ(ierr);
280         ierr = VecHYPRE_IJVectorCopy(jac->hmnull_constant,jac->hmnull[nvec]);CHKERRQ(ierr);
281         PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->hmnull[nvec]->ij,(void**)&jac->phmnull[nvec]));
282         nvec++;
283       }
284       PetscStackCallStandard(HYPRE_BoomerAMGSetInterpVectors,(jac->hsolver,nvec,jac->phmnull));
285       jac->n_hmnull = nvec;
286     }
287   }
288 
289   /* special case for AMS */
290   if (jac->setup == HYPRE_AMSSetup) {
291     Mat_HYPRE          *hm;
292     HYPRE_ParCSRMatrix parcsr;
293     if (!jac->coords[0] && !jac->constants[0] && !(jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
294       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");
295     }
296     if (jac->dim) {
297       PetscStackCallStandard(HYPRE_AMSSetDimension,(jac->hsolver,jac->dim));
298     }
299     if (jac->constants[0]) {
300       HYPRE_ParVector ozz,zoz,zzo = NULL;
301       PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->constants[0]->ij,(void**)(&ozz)));
302       PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->constants[1]->ij,(void**)(&zoz)));
303       if (jac->constants[2]) {
304         PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->constants[2]->ij,(void**)(&zzo)));
305       }
306       PetscStackCallStandard(HYPRE_AMSSetEdgeConstantVectors,(jac->hsolver,ozz,zoz,zzo));
307     }
308     if (jac->coords[0]) {
309       HYPRE_ParVector coords[3];
310       coords[0] = NULL;
311       coords[1] = NULL;
312       coords[2] = NULL;
313       if (jac->coords[0]) PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->coords[0]->ij,(void**)(&coords[0])));
314       if (jac->coords[1]) PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->coords[1]->ij,(void**)(&coords[1])));
315       if (jac->coords[2]) PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->coords[2]->ij,(void**)(&coords[2])));
316       PetscStackCallStandard(HYPRE_AMSSetCoordinateVectors,(jac->hsolver,coords[0],coords[1],coords[2]));
317     }
318     if (!jac->G) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE AMS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
319     hm = (Mat_HYPRE*)(jac->G->data);
320     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&parcsr)));
321     PetscStackCallStandard(HYPRE_AMSSetDiscreteGradient,(jac->hsolver,parcsr));
322     if (jac->alpha_Poisson) {
323       hm = (Mat_HYPRE*)(jac->alpha_Poisson->data);
324       PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&parcsr)));
325       PetscStackCallStandard(HYPRE_AMSSetAlphaPoissonMatrix,(jac->hsolver,parcsr));
326     }
327     if (jac->ams_beta_is_zero) {
328       PetscStackCallStandard(HYPRE_AMSSetBetaPoissonMatrix,(jac->hsolver,NULL));
329     } else if (jac->beta_Poisson) {
330       hm = (Mat_HYPRE*)(jac->beta_Poisson->data);
331       PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&parcsr)));
332       PetscStackCallStandard(HYPRE_AMSSetBetaPoissonMatrix,(jac->hsolver,parcsr));
333     }
334     if (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1])) {
335       PetscInt           i;
336       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
337       if (jac->ND_PiFull) {
338         hm = (Mat_HYPRE*)(jac->ND_PiFull->data);
339         PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&nd_parcsrfull)));
340       } else {
341         nd_parcsrfull = NULL;
342       }
343       for (i=0;i<3;++i) {
344         if (jac->ND_Pi[i]) {
345           hm = (Mat_HYPRE*)(jac->ND_Pi[i]->data);
346           PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&nd_parcsr[i])));
347         } else {
348           nd_parcsr[i] = NULL;
349         }
350       }
351       PetscStackCallStandard(HYPRE_AMSSetInterpolations,(jac->hsolver,nd_parcsrfull,nd_parcsr[0],nd_parcsr[1],nd_parcsr[2]));
352     }
353   }
354   /* special case for ADS */
355   if (jac->setup == HYPRE_ADSSetup) {
356     Mat_HYPRE          *hm;
357     HYPRE_ParCSRMatrix parcsr;
358     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])))) {
359       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner needs either the coordinate vectors via PCSetCoordinates() or the interpolation matrices via PCHYPRESetInterpolations");
360     }
361     else if (!jac->coords[1] || !jac->coords[2]) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner has been designed for three dimensional problems! For two dimensional problems, use HYPRE AMS instead");
362     if (!jac->G) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner needs the discrete gradient operator via PCHYPRESetDiscreteGradient");
363     if (!jac->C) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"HYPRE ADS preconditioner needs the discrete curl operator via PCHYPRESetDiscreteGradient");
364     if (jac->coords[0]) {
365       HYPRE_ParVector coords[3];
366       coords[0] = NULL;
367       coords[1] = NULL;
368       coords[2] = NULL;
369       if (jac->coords[0]) PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->coords[0]->ij,(void**)(&coords[0])));
370       if (jac->coords[1]) PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->coords[1]->ij,(void**)(&coords[1])));
371       if (jac->coords[2]) PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->coords[2]->ij,(void**)(&coords[2])));
372       PetscStackCallStandard(HYPRE_ADSSetCoordinateVectors,(jac->hsolver,coords[0],coords[1],coords[2]));
373     }
374     hm = (Mat_HYPRE*)(jac->G->data);
375     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&parcsr)));
376     PetscStackCallStandard(HYPRE_ADSSetDiscreteGradient,(jac->hsolver,parcsr));
377     hm = (Mat_HYPRE*)(jac->C->data);
378     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&parcsr)));
379     PetscStackCallStandard(HYPRE_ADSSetDiscreteCurl,(jac->hsolver,parcsr));
380     if ((jac->RT_PiFull || (jac->RT_Pi[0] && jac->RT_Pi[1])) && (jac->ND_PiFull || (jac->ND_Pi[0] && jac->ND_Pi[1]))) {
381       PetscInt           i;
382       HYPRE_ParCSRMatrix rt_parcsrfull, rt_parcsr[3];
383       HYPRE_ParCSRMatrix nd_parcsrfull, nd_parcsr[3];
384       if (jac->RT_PiFull) {
385         hm = (Mat_HYPRE*)(jac->RT_PiFull->data);
386         PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&rt_parcsrfull)));
387       } else {
388         rt_parcsrfull = NULL;
389       }
390       for (i=0;i<3;++i) {
391         if (jac->RT_Pi[i]) {
392           hm = (Mat_HYPRE*)(jac->RT_Pi[i]->data);
393           PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&rt_parcsr[i])));
394         } else {
395           rt_parcsr[i] = NULL;
396         }
397       }
398       if (jac->ND_PiFull) {
399         hm = (Mat_HYPRE*)(jac->ND_PiFull->data);
400         PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&nd_parcsrfull)));
401       } else {
402         nd_parcsrfull = NULL;
403       }
404       for (i=0;i<3;++i) {
405         if (jac->ND_Pi[i]) {
406           hm = (Mat_HYPRE*)(jac->ND_Pi[i]->data);
407           PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hm->ij,(void**)(&nd_parcsr[i])));
408         } else {
409           nd_parcsr[i] = NULL;
410         }
411       }
412       PetscStackCallStandard(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]));
413     }
414   }
415   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hjac->ij,(void**)&hmat));
416   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hjac->b->ij,(void**)&bv));
417   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hjac->x->ij,(void**)&xv));
418   PetscStackCallStandard(jac->setup,(jac->hsolver,hmat,bv,xv));
419   PetscFunctionReturn(0);
420 }
421 
422 static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x)
423 {
424   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
425   Mat_HYPRE          *hjac = (Mat_HYPRE*)(jac->hpmat->data);
426   PetscErrorCode     ierr;
427   HYPRE_ParCSRMatrix hmat;
428   HYPRE_ParVector    jbv,jxv;
429   PetscInt           hierr;
430 
431   PetscFunctionBegin;
432   ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
433   if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);}
434   ierr = VecHYPRE_IJVectorPushVecRead(hjac->b,b);CHKERRQ(ierr);
435   if (jac->applyrichardson) { ierr = VecHYPRE_IJVectorPushVec(hjac->x,x);CHKERRQ(ierr); }
436   else { ierr = VecHYPRE_IJVectorPushVecWrite(hjac->x,x);CHKERRQ(ierr); }
437   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hjac->ij,(void**)&hmat));
438   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hjac->b->ij,(void**)&jbv));
439   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hjac->x->ij,(void**)&jxv));
440   PetscStackCall("Hypre solve",hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv);
441   if (hierr && hierr != HYPRE_ERROR_CONV) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
442   if (hierr) hypre__global_error = 0;);
443 
444   if (jac->setup == HYPRE_AMSSetup && jac->ams_beta_is_zero_part) {
445     PetscStackCallStandard(HYPRE_AMSProjectOutGradients,(jac->hsolver,jxv));
446   }
447   ierr = VecHYPRE_IJVectorPopVec(hjac->x);CHKERRQ(ierr);
448   ierr = VecHYPRE_IJVectorPopVec(hjac->b);CHKERRQ(ierr);
449   PetscFunctionReturn(0);
450 }
451 
452 static PetscErrorCode PCReset_HYPRE(PC pc)
453 {
454   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
455   PetscErrorCode ierr;
456 
457   PetscFunctionBegin;
458   ierr = MatDestroy(&jac->hpmat);CHKERRQ(ierr);
459   ierr = MatDestroy(&jac->G);CHKERRQ(ierr);
460   ierr = MatDestroy(&jac->C);CHKERRQ(ierr);
461   ierr = MatDestroy(&jac->alpha_Poisson);CHKERRQ(ierr);
462   ierr = MatDestroy(&jac->beta_Poisson);CHKERRQ(ierr);
463   ierr = MatDestroy(&jac->RT_PiFull);CHKERRQ(ierr);
464   ierr = MatDestroy(&jac->RT_Pi[0]);CHKERRQ(ierr);
465   ierr = MatDestroy(&jac->RT_Pi[1]);CHKERRQ(ierr);
466   ierr = MatDestroy(&jac->RT_Pi[2]);CHKERRQ(ierr);
467   ierr = MatDestroy(&jac->ND_PiFull);CHKERRQ(ierr);
468   ierr = MatDestroy(&jac->ND_Pi[0]);CHKERRQ(ierr);
469   ierr = MatDestroy(&jac->ND_Pi[1]);CHKERRQ(ierr);
470   ierr = MatDestroy(&jac->ND_Pi[2]);CHKERRQ(ierr);
471   ierr = VecHYPRE_IJVectorDestroy(&jac->coords[0]);CHKERRQ(ierr);
472   ierr = VecHYPRE_IJVectorDestroy(&jac->coords[1]);CHKERRQ(ierr);
473   ierr = VecHYPRE_IJVectorDestroy(&jac->coords[2]);CHKERRQ(ierr);
474   ierr = VecHYPRE_IJVectorDestroy(&jac->constants[0]);CHKERRQ(ierr);
475   ierr = VecHYPRE_IJVectorDestroy(&jac->constants[1]);CHKERRQ(ierr);
476   ierr = VecHYPRE_IJVectorDestroy(&jac->constants[2]);CHKERRQ(ierr);
477   ierr = PCHYPREResetNearNullSpace_Private(pc);CHKERRQ(ierr);
478   jac->ams_beta_is_zero = PETSC_FALSE;
479   jac->dim = 0;
480   PetscFunctionReturn(0);
481 }
482 
483 static PetscErrorCode PCDestroy_HYPRE(PC pc)
484 {
485   PC_HYPRE                 *jac = (PC_HYPRE*)pc->data;
486   PetscErrorCode           ierr;
487 
488   PetscFunctionBegin;
489   ierr = PCReset_HYPRE(pc);CHKERRQ(ierr);
490   if (jac->destroy) PetscStackCallStandard(jac->destroy,(jac->hsolver));
491   ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr);
492   if (jac->comm_hypre != MPI_COMM_NULL) {ierr = MPI_Comm_free(&(jac->comm_hypre));CHKERRMPI(ierr);}
493   ierr = PetscFree(pc->data);CHKERRQ(ierr);
494 
495   ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr);
496   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C",NULL);CHKERRQ(ierr);
497   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C",NULL);CHKERRQ(ierr);
498   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetCoordinates_C",NULL);CHKERRQ(ierr);
499   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteGradient_C",NULL);CHKERRQ(ierr);
500   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteCurl_C",NULL);CHKERRQ(ierr);
501   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetInterpolations_C",NULL);CHKERRQ(ierr);
502   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetConstantEdgeVectors_C",NULL);CHKERRQ(ierr);
503   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetPoissonMatrix_C",NULL);CHKERRQ(ierr);
504   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",NULL);CHKERRQ(ierr);
505   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",NULL);CHKERRQ(ierr);
506   PetscFunctionReturn(0);
507 }
508 
509 /* --------------------------------------------------------------------------------------------*/
510 static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PetscOptionItems *PetscOptionsObject,PC pc)
511 {
512   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
513   PetscErrorCode ierr;
514   PetscBool      flag;
515 
516   PetscFunctionBegin;
517   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE Pilut Options");CHKERRQ(ierr);
518   ierr = PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);CHKERRQ(ierr);
519   if (flag) PetscStackCallStandard(HYPRE_ParCSRPilutSetMaxIter,(jac->hsolver,jac->maxiter));
520   ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr);
521   if (flag) PetscStackCallStandard(HYPRE_ParCSRPilutSetDropTolerance,(jac->hsolver,jac->tol));
522   ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr);
523   if (flag) PetscStackCallStandard(HYPRE_ParCSRPilutSetFactorRowSize,(jac->hsolver,jac->factorrowsize));
524   ierr = PetscOptionsTail();CHKERRQ(ierr);
525   PetscFunctionReturn(0);
526 }
527 
528 static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer)
529 {
530   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
531   PetscErrorCode ierr;
532   PetscBool      iascii;
533 
534   PetscFunctionBegin;
535   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
536   if (iascii) {
537     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Pilut preconditioning\n");CHKERRQ(ierr);
538     if (jac->maxiter != PETSC_DEFAULT) {
539       ierr = PetscViewerASCIIPrintf(viewer,"    maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr);
540     } else {
541       ierr = PetscViewerASCIIPrintf(viewer,"    default maximum number of iterations \n");CHKERRQ(ierr);
542     }
543     if (jac->tol != PETSC_DEFAULT) {
544       ierr = PetscViewerASCIIPrintf(viewer,"    drop tolerance %g\n",(double)jac->tol);CHKERRQ(ierr);
545     } else {
546       ierr = PetscViewerASCIIPrintf(viewer,"    default drop tolerance \n");CHKERRQ(ierr);
547     }
548     if (jac->factorrowsize != PETSC_DEFAULT) {
549       ierr = PetscViewerASCIIPrintf(viewer,"    factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr);
550     } else {
551       ierr = PetscViewerASCIIPrintf(viewer,"    default factor row size \n");CHKERRQ(ierr);
552     }
553   }
554   PetscFunctionReturn(0);
555 }
556 
557 /* --------------------------------------------------------------------------------------------*/
558 static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PetscOptionItems *PetscOptionsObject,PC pc)
559 {
560   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
561   PetscErrorCode ierr;
562   PetscBool      flag,eu_bj = jac->eu_bj ? PETSC_TRUE : PETSC_FALSE;
563 
564   PetscFunctionBegin;
565   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE Euclid Options");CHKERRQ(ierr);
566   ierr = PetscOptionsInt("-pc_hypre_euclid_level","Factorization levels","None",jac->eu_level,&jac->eu_level,&flag);CHKERRQ(ierr);
567   if (flag) PetscStackCallStandard(HYPRE_EuclidSetLevel,(jac->hsolver,jac->eu_level));
568 
569   ierr = PetscOptionsReal("-pc_hypre_euclid_droptolerance","Drop tolerance for ILU(k) in Euclid","None",jac->eu_droptolerance,&jac->eu_droptolerance,&flag);CHKERRQ(ierr);
570   if (flag) {
571     PetscMPIInt size;
572 
573     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
574     if (size > 1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"hypre's Euclid does not support a parallel drop tolerance");
575     PetscStackCallStandard(HYPRE_EuclidSetILUT,(jac->hsolver,jac->eu_droptolerance));
576   }
577 
578   ierr = PetscOptionsBool("-pc_hypre_euclid_bj", "Use Block Jacobi for ILU in Euclid", "None", eu_bj,&eu_bj,&flag);CHKERRQ(ierr);
579   if (flag) {
580     jac->eu_bj = eu_bj ? 1 : 0;
581     PetscStackCallStandard(HYPRE_EuclidSetBJ,(jac->hsolver,jac->eu_bj));
582   }
583   ierr = PetscOptionsTail();CHKERRQ(ierr);
584   PetscFunctionReturn(0);
585 }
586 
587 static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer)
588 {
589   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
590   PetscErrorCode ierr;
591   PetscBool      iascii;
592 
593   PetscFunctionBegin;
594   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
595   if (iascii) {
596     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE Euclid preconditioning\n");CHKERRQ(ierr);
597     if (jac->eu_level != PETSC_DEFAULT) {
598       ierr = PetscViewerASCIIPrintf(viewer,"    factorization levels %d\n",jac->eu_level);CHKERRQ(ierr);
599     } else {
600       ierr = PetscViewerASCIIPrintf(viewer,"    default factorization levels \n");CHKERRQ(ierr);
601     }
602     ierr = PetscViewerASCIIPrintf(viewer,"    drop tolerance %g\n",(double)jac->eu_droptolerance);CHKERRQ(ierr);
603     ierr = PetscViewerASCIIPrintf(viewer,"    use Block-Jacobi? %D\n",jac->eu_bj);CHKERRQ(ierr);
604   }
605   PetscFunctionReturn(0);
606 }
607 
608 /* --------------------------------------------------------------------------------------------*/
609 
610 static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x)
611 {
612   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
613   Mat_HYPRE          *hjac = (Mat_HYPRE*)(jac->hpmat->data);
614   PetscErrorCode     ierr;
615   HYPRE_ParCSRMatrix hmat;
616   HYPRE_ParVector    jbv,jxv;
617   PetscInt           hierr;
618 
619   PetscFunctionBegin;
620   ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
621   ierr = VecSet(x,0.0);CHKERRQ(ierr);
622   ierr = VecHYPRE_IJVectorPushVecRead(hjac->x,b);CHKERRQ(ierr);
623   ierr = VecHYPRE_IJVectorPushVecWrite(hjac->b,x);CHKERRQ(ierr);
624 
625   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hjac->ij,(void**)&hmat));
626   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hjac->b->ij,(void**)&jbv));
627   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hjac->x->ij,(void**)&jxv));
628 
629   hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jxv,jbv);
630   /* error code of 1 in BoomerAMG merely means convergence not achieved */
631   if (hierr && (hierr != 1)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr);
632   if (hierr) hypre__global_error = 0;
633 
634   ierr = VecHYPRE_IJVectorPopVec(hjac->x);CHKERRQ(ierr);
635   ierr = VecHYPRE_IJVectorPopVec(hjac->b);CHKERRQ(ierr);
636   PetscFunctionReturn(0);
637 }
638 
639 /* static array length */
640 #define ALEN(a) (sizeof(a)/sizeof((a)[0]))
641 
642 static const char *HYPREBoomerAMGCycleType[]   = {"","V","W"};
643 static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout", "", "PMIS", "", "HMIS"};
644 static const char *HYPREBoomerAMGMeasureType[] = {"local","global"};
645 /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */
646 static const char *HYPREBoomerAMGSmoothType[]  = {"Schwarz-smoothers","Pilut","ParaSails","Euclid"};
647 static const char *HYPREBoomerAMGRelaxType[]   = {"Jacobi","sequential-Gauss-Seidel","seqboundary-Gauss-Seidel","SOR/Jacobi","backward-SOR/Jacobi",
648                                                   "" /* [5] hybrid chaotic Gauss-Seidel (works only with OpenMP) */,"symmetric-SOR/Jacobi",
649                                                   "" /* 7 */,"l1scaled-SOR/Jacobi","Gaussian-elimination",
650                                                   "" /* 10 */, "" /* 11 */, "" /* 12 */, "l1-Gauss-Seidel" /* nonsymmetric */, "backward-l1-Gauss-Seidel" /* nonsymmetric */,
651                                                   "CG" /* non-stationary */,"Chebyshev","FCF-Jacobi","l1scaled-Jacobi"};
652 static const char *HYPREBoomerAMGInterpType[]  = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i",
653                                                   "ext+i-cc", "standard", "standard-wts", "block", "block-wtd", "FF", "FF1",
654                                                   "ext", "ad-wts", "ext-mm", "ext+i-mm", "ext+e-mm"};
655 static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PetscOptionItems *PetscOptionsObject,PC pc)
656 {
657   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
658   PetscErrorCode ierr;
659   PetscInt       bs,n,indx,level;
660   PetscBool      flg, tmp_truth;
661   double         tmpdbl, twodbl[2];
662   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
663 
664   PetscFunctionBegin;
665   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE BoomerAMG Options");CHKERRQ(ierr);
666   ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType+1,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr);
667   if (flg) {
668     jac->cycletype = indx+1;
669     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype));
670   }
671   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr);
672   if (flg) {
673     if (jac->maxlevels < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels);
674     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels));
675   }
676   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr);
677   if (flg) {
678     if (jac->maxiter < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter);
679     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter));
680   }
681   ierr = PetscOptionsReal("-pc_hypre_boomeramg_tol","Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)","None",jac->tol,&jac->tol,&flg);CHKERRQ(ierr);
682   if (flg) {
683     if (jac->tol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Tolerance %g must be greater than or equal to zero",(double)jac->tol);
684     PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol));
685   }
686   bs = 1;
687   if (pc->pmat) {
688     ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
689   }
690   ierr = PetscOptionsInt("-pc_hypre_boomeramg_numfunctions","Number of functions","HYPRE_BoomerAMGSetNumFunctions",bs,&bs,&flg);CHKERRQ(ierr);
691   if (flg) {
692     PetscStackCallStandard(HYPRE_BoomerAMGSetNumFunctions,(jac->hsolver,bs));
693   }
694 
695   ierr = PetscOptionsReal("-pc_hypre_boomeramg_truncfactor","Truncation factor for interpolation (0=no truncation)","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr);
696   if (flg) {
697     if (jac->truncfactor < 0.0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Truncation factor %g must be great than or equal zero",(double)jac->truncfactor);
698     PetscStackCallStandard(HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor));
699   }
700 
701   ierr = PetscOptionsInt("-pc_hypre_boomeramg_P_max","Max elements per row for interpolation operator (0=unlimited)","None",jac->pmax,&jac->pmax,&flg);CHKERRQ(ierr);
702   if (flg) {
703     if (jac->pmax < 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"P_max %D must be greater than or equal to zero",jac->pmax);
704     PetscStackCallStandard(HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax));
705   }
706 
707   ierr = PetscOptionsRangeInt("-pc_hypre_boomeramg_agg_nl","Number of levels of aggressive coarsening","None",jac->agg_nl,&jac->agg_nl,&flg,0,jac->maxlevels);CHKERRQ(ierr);
708   if (flg) PetscStackCallStandard(HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl));
709 
710   ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_num_paths","Number of paths for aggressive coarsening","None",jac->agg_num_paths,&jac->agg_num_paths,&flg);CHKERRQ(ierr);
711   if (flg) {
712     if (jac->agg_num_paths < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of paths %D must be greater than or equal to 1",jac->agg_num_paths);
713     PetscStackCallStandard(HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths));
714   }
715 
716   ierr = PetscOptionsReal("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr);
717   if (flg) {
718     if (jac->strongthreshold < 0.0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Strong threshold %g must be great than or equal zero",(double)jac->strongthreshold);
719     PetscStackCallStandard(HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold));
720   }
721   ierr = PetscOptionsReal("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr);
722   if (flg) {
723     if (jac->maxrowsum < 0.0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %g must be greater than zero",(double)jac->maxrowsum);
724     if (jac->maxrowsum > 1.0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %g must be less than or equal one",(double)jac->maxrowsum);
725     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum));
726   }
727 
728   /* Grid sweeps */
729   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_all","Number of sweeps for the up and down grid levels","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr);
730   if (flg) {
731     PetscStackCallStandard(HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver,indx));
732     /* modify the jac structure so we can view the updated options with PC_View */
733     jac->gridsweeps[0] = indx;
734     jac->gridsweeps[1] = indx;
735     /*defaults coarse to 1 */
736     jac->gridsweeps[2] = 1;
737   }
738   ierr = PetscOptionsInt("-pc_hypre_boomeramg_nodal_coarsen","Use a nodal based coarsening 1-6","HYPRE_BoomerAMGSetNodal",jac->nodal_coarsening,&jac->nodal_coarsening,&flg);CHKERRQ(ierr);
739   if (flg) {
740     PetscStackCallStandard(HYPRE_BoomerAMGSetNodal,(jac->hsolver,jac->nodal_coarsening));
741   }
742   ierr = 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);CHKERRQ(ierr);
743   if (flg) {
744     PetscStackCallStandard(HYPRE_BoomerAMGSetNodalDiag,(jac->hsolver,jac->nodal_coarsening_diag));
745   }
746   ierr = PetscOptionsInt("-pc_hypre_boomeramg_vec_interp_variant","Variant of algorithm 1-3","HYPRE_BoomerAMGSetInterpVecVariant",jac->vec_interp_variant, &jac->vec_interp_variant,&flg);CHKERRQ(ierr);
747   if (flg) {
748     PetscStackCallStandard(HYPRE_BoomerAMGSetInterpVecVariant,(jac->hsolver,jac->vec_interp_variant));
749   }
750   ierr = 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);CHKERRQ(ierr);
751   if (flg) {
752     PetscStackCallStandard(HYPRE_BoomerAMGSetInterpVecQMax,(jac->hsolver,jac->vec_interp_qmax));
753   }
754   ierr = PetscOptionsBool("-pc_hypre_boomeramg_vec_interp_smooth","Whether to smooth the interpolation vectors","HYPRE_BoomerAMGSetSmoothInterpVectors",jac->vec_interp_smooth, &jac->vec_interp_smooth,&flg);CHKERRQ(ierr);
755   if (flg) {
756     PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothInterpVectors,(jac->hsolver,jac->vec_interp_smooth));
757   }
758   ierr = PetscOptionsInt("-pc_hypre_boomeramg_interp_refine","Preprocess the interpolation matrix through iterative weight refinement","HYPRE_BoomerAMGSetInterpRefine",jac->interp_refine, &jac->interp_refine,&flg);CHKERRQ(ierr);
759   if (flg) {
760     PetscStackCallStandard(HYPRE_BoomerAMGSetInterpRefine,(jac->hsolver,jac->interp_refine));
761   }
762   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[0], &indx,&flg);CHKERRQ(ierr);
763   if (flg) {
764     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 1));
765     jac->gridsweeps[0] = indx;
766   }
767   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr);
768   if (flg) {
769     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 2));
770     jac->gridsweeps[1] = indx;
771   }
772   ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr);
773   if (flg) {
774     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 3));
775     jac->gridsweeps[2] = indx;
776   }
777 
778   /* Smooth type */
779   ierr = PetscOptionsEList("-pc_hypre_boomeramg_smooth_type","Enable more complex smoothers","None",HYPREBoomerAMGSmoothType,ALEN(HYPREBoomerAMGSmoothType),HYPREBoomerAMGSmoothType[0],&indx,&flg);CHKERRQ(ierr);
780   if (flg) {
781     jac->smoothtype = indx;
782     PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothType,(jac->hsolver,indx+6));
783     jac->smoothnumlevels = 25;
784     PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothNumLevels,(jac->hsolver,25));
785   }
786 
787   /* Number of smoothing levels */
788   ierr = PetscOptionsInt("-pc_hypre_boomeramg_smooth_num_levels","Number of levels on which more complex smoothers are used","None",25,&indx,&flg);CHKERRQ(ierr);
789   if (flg && (jac->smoothtype != -1)) {
790     jac->smoothnumlevels = indx;
791     PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothNumLevels,(jac->hsolver,indx));
792   }
793 
794   /* Number of levels for ILU(k) for Euclid */
795   ierr = PetscOptionsInt("-pc_hypre_boomeramg_eu_level","Number of levels for ILU(k) in Euclid smoother","None",0,&indx,&flg);CHKERRQ(ierr);
796   if (flg && (jac->smoothtype == 3)) {
797     jac->eu_level = indx;
798     PetscStackCallStandard(HYPRE_BoomerAMGSetEuLevel,(jac->hsolver,indx));
799   }
800 
801   /* Filter for ILU(k) for Euclid */
802   double droptolerance;
803   ierr = PetscOptionsReal("-pc_hypre_boomeramg_eu_droptolerance","Drop tolerance for ILU(k) in Euclid smoother","None",0,&droptolerance,&flg);CHKERRQ(ierr);
804   if (flg && (jac->smoothtype == 3)) {
805     jac->eu_droptolerance = droptolerance;
806     PetscStackCallStandard(HYPRE_BoomerAMGSetEuLevel,(jac->hsolver,droptolerance));
807   }
808 
809   /* Use Block Jacobi ILUT for Euclid */
810   ierr = PetscOptionsBool("-pc_hypre_boomeramg_eu_bj", "Use Block Jacobi for ILU in Euclid smoother?", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
811   if (flg && (jac->smoothtype == 3)) {
812     jac->eu_bj = tmp_truth;
813     PetscStackCallStandard(HYPRE_BoomerAMGSetEuBJ,(jac->hsolver,jac->eu_bj));
814   }
815 
816   /* Relax type */
817   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all","Relax type for the up and down cycles","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
818   if (flg) {
819     jac->relaxtype[0] = jac->relaxtype[1]  = indx;
820     PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, indx));
821     /* by default, coarse type set to 9 */
822     jac->relaxtype[2] = 9;
823     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, 9, 3));
824   }
825   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
826   if (flg) {
827     jac->relaxtype[0] = indx;
828     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 1));
829   }
830   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr);
831   if (flg) {
832     jac->relaxtype[1] = indx;
833     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 2));
834   }
835   ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr);
836   if (flg) {
837     jac->relaxtype[2] = indx;
838     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 3));
839   }
840 
841   /* Relaxation Weight */
842   ierr = 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);CHKERRQ(ierr);
843   if (flg) {
844     PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxWt,(jac->hsolver,tmpdbl));
845     jac->relaxweight = tmpdbl;
846   }
847 
848   n         = 2;
849   twodbl[0] = twodbl[1] = 1.0;
850   ierr      = PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr);
851   if (flg) {
852     if (n == 2) {
853       indx =  (int)PetscAbsReal(twodbl[1]);
854       PetscStackCallStandard(HYPRE_BoomerAMGSetLevelRelaxWt,(jac->hsolver,twodbl[0],indx));
855     } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %d",n);
856   }
857 
858   /* Outer relaxation Weight */
859   ierr = 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);CHKERRQ(ierr);
860   if (flg) {
861     PetscStackCallStandard(HYPRE_BoomerAMGSetOuterWt,(jac->hsolver, tmpdbl));
862     jac->outerrelaxweight = tmpdbl;
863   }
864 
865   n         = 2;
866   twodbl[0] = twodbl[1] = 1.0;
867   ierr      = PetscOptionsRealArray("-pc_hypre_boomeramg_outer_relax_weight_level","Set the outer relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr);
868   if (flg) {
869     if (n == 2) {
870       indx =  (int)PetscAbsReal(twodbl[1]);
871       PetscStackCallStandard(HYPRE_BoomerAMGSetLevelOuterWt,(jac->hsolver, twodbl[0], indx));
872     } else SETERRQ1(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 %d",n);
873   }
874 
875   /* the Relax Order */
876   ierr = PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
877 
878   if (flg && tmp_truth) {
879     jac->relaxorder = 0;
880     PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder));
881   }
882   ierr = PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,ALEN(HYPREBoomerAMGMeasureType),HYPREBoomerAMGMeasureType[0],&indx,&flg);CHKERRQ(ierr);
883   if (flg) {
884     jac->measuretype = indx;
885     PetscStackCallStandard(HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype));
886   }
887   /* update list length 3/07 */
888   ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,ALEN(HYPREBoomerAMGCoarsenType),HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr);
889   if (flg) {
890     jac->coarsentype = indx;
891     PetscStackCallStandard(HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype));
892   }
893 
894   ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_coarse_size", "Maximum size of coarsest grid", "None", jac->maxc, &jac->maxc, &flg);CHKERRQ(ierr);
895   if (flg) {
896     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxCoarseSize,(jac->hsolver, jac->maxc));
897   }
898   ierr = PetscOptionsInt("-pc_hypre_boomeramg_min_coarse_size", "Minimum size of coarsest grid", "None", jac->minc, &jac->minc, &flg);CHKERRQ(ierr);
899   if (flg) {
900     PetscStackCallStandard(HYPRE_BoomerAMGSetMinCoarseSize,(jac->hsolver, jac->minc));
901   }
902 
903   /* AIR */
904 #if PETSC_PKG_HYPRE_VERSION_GE(2,18,0)
905   ierr = PetscOptionsInt("-pc_hypre_boomeramg_restriction_type", "Type of AIR method (distance 1 or 2, 0 means no AIR)", "None", jac->Rtype, &jac->Rtype, NULL);CHKERRQ(ierr);
906   PetscStackCallStandard(HYPRE_BoomerAMGSetRestriction,(jac->hsolver,jac->Rtype));
907   if (jac->Rtype) {
908     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 */
909 
910     ierr = PetscOptionsReal("-pc_hypre_boomeramg_strongthresholdR","Threshold for R","None",jac->Rstrongthreshold,&jac->Rstrongthreshold,NULL);CHKERRQ(ierr);
911     PetscStackCallStandard(HYPRE_BoomerAMGSetStrongThresholdR,(jac->hsolver,jac->Rstrongthreshold));
912 
913     ierr = PetscOptionsReal("-pc_hypre_boomeramg_filterthresholdR","Filter threshold for R","None",jac->Rfilterthreshold,&jac->Rfilterthreshold,NULL);CHKERRQ(ierr);
914     PetscStackCallStandard(HYPRE_BoomerAMGSetFilterThresholdR,(jac->hsolver,jac->Rfilterthreshold));
915 
916     ierr = 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);CHKERRQ(ierr);
917     PetscStackCallStandard(HYPRE_BoomerAMGSetADropTol,(jac->hsolver,jac->Adroptol));
918 
919     ierr = 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);CHKERRQ(ierr);
920     PetscStackCallStandard(HYPRE_BoomerAMGSetADropType,(jac->hsolver,jac->Adroptype));
921   }
922 #endif
923 
924 #if PETSC_PKG_HYPRE_VERSION_LE(9,9,9)
925   if (jac->Rtype && jac->agg_nl) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"-pc_hypre_boomeramg_restriction_type (%D) and -pc_hypre_boomeramg_agg_nl (%D)",jac->Rtype,jac->agg_nl);
926 #endif
927 
928   /* new 3/07 */
929   ierr = PetscOptionsEList("-pc_hypre_boomeramg_interp_type","Interpolation type","None",HYPREBoomerAMGInterpType,ALEN(HYPREBoomerAMGInterpType),HYPREBoomerAMGInterpType[0],&indx,&flg);CHKERRQ(ierr);
930   if (flg || jac->Rtype) {
931     if (flg) jac->interptype = indx;
932     PetscStackCallStandard(HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype));
933   }
934 
935   ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr);
936   if (flg) {
937     level = 3;
938     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,NULL);CHKERRQ(ierr);
939 
940     jac->printstatistics = PETSC_TRUE;
941     PetscStackCallStandard(HYPRE_BoomerAMGSetPrintLevel,(jac->hsolver,level));
942   }
943 
944   ierr = PetscOptionsName("-pc_hypre_boomeramg_print_debug","Print debug information","None",&flg);CHKERRQ(ierr);
945   if (flg) {
946     level = 3;
947     ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_debug","Print debug information","None",level,&level,NULL);CHKERRQ(ierr);
948 
949     jac->printstatistics = PETSC_TRUE;
950     PetscStackCallStandard(HYPRE_BoomerAMGSetDebugFlag,(jac->hsolver,level));
951   }
952 
953   ierr = PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr);
954   if (flg && tmp_truth) {
955     PetscInt tmp_int;
956     ierr = PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg);CHKERRQ(ierr);
957     if (flg) jac->nodal_relax_levels = tmp_int;
958     PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothType,(jac->hsolver,6));
959     PetscStackCallStandard(HYPRE_BoomerAMGSetDomainType,(jac->hsolver,1));
960     PetscStackCallStandard(HYPRE_BoomerAMGSetOverlap,(jac->hsolver,0));
961     PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothNumLevels,(jac->hsolver,jac->nodal_relax_levels));
962   }
963 
964   ierr = PetscOptionsBool("-pc_hypre_boomeramg_keeptranspose", "Avoid transpose matvecs in preconditioner application", "None", jac->keeptranspose, &jac->keeptranspose, NULL);CHKERRQ(ierr);
965   PetscStackCallStandard(HYPRE_BoomerAMGSetKeepTranspose,(jac->hsolver,jac->keeptranspose ? 1 : 0));
966 
967   /* options for ParaSails solvers */
968   ierr = PetscOptionsEList("-pc_hypre_boomeramg_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,ALEN(symtlist),symtlist[0],&indx,&flg);CHKERRQ(ierr);
969   if (flg) {
970     jac->symt = indx;
971     PetscStackCallStandard(HYPRE_BoomerAMGSetSym,(jac->hsolver,jac->symt));
972   }
973 
974   ierr = PetscOptionsTail();CHKERRQ(ierr);
975   PetscFunctionReturn(0);
976 }
977 
978 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)
979 {
980   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
981   PetscErrorCode ierr;
982   HYPRE_Int      oits;
983 
984   PetscFunctionBegin;
985   ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
986   PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,its*jac->maxiter));
987   PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,rtol));
988   jac->applyrichardson = PETSC_TRUE;
989   ierr                 = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr);
990   jac->applyrichardson = PETSC_FALSE;
991   PetscStackCallStandard(HYPRE_BoomerAMGGetNumIterations,(jac->hsolver,&oits));
992   *outits = oits;
993   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
994   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
995   PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol));
996   PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter));
997   PetscFunctionReturn(0);
998 }
999 
1000 static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer)
1001 {
1002   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1003   PetscErrorCode ierr;
1004   PetscBool      iascii;
1005 
1006   PetscFunctionBegin;
1007   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1008   if (iascii) {
1009     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr);
1010     ierr = PetscViewerASCIIPrintf(viewer,"    Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr);
1011     ierr = PetscViewerASCIIPrintf(viewer,"    Maximum number of levels %D\n",jac->maxlevels);CHKERRQ(ierr);
1012     ierr = PetscViewerASCIIPrintf(viewer,"    Maximum number of iterations PER hypre call %D\n",jac->maxiter);CHKERRQ(ierr);
1013     ierr = PetscViewerASCIIPrintf(viewer,"    Convergence tolerance PER hypre call %g\n",(double)jac->tol);CHKERRQ(ierr);
1014     ierr = PetscViewerASCIIPrintf(viewer,"    Threshold for strong coupling %g\n",(double)jac->strongthreshold);CHKERRQ(ierr);
1015     ierr = PetscViewerASCIIPrintf(viewer,"    Interpolation truncation factor %g\n",(double)jac->truncfactor);CHKERRQ(ierr);
1016     ierr = PetscViewerASCIIPrintf(viewer,"    Interpolation: max elements per row %D\n",jac->pmax);CHKERRQ(ierr);
1017     if (jac->interp_refine) {
1018       ierr = PetscViewerASCIIPrintf(viewer,"    Interpolation: number of steps of weighted refinement %D\n",jac->interp_refine);CHKERRQ(ierr);
1019     }
1020     ierr = PetscViewerASCIIPrintf(viewer,"    Number of levels of aggressive coarsening %D\n",jac->agg_nl);CHKERRQ(ierr);
1021     ierr = PetscViewerASCIIPrintf(viewer,"    Number of paths for aggressive coarsening %D\n",jac->agg_num_paths);CHKERRQ(ierr);
1022 
1023     ierr = PetscViewerASCIIPrintf(viewer,"    Maximum row sums %g\n",(double)jac->maxrowsum);CHKERRQ(ierr);
1024 
1025     ierr = PetscViewerASCIIPrintf(viewer,"    Sweeps down         %D\n",jac->gridsweeps[0]);CHKERRQ(ierr);
1026     ierr = PetscViewerASCIIPrintf(viewer,"    Sweeps up           %D\n",jac->gridsweeps[1]);CHKERRQ(ierr);
1027     ierr = PetscViewerASCIIPrintf(viewer,"    Sweeps on coarse    %D\n",jac->gridsweeps[2]);CHKERRQ(ierr);
1028 
1029     ierr = PetscViewerASCIIPrintf(viewer,"    Relax down          %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr);
1030     ierr = PetscViewerASCIIPrintf(viewer,"    Relax up            %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr);
1031     ierr = PetscViewerASCIIPrintf(viewer,"    Relax on coarse     %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr);
1032 
1033     ierr = PetscViewerASCIIPrintf(viewer,"    Relax weight  (all)      %g\n",(double)jac->relaxweight);CHKERRQ(ierr);
1034     ierr = PetscViewerASCIIPrintf(viewer,"    Outer relax weight (all) %g\n",(double)jac->outerrelaxweight);CHKERRQ(ierr);
1035 
1036     if (jac->relaxorder) {
1037       ierr = PetscViewerASCIIPrintf(viewer,"    Using CF-relaxation\n");CHKERRQ(ierr);
1038     } else {
1039       ierr = PetscViewerASCIIPrintf(viewer,"    Not using CF-relaxation\n");CHKERRQ(ierr);
1040     }
1041     if (jac->smoothtype!=-1) {
1042       ierr = PetscViewerASCIIPrintf(viewer,"    Smooth type          %s\n",HYPREBoomerAMGSmoothType[jac->smoothtype]);CHKERRQ(ierr);
1043       ierr = PetscViewerASCIIPrintf(viewer,"    Smooth num levels    %D\n",jac->smoothnumlevels);CHKERRQ(ierr);
1044     } else {
1045       ierr = PetscViewerASCIIPrintf(viewer,"    Not using more complex smoothers.\n");CHKERRQ(ierr);
1046     }
1047     if (jac->smoothtype==3) {
1048       ierr = PetscViewerASCIIPrintf(viewer,"    Euclid ILU(k) levels %D\n",jac->eu_level);CHKERRQ(ierr);
1049       ierr = PetscViewerASCIIPrintf(viewer,"    Euclid ILU(k) drop tolerance %g\n",(double)jac->eu_droptolerance);CHKERRQ(ierr);
1050       ierr = PetscViewerASCIIPrintf(viewer,"    Euclid ILU use Block-Jacobi? %D\n",jac->eu_bj);CHKERRQ(ierr);
1051     }
1052     ierr = PetscViewerASCIIPrintf(viewer,"    Measure type        %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr);
1053     ierr = PetscViewerASCIIPrintf(viewer,"    Coarsen type        %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr);
1054     ierr = PetscViewerASCIIPrintf(viewer,"    Interpolation type  %s\n",jac->interptype != 100 ? HYPREBoomerAMGInterpType[jac->interptype] : "1pt");CHKERRQ(ierr);
1055     if (jac->nodal_coarsening) {
1056       ierr = PetscViewerASCIIPrintf(viewer,"    Using nodal coarsening with HYPRE_BOOMERAMGSetNodal() %D\n",jac->nodal_coarsening);CHKERRQ(ierr);
1057     }
1058     if (jac->vec_interp_variant) {
1059       ierr = PetscViewerASCIIPrintf(viewer,"    HYPRE_BoomerAMGSetInterpVecVariant() %D\n",jac->vec_interp_variant);CHKERRQ(ierr);
1060       ierr = PetscViewerASCIIPrintf(viewer,"    HYPRE_BoomerAMGSetInterpVecQMax() %D\n",jac->vec_interp_qmax);CHKERRQ(ierr);
1061       ierr = PetscViewerASCIIPrintf(viewer,"    HYPRE_BoomerAMGSetSmoothInterpVectors() %d\n",jac->vec_interp_smooth);CHKERRQ(ierr);
1062     }
1063     if (jac->nodal_relax) {
1064       ierr = PetscViewerASCIIPrintf(viewer,"    Using nodal relaxation via Schwarz smoothing on levels %D\n",jac->nodal_relax_levels);CHKERRQ(ierr);
1065     }
1066 
1067     /* AIR */
1068     if (jac->Rtype) {
1069       ierr = PetscViewerASCIIPrintf(viewer,"    Using approximate ideal restriction type %D\n",jac->Rtype);CHKERRQ(ierr);
1070       ierr = PetscViewerASCIIPrintf(viewer,"      Threshold for R %g\n",(double)jac->Rstrongthreshold);CHKERRQ(ierr);
1071       ierr = PetscViewerASCIIPrintf(viewer,"      Filter for R %g\n",(double)jac->Rfilterthreshold);CHKERRQ(ierr);
1072       ierr = PetscViewerASCIIPrintf(viewer,"      A drop tolerance %g\n",(double)jac->Adroptol);CHKERRQ(ierr);
1073       ierr = PetscViewerASCIIPrintf(viewer,"      A drop type %D\n",jac->Adroptype);CHKERRQ(ierr);
1074     }
1075   }
1076   PetscFunctionReturn(0);
1077 }
1078 
1079 /* --------------------------------------------------------------------------------------------*/
1080 static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PetscOptionItems *PetscOptionsObject,PC pc)
1081 {
1082   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1083   PetscErrorCode ierr;
1084   PetscInt       indx;
1085   PetscBool      flag;
1086   const char     *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"};
1087 
1088   PetscFunctionBegin;
1089   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE ParaSails Options");CHKERRQ(ierr);
1090   ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr);
1091   ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshold,&jac->threshold,&flag);CHKERRQ(ierr);
1092   if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshold,jac->nlevels));
1093 
1094   ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr);
1095   if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter));
1096 
1097   ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr);
1098   if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal));
1099 
1100   ierr = PetscOptionsBool("-pc_hypre_parasails_logging","Print info to screen","None",(PetscBool)jac->logging,(PetscBool*)&jac->logging,&flag);CHKERRQ(ierr);
1101   if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging));
1102 
1103   ierr = PetscOptionsBool("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscBool)jac->ruse,(PetscBool*)&jac->ruse,&flag);CHKERRQ(ierr);
1104   if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse));
1105 
1106   ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,ALEN(symtlist),symtlist[0],&indx,&flag);CHKERRQ(ierr);
1107   if (flag) {
1108     jac->symt = indx;
1109     PetscStackCallStandard(HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt));
1110   }
1111 
1112   ierr = PetscOptionsTail();CHKERRQ(ierr);
1113   PetscFunctionReturn(0);
1114 }
1115 
1116 static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer)
1117 {
1118   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1119   PetscErrorCode ierr;
1120   PetscBool      iascii;
1121   const char     *symt = 0;
1122 
1123   PetscFunctionBegin;
1124   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1125   if (iascii) {
1126     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ParaSails preconditioning\n");CHKERRQ(ierr);
1127     ierr = PetscViewerASCIIPrintf(viewer,"    nlevels %d\n",jac->nlevels);CHKERRQ(ierr);
1128     ierr = PetscViewerASCIIPrintf(viewer,"    threshold %g\n",(double)jac->threshold);CHKERRQ(ierr);
1129     ierr = PetscViewerASCIIPrintf(viewer,"    filter %g\n",(double)jac->filter);CHKERRQ(ierr);
1130     ierr = PetscViewerASCIIPrintf(viewer,"    load balance %g\n",(double)jac->loadbal);CHKERRQ(ierr);
1131     ierr = PetscViewerASCIIPrintf(viewer,"    reuse nonzero structure %s\n",PetscBools[jac->ruse]);CHKERRQ(ierr);
1132     ierr = PetscViewerASCIIPrintf(viewer,"    print info to screen %s\n",PetscBools[jac->logging]);CHKERRQ(ierr);
1133     if (!jac->symt) symt = "nonsymmetric matrix and preconditioner";
1134     else if (jac->symt == 1) symt = "SPD matrix and preconditioner";
1135     else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner";
1136     else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt);
1137     ierr = PetscViewerASCIIPrintf(viewer,"    %s\n",symt);CHKERRQ(ierr);
1138   }
1139   PetscFunctionReturn(0);
1140 }
1141 /* --------------------------------------------------------------------------------------------*/
1142 static PetscErrorCode PCSetFromOptions_HYPRE_AMS(PetscOptionItems *PetscOptionsObject,PC pc)
1143 {
1144   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1145   PetscErrorCode ierr;
1146   PetscInt       n;
1147   PetscBool      flag,flag2,flag3,flag4;
1148 
1149   PetscFunctionBegin;
1150   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE AMS Options");CHKERRQ(ierr);
1151   ierr = PetscOptionsInt("-pc_hypre_ams_print_level","Debugging output level for AMS","None",jac->as_print,&jac->as_print,&flag);CHKERRQ(ierr);
1152   if (flag) PetscStackCallStandard(HYPRE_AMSSetPrintLevel,(jac->hsolver,jac->as_print));
1153   ierr = PetscOptionsInt("-pc_hypre_ams_max_iter","Maximum number of AMS multigrid iterations within PCApply","None",jac->as_max_iter,&jac->as_max_iter,&flag);CHKERRQ(ierr);
1154   if (flag) PetscStackCallStandard(HYPRE_AMSSetMaxIter,(jac->hsolver,jac->as_max_iter));
1155   ierr = PetscOptionsInt("-pc_hypre_ams_cycle_type","Cycle type for AMS multigrid","None",jac->ams_cycle_type,&jac->ams_cycle_type,&flag);CHKERRQ(ierr);
1156   if (flag) PetscStackCallStandard(HYPRE_AMSSetCycleType,(jac->hsolver,jac->ams_cycle_type));
1157   ierr = PetscOptionsReal("-pc_hypre_ams_tol","Error tolerance for AMS multigrid","None",jac->as_tol,&jac->as_tol,&flag);CHKERRQ(ierr);
1158   if (flag) PetscStackCallStandard(HYPRE_AMSSetTol,(jac->hsolver,jac->as_tol));
1159   ierr = PetscOptionsInt("-pc_hypre_ams_relax_type","Relaxation type for AMS smoother","None",jac->as_relax_type,&jac->as_relax_type,&flag);CHKERRQ(ierr);
1160   ierr = PetscOptionsInt("-pc_hypre_ams_relax_times","Number of relaxation steps for AMS smoother","None",jac->as_relax_times,&jac->as_relax_times,&flag2);CHKERRQ(ierr);
1161   ierr = PetscOptionsReal("-pc_hypre_ams_relax_weight","Relaxation weight for AMS smoother","None",jac->as_relax_weight,&jac->as_relax_weight,&flag3);CHKERRQ(ierr);
1162   ierr = PetscOptionsReal("-pc_hypre_ams_omega","SSOR coefficient for AMS smoother","None",jac->as_omega,&jac->as_omega,&flag4);CHKERRQ(ierr);
1163   if (flag || flag2 || flag3 || flag4) {
1164     PetscStackCallStandard(HYPRE_AMSSetSmoothingOptions,(jac->hsolver,jac->as_relax_type,
1165                                                                       jac->as_relax_times,
1166                                                                       jac->as_relax_weight,
1167                                                                       jac->as_omega));
1168   }
1169   ierr = 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);CHKERRQ(ierr);
1170   n = 5;
1171   ierr = PetscOptionsIntArray("-pc_hypre_ams_amg_alpha_options","AMG options for vector Poisson","None",jac->as_amg_alpha_opts,&n,&flag2);CHKERRQ(ierr);
1172   if (flag || flag2) {
1173     PetscStackCallStandard(HYPRE_AMSSetAlphaAMGOptions,(jac->hsolver,jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
1174                                                                      jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
1175                                                                      jac->as_amg_alpha_opts[2],       /* AMG relax_type */
1176                                                                      jac->as_amg_alpha_theta,
1177                                                                      jac->as_amg_alpha_opts[3],       /* AMG interp_type */
1178                                                                      jac->as_amg_alpha_opts[4]));     /* AMG Pmax */
1179   }
1180   ierr = 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);CHKERRQ(ierr);
1181   n = 5;
1182   ierr = PetscOptionsIntArray("-pc_hypre_ams_amg_beta_options","AMG options for scalar Poisson solver","None",jac->as_amg_beta_opts,&n,&flag2);CHKERRQ(ierr);
1183   if (flag || flag2) {
1184     PetscStackCallStandard(HYPRE_AMSSetBetaAMGOptions,(jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
1185                                                                     jac->as_amg_beta_opts[1],       /* AMG agg_levels */
1186                                                                     jac->as_amg_beta_opts[2],       /* AMG relax_type */
1187                                                                     jac->as_amg_beta_theta,
1188                                                                     jac->as_amg_beta_opts[3],       /* AMG interp_type */
1189                                                                     jac->as_amg_beta_opts[4]));     /* AMG Pmax */
1190   }
1191   ierr = 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);CHKERRQ(ierr);
1192   if (flag) { /* override HYPRE's default only if the options is used */
1193     PetscStackCallStandard(HYPRE_AMSSetProjectionFrequency,(jac->hsolver,jac->ams_proj_freq));
1194   }
1195   ierr = PetscOptionsTail();CHKERRQ(ierr);
1196   PetscFunctionReturn(0);
1197 }
1198 
1199 static PetscErrorCode PCView_HYPRE_AMS(PC pc,PetscViewer viewer)
1200 {
1201   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1202   PetscErrorCode ierr;
1203   PetscBool      iascii;
1204 
1205   PetscFunctionBegin;
1206   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1207   if (iascii) {
1208     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE AMS preconditioning\n");CHKERRQ(ierr);
1209     ierr = PetscViewerASCIIPrintf(viewer,"    subspace iterations per application %d\n",jac->as_max_iter);CHKERRQ(ierr);
1210     ierr = PetscViewerASCIIPrintf(viewer,"    subspace cycle type %d\n",jac->ams_cycle_type);CHKERRQ(ierr);
1211     ierr = PetscViewerASCIIPrintf(viewer,"    subspace iteration tolerance %g\n",jac->as_tol);CHKERRQ(ierr);
1212     ierr = PetscViewerASCIIPrintf(viewer,"    smoother type %d\n",jac->as_relax_type);CHKERRQ(ierr);
1213     ierr = PetscViewerASCIIPrintf(viewer,"    number of smoothing steps %d\n",jac->as_relax_times);CHKERRQ(ierr);
1214     ierr = PetscViewerASCIIPrintf(viewer,"    smoother weight %g\n",jac->as_relax_weight);CHKERRQ(ierr);
1215     ierr = PetscViewerASCIIPrintf(viewer,"    smoother omega %g\n",jac->as_omega);CHKERRQ(ierr);
1216     if (jac->alpha_Poisson) {
1217       ierr = PetscViewerASCIIPrintf(viewer,"    vector Poisson solver (passed in by user)\n");CHKERRQ(ierr);
1218     } else {
1219       ierr = PetscViewerASCIIPrintf(viewer,"    vector Poisson solver (computed) \n");CHKERRQ(ierr);
1220     }
1221     ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG coarsening type %d\n",jac->as_amg_alpha_opts[0]);CHKERRQ(ierr);
1222     ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG levels of aggressive coarsening %d\n",jac->as_amg_alpha_opts[1]);CHKERRQ(ierr);
1223     ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG relaxation type %d\n",jac->as_amg_alpha_opts[2]);CHKERRQ(ierr);
1224     ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG interpolation type %d\n",jac->as_amg_alpha_opts[3]);CHKERRQ(ierr);
1225     ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG max nonzero elements in interpolation rows %d\n",jac->as_amg_alpha_opts[4]);CHKERRQ(ierr);
1226     ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG strength threshold %g\n",jac->as_amg_alpha_theta);CHKERRQ(ierr);
1227     if (!jac->ams_beta_is_zero) {
1228       if (jac->beta_Poisson) {
1229         ierr = PetscViewerASCIIPrintf(viewer,"    scalar Poisson solver (passed in by user)\n");CHKERRQ(ierr);
1230       } else {
1231         ierr = PetscViewerASCIIPrintf(viewer,"    scalar Poisson solver (computed) \n");CHKERRQ(ierr);
1232       }
1233       ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG coarsening type %d\n",jac->as_amg_beta_opts[0]);CHKERRQ(ierr);
1234       ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG levels of aggressive coarsening %d\n",jac->as_amg_beta_opts[1]);CHKERRQ(ierr);
1235       ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG relaxation type %d\n",jac->as_amg_beta_opts[2]);CHKERRQ(ierr);
1236       ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG interpolation type %d\n",jac->as_amg_beta_opts[3]);CHKERRQ(ierr);
1237       ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG max nonzero elements in interpolation rows %d\n",jac->as_amg_beta_opts[4]);CHKERRQ(ierr);
1238       ierr = PetscViewerASCIIPrintf(viewer,"        boomerAMG strength threshold %g\n",jac->as_amg_beta_theta);CHKERRQ(ierr);
1239       if (jac->ams_beta_is_zero_part) {
1240         ierr = PetscViewerASCIIPrintf(viewer,"        compatible subspace projection frequency %d (-1 HYPRE uses default)\n",jac->ams_proj_freq);CHKERRQ(ierr);
1241       }
1242     } else {
1243       ierr = PetscViewerASCIIPrintf(viewer,"    scalar Poisson solver not used (zero-conductivity everywhere) \n");CHKERRQ(ierr);
1244     }
1245   }
1246   PetscFunctionReturn(0);
1247 }
1248 
1249 static PetscErrorCode PCSetFromOptions_HYPRE_ADS(PetscOptionItems *PetscOptionsObject,PC pc)
1250 {
1251   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1252   PetscErrorCode ierr;
1253   PetscInt       n;
1254   PetscBool      flag,flag2,flag3,flag4;
1255 
1256   PetscFunctionBegin;
1257   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE ADS Options");CHKERRQ(ierr);
1258   ierr = PetscOptionsInt("-pc_hypre_ads_print_level","Debugging output level for ADS","None",jac->as_print,&jac->as_print,&flag);CHKERRQ(ierr);
1259   if (flag) PetscStackCallStandard(HYPRE_ADSSetPrintLevel,(jac->hsolver,jac->as_print));
1260   ierr = PetscOptionsInt("-pc_hypre_ads_max_iter","Maximum number of ADS multigrid iterations within PCApply","None",jac->as_max_iter,&jac->as_max_iter,&flag);CHKERRQ(ierr);
1261   if (flag) PetscStackCallStandard(HYPRE_ADSSetMaxIter,(jac->hsolver,jac->as_max_iter));
1262   ierr = PetscOptionsInt("-pc_hypre_ads_cycle_type","Cycle type for ADS multigrid","None",jac->ads_cycle_type,&jac->ads_cycle_type,&flag);CHKERRQ(ierr);
1263   if (flag) PetscStackCallStandard(HYPRE_ADSSetCycleType,(jac->hsolver,jac->ads_cycle_type));
1264   ierr = PetscOptionsReal("-pc_hypre_ads_tol","Error tolerance for ADS multigrid","None",jac->as_tol,&jac->as_tol,&flag);CHKERRQ(ierr);
1265   if (flag) PetscStackCallStandard(HYPRE_ADSSetTol,(jac->hsolver,jac->as_tol));
1266   ierr = PetscOptionsInt("-pc_hypre_ads_relax_type","Relaxation type for ADS smoother","None",jac->as_relax_type,&jac->as_relax_type,&flag);CHKERRQ(ierr);
1267   ierr = PetscOptionsInt("-pc_hypre_ads_relax_times","Number of relaxation steps for ADS smoother","None",jac->as_relax_times,&jac->as_relax_times,&flag2);CHKERRQ(ierr);
1268   ierr = PetscOptionsReal("-pc_hypre_ads_relax_weight","Relaxation weight for ADS smoother","None",jac->as_relax_weight,&jac->as_relax_weight,&flag3);CHKERRQ(ierr);
1269   ierr = PetscOptionsReal("-pc_hypre_ads_omega","SSOR coefficient for ADS smoother","None",jac->as_omega,&jac->as_omega,&flag4);CHKERRQ(ierr);
1270   if (flag || flag2 || flag3 || flag4) {
1271     PetscStackCallStandard(HYPRE_ADSSetSmoothingOptions,(jac->hsolver,jac->as_relax_type,
1272                                                                       jac->as_relax_times,
1273                                                                       jac->as_relax_weight,
1274                                                                       jac->as_omega));
1275   }
1276   ierr = 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);CHKERRQ(ierr);
1277   n = 5;
1278   ierr = PetscOptionsIntArray("-pc_hypre_ads_ams_options","AMG options for AMS solver inside ADS","None",jac->as_amg_alpha_opts,&n,&flag2);CHKERRQ(ierr);
1279   ierr = PetscOptionsInt("-pc_hypre_ads_ams_cycle_type","Cycle type for AMS solver inside ADS","None",jac->ams_cycle_type,&jac->ams_cycle_type,&flag3);CHKERRQ(ierr);
1280   if (flag || flag2 || flag3) {
1281     PetscStackCallStandard(HYPRE_ADSSetAMSOptions,(jac->hsolver,jac->ams_cycle_type,             /* AMS cycle type */
1282                                                                 jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
1283                                                                 jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
1284                                                                 jac->as_amg_alpha_opts[2],       /* AMG relax_type */
1285                                                                 jac->as_amg_alpha_theta,
1286                                                                 jac->as_amg_alpha_opts[3],       /* AMG interp_type */
1287                                                                 jac->as_amg_alpha_opts[4]));     /* AMG Pmax */
1288   }
1289   ierr = 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);CHKERRQ(ierr);
1290   n = 5;
1291   ierr = PetscOptionsIntArray("-pc_hypre_ads_amg_options","AMG options for vector AMG solver inside ADS","None",jac->as_amg_beta_opts,&n,&flag2);CHKERRQ(ierr);
1292   if (flag || flag2) {
1293     PetscStackCallStandard(HYPRE_ADSSetAMGOptions,(jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
1294                                                                 jac->as_amg_beta_opts[1],       /* AMG agg_levels */
1295                                                                 jac->as_amg_beta_opts[2],       /* AMG relax_type */
1296                                                                 jac->as_amg_beta_theta,
1297                                                                 jac->as_amg_beta_opts[3],       /* AMG interp_type */
1298                                                                 jac->as_amg_beta_opts[4]));     /* AMG Pmax */
1299   }
1300   ierr = PetscOptionsTail();CHKERRQ(ierr);
1301   PetscFunctionReturn(0);
1302 }
1303 
1304 static PetscErrorCode PCView_HYPRE_ADS(PC pc,PetscViewer viewer)
1305 {
1306   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1307   PetscErrorCode ierr;
1308   PetscBool      iascii;
1309 
1310   PetscFunctionBegin;
1311   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1312   if (iascii) {
1313     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE ADS preconditioning\n");CHKERRQ(ierr);
1314     ierr = PetscViewerASCIIPrintf(viewer,"    subspace iterations per application %d\n",jac->as_max_iter);CHKERRQ(ierr);
1315     ierr = PetscViewerASCIIPrintf(viewer,"    subspace cycle type %d\n",jac->ads_cycle_type);CHKERRQ(ierr);
1316     ierr = PetscViewerASCIIPrintf(viewer,"    subspace iteration tolerance %g\n",jac->as_tol);CHKERRQ(ierr);
1317     ierr = PetscViewerASCIIPrintf(viewer,"    smoother type %d\n",jac->as_relax_type);CHKERRQ(ierr);
1318     ierr = PetscViewerASCIIPrintf(viewer,"    number of smoothing steps %d\n",jac->as_relax_times);CHKERRQ(ierr);
1319     ierr = PetscViewerASCIIPrintf(viewer,"    smoother weight %g\n",jac->as_relax_weight);CHKERRQ(ierr);
1320     ierr = PetscViewerASCIIPrintf(viewer,"    smoother omega %g\n",jac->as_omega);CHKERRQ(ierr);
1321     ierr = PetscViewerASCIIPrintf(viewer,"    AMS solver using boomerAMG\n");CHKERRQ(ierr);
1322     ierr = PetscViewerASCIIPrintf(viewer,"        subspace cycle type %d\n",jac->ams_cycle_type);CHKERRQ(ierr);
1323     ierr = PetscViewerASCIIPrintf(viewer,"        coarsening type %d\n",jac->as_amg_alpha_opts[0]);CHKERRQ(ierr);
1324     ierr = PetscViewerASCIIPrintf(viewer,"        levels of aggressive coarsening %d\n",jac->as_amg_alpha_opts[1]);CHKERRQ(ierr);
1325     ierr = PetscViewerASCIIPrintf(viewer,"        relaxation type %d\n",jac->as_amg_alpha_opts[2]);CHKERRQ(ierr);
1326     ierr = PetscViewerASCIIPrintf(viewer,"        interpolation type %d\n",jac->as_amg_alpha_opts[3]);CHKERRQ(ierr);
1327     ierr = PetscViewerASCIIPrintf(viewer,"        max nonzero elements in interpolation rows %d\n",jac->as_amg_alpha_opts[4]);CHKERRQ(ierr);
1328     ierr = PetscViewerASCIIPrintf(viewer,"        strength threshold %g\n",jac->as_amg_alpha_theta);CHKERRQ(ierr);
1329     ierr = PetscViewerASCIIPrintf(viewer,"    vector Poisson solver using boomerAMG\n");CHKERRQ(ierr);
1330     ierr = PetscViewerASCIIPrintf(viewer,"        coarsening type %d\n",jac->as_amg_beta_opts[0]);CHKERRQ(ierr);
1331     ierr = PetscViewerASCIIPrintf(viewer,"        levels of aggressive coarsening %d\n",jac->as_amg_beta_opts[1]);CHKERRQ(ierr);
1332     ierr = PetscViewerASCIIPrintf(viewer,"        relaxation type %d\n",jac->as_amg_beta_opts[2]);CHKERRQ(ierr);
1333     ierr = PetscViewerASCIIPrintf(viewer,"        interpolation type %d\n",jac->as_amg_beta_opts[3]);CHKERRQ(ierr);
1334     ierr = PetscViewerASCIIPrintf(viewer,"        max nonzero elements in interpolation rows %d\n",jac->as_amg_beta_opts[4]);CHKERRQ(ierr);
1335     ierr = PetscViewerASCIIPrintf(viewer,"        strength threshold %g\n",jac->as_amg_beta_theta);CHKERRQ(ierr);
1336   }
1337   PetscFunctionReturn(0);
1338 }
1339 
1340 static PetscErrorCode PCHYPRESetDiscreteGradient_HYPRE(PC pc, Mat G)
1341 {
1342   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1343   PetscBool      ishypre;
1344   PetscErrorCode ierr;
1345 
1346   PetscFunctionBegin;
1347   ierr = PetscObjectTypeCompare((PetscObject)G,MATHYPRE,&ishypre);CHKERRQ(ierr);
1348   if (ishypre) {
1349     ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
1350     ierr = MatDestroy(&jac->G);CHKERRQ(ierr);
1351     jac->G = G;
1352   } else {
1353     ierr = MatDestroy(&jac->G);CHKERRQ(ierr);
1354     ierr = MatConvert(G,MATHYPRE,MAT_INITIAL_MATRIX,&jac->G);CHKERRQ(ierr);
1355   }
1356   PetscFunctionReturn(0);
1357 }
1358 
1359 /*@
1360  PCHYPRESetDiscreteGradient - Set discrete gradient matrix
1361 
1362    Collective on PC
1363 
1364    Input Parameters:
1365 +  pc - the preconditioning context
1366 -  G - the discrete gradient
1367 
1368    Level: intermediate
1369 
1370    Notes:
1371     G should have as many rows as the number of edges and as many columns as the number of vertices in the mesh
1372           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
1373 
1374 .seealso:
1375 @*/
1376 PetscErrorCode PCHYPRESetDiscreteGradient(PC pc, Mat G)
1377 {
1378   PetscErrorCode ierr;
1379 
1380   PetscFunctionBegin;
1381   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1382   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
1383   PetscCheckSameComm(pc,1,G,2);
1384   ierr = PetscTryMethod(pc,"PCHYPRESetDiscreteGradient_C",(PC,Mat),(pc,G));CHKERRQ(ierr);
1385   PetscFunctionReturn(0);
1386 }
1387 
1388 static PetscErrorCode PCHYPRESetDiscreteCurl_HYPRE(PC pc, Mat C)
1389 {
1390   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1391   PetscBool      ishypre;
1392   PetscErrorCode ierr;
1393 
1394   PetscFunctionBegin;
1395   ierr = PetscObjectTypeCompare((PetscObject)C,MATHYPRE,&ishypre);CHKERRQ(ierr);
1396   if (ishypre) {
1397     ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
1398     ierr = MatDestroy(&jac->C);CHKERRQ(ierr);
1399     jac->C = C;
1400   } else {
1401     ierr = MatDestroy(&jac->C);CHKERRQ(ierr);
1402     ierr = MatConvert(C,MATHYPRE,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
1403   }
1404   PetscFunctionReturn(0);
1405 }
1406 
1407 /*@
1408  PCHYPRESetDiscreteCurl - Set discrete curl matrix
1409 
1410    Collective on PC
1411 
1412    Input Parameters:
1413 +  pc - the preconditioning context
1414 -  C - the discrete curl
1415 
1416    Level: intermediate
1417 
1418    Notes:
1419     C should have as many rows as the number of faces and as many columns as the number of edges in the mesh
1420           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
1421 
1422 .seealso:
1423 @*/
1424 PetscErrorCode PCHYPRESetDiscreteCurl(PC pc, Mat C)
1425 {
1426   PetscErrorCode ierr;
1427 
1428   PetscFunctionBegin;
1429   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1430   PetscValidHeaderSpecific(C,MAT_CLASSID,2);
1431   PetscCheckSameComm(pc,1,C,2);
1432   ierr = PetscTryMethod(pc,"PCHYPRESetDiscreteCurl_C",(PC,Mat),(pc,C));CHKERRQ(ierr);
1433   PetscFunctionReturn(0);
1434 }
1435 
1436 static PetscErrorCode PCHYPRESetInterpolations_HYPRE(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1437 {
1438   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1439   PetscBool      ishypre;
1440   PetscErrorCode ierr;
1441   PetscInt       i;
1442   PetscFunctionBegin;
1443 
1444   ierr = MatDestroy(&jac->RT_PiFull);CHKERRQ(ierr);
1445   ierr = MatDestroy(&jac->ND_PiFull);CHKERRQ(ierr);
1446   for (i=0;i<3;++i) {
1447     ierr = MatDestroy(&jac->RT_Pi[i]);CHKERRQ(ierr);
1448     ierr = MatDestroy(&jac->ND_Pi[i]);CHKERRQ(ierr);
1449   }
1450 
1451   jac->dim = dim;
1452   if (RT_PiFull) {
1453     ierr = PetscObjectTypeCompare((PetscObject)RT_PiFull,MATHYPRE,&ishypre);CHKERRQ(ierr);
1454     if (ishypre) {
1455       ierr = PetscObjectReference((PetscObject)RT_PiFull);CHKERRQ(ierr);
1456       jac->RT_PiFull = RT_PiFull;
1457     } else {
1458       ierr = MatConvert(RT_PiFull,MATHYPRE,MAT_INITIAL_MATRIX,&jac->RT_PiFull);CHKERRQ(ierr);
1459     }
1460   }
1461   if (RT_Pi) {
1462     for (i=0;i<dim;++i) {
1463       if (RT_Pi[i]) {
1464         ierr = PetscObjectTypeCompare((PetscObject)RT_Pi[i],MATHYPRE,&ishypre);CHKERRQ(ierr);
1465         if (ishypre) {
1466           ierr = PetscObjectReference((PetscObject)RT_Pi[i]);CHKERRQ(ierr);
1467           jac->RT_Pi[i] = RT_Pi[i];
1468         } else {
1469           ierr = MatConvert(RT_Pi[i],MATHYPRE,MAT_INITIAL_MATRIX,&jac->RT_Pi[i]);CHKERRQ(ierr);
1470         }
1471       }
1472     }
1473   }
1474   if (ND_PiFull) {
1475     ierr = PetscObjectTypeCompare((PetscObject)ND_PiFull,MATHYPRE,&ishypre);CHKERRQ(ierr);
1476     if (ishypre) {
1477       ierr = PetscObjectReference((PetscObject)ND_PiFull);CHKERRQ(ierr);
1478       jac->ND_PiFull = ND_PiFull;
1479     } else {
1480       ierr = MatConvert(ND_PiFull,MATHYPRE,MAT_INITIAL_MATRIX,&jac->ND_PiFull);CHKERRQ(ierr);
1481     }
1482   }
1483   if (ND_Pi) {
1484     for (i=0;i<dim;++i) {
1485       if (ND_Pi[i]) {
1486         ierr = PetscObjectTypeCompare((PetscObject)ND_Pi[i],MATHYPRE,&ishypre);CHKERRQ(ierr);
1487         if (ishypre) {
1488           ierr = PetscObjectReference((PetscObject)ND_Pi[i]);CHKERRQ(ierr);
1489           jac->ND_Pi[i] = ND_Pi[i];
1490         } else {
1491           ierr = MatConvert(ND_Pi[i],MATHYPRE,MAT_INITIAL_MATRIX,&jac->ND_Pi[i]);CHKERRQ(ierr);
1492         }
1493       }
1494     }
1495   }
1496 
1497   PetscFunctionReturn(0);
1498 }
1499 
1500 /*@
1501  PCHYPRESetInterpolations - Set interpolation matrices for AMS/ADS preconditioner
1502 
1503    Collective on PC
1504 
1505    Input Parameters:
1506 +  pc - the preconditioning context
1507 -  dim - the dimension of the problem, only used in AMS
1508 -  RT_PiFull - Raviart-Thomas interpolation matrix
1509 -  RT_Pi - x/y/z component of Raviart-Thomas interpolation matrix
1510 -  ND_PiFull - Nedelec interpolation matrix
1511 -  ND_Pi - x/y/z component of Nedelec interpolation matrix
1512 
1513    Notes:
1514     For AMS, only Nedelec interpolation matrices are needed, the Raviart-Thomas interpolation matrices can be set to NULL.
1515           For ADS, both type of interpolation matrices are needed.
1516    Level: intermediate
1517 
1518 .seealso:
1519 @*/
1520 PetscErrorCode PCHYPRESetInterpolations(PC pc, PetscInt dim, Mat RT_PiFull, Mat RT_Pi[], Mat ND_PiFull, Mat ND_Pi[])
1521 {
1522   PetscErrorCode ierr;
1523   PetscInt       i;
1524 
1525   PetscFunctionBegin;
1526   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1527   if (RT_PiFull) {
1528     PetscValidHeaderSpecific(RT_PiFull,MAT_CLASSID,3);
1529     PetscCheckSameComm(pc,1,RT_PiFull,3);
1530   }
1531   if (RT_Pi) {
1532     PetscValidPointer(RT_Pi,4);
1533     for (i=0;i<dim;++i) {
1534       if (RT_Pi[i]) {
1535         PetscValidHeaderSpecific(RT_Pi[i],MAT_CLASSID,4);
1536         PetscCheckSameComm(pc,1,RT_Pi[i],4);
1537       }
1538     }
1539   }
1540   if (ND_PiFull) {
1541     PetscValidHeaderSpecific(ND_PiFull,MAT_CLASSID,5);
1542     PetscCheckSameComm(pc,1,ND_PiFull,5);
1543   }
1544   if (ND_Pi) {
1545     PetscValidPointer(ND_Pi,6);
1546     for (i=0;i<dim;++i) {
1547       if (ND_Pi[i]) {
1548         PetscValidHeaderSpecific(ND_Pi[i],MAT_CLASSID,6);
1549         PetscCheckSameComm(pc,1,ND_Pi[i],6);
1550       }
1551     }
1552   }
1553   ierr = PetscTryMethod(pc,"PCHYPRESetInterpolations_C",(PC,PetscInt,Mat,Mat[],Mat,Mat[]),(pc,dim,RT_PiFull,RT_Pi,ND_PiFull,ND_Pi));CHKERRQ(ierr);
1554   PetscFunctionReturn(0);
1555 }
1556 
1557 static PetscErrorCode PCHYPRESetPoissonMatrix_HYPRE(PC pc, Mat A, PetscBool isalpha)
1558 {
1559   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1560   PetscBool      ishypre;
1561   PetscErrorCode ierr;
1562 
1563   PetscFunctionBegin;
1564   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
1565   if (ishypre) {
1566     if (isalpha) {
1567       ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
1568       ierr = MatDestroy(&jac->alpha_Poisson);CHKERRQ(ierr);
1569       jac->alpha_Poisson = A;
1570     } else {
1571       if (A) {
1572         ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
1573       } else {
1574         jac->ams_beta_is_zero = PETSC_TRUE;
1575       }
1576       ierr = MatDestroy(&jac->beta_Poisson);CHKERRQ(ierr);
1577       jac->beta_Poisson = A;
1578     }
1579   } else {
1580     if (isalpha) {
1581       ierr = MatDestroy(&jac->alpha_Poisson);CHKERRQ(ierr);
1582       ierr = MatConvert(A,MATHYPRE,MAT_INITIAL_MATRIX,&jac->alpha_Poisson);CHKERRQ(ierr);
1583     } else {
1584       if (A) {
1585         ierr = MatDestroy(&jac->beta_Poisson);CHKERRQ(ierr);
1586         ierr = MatConvert(A,MATHYPRE,MAT_INITIAL_MATRIX,&jac->beta_Poisson);CHKERRQ(ierr);
1587       } else {
1588         ierr = MatDestroy(&jac->beta_Poisson);CHKERRQ(ierr);
1589         jac->ams_beta_is_zero = PETSC_TRUE;
1590       }
1591     }
1592   }
1593   PetscFunctionReturn(0);
1594 }
1595 
1596 /*@
1597  PCHYPRESetAlphaPoissonMatrix - Set vector Poisson matrix
1598 
1599    Collective on PC
1600 
1601    Input Parameters:
1602 +  pc - the preconditioning context
1603 -  A - the matrix
1604 
1605    Level: intermediate
1606 
1607    Notes:
1608     A should be obtained by discretizing the vector valued Poisson problem with linear finite elements
1609 
1610 .seealso:
1611 @*/
1612 PetscErrorCode PCHYPRESetAlphaPoissonMatrix(PC pc, Mat A)
1613 {
1614   PetscErrorCode ierr;
1615 
1616   PetscFunctionBegin;
1617   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1618   PetscValidHeaderSpecific(A,MAT_CLASSID,2);
1619   PetscCheckSameComm(pc,1,A,2);
1620   ierr = PetscTryMethod(pc,"PCHYPRESetPoissonMatrix_C",(PC,Mat,PetscBool),(pc,A,PETSC_TRUE));CHKERRQ(ierr);
1621   PetscFunctionReturn(0);
1622 }
1623 
1624 /*@
1625  PCHYPRESetBetaPoissonMatrix - Set Poisson matrix
1626 
1627    Collective on PC
1628 
1629    Input Parameters:
1630 +  pc - the preconditioning context
1631 -  A - the matrix
1632 
1633    Level: intermediate
1634 
1635    Notes:
1636     A should be obtained by discretizing the Poisson problem with linear finite elements.
1637           Following HYPRE convention, the scalar Poisson solver of AMS can be turned off by passing NULL.
1638 
1639 .seealso:
1640 @*/
1641 PetscErrorCode PCHYPRESetBetaPoissonMatrix(PC pc, Mat A)
1642 {
1643   PetscErrorCode ierr;
1644 
1645   PetscFunctionBegin;
1646   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1647   if (A) {
1648     PetscValidHeaderSpecific(A,MAT_CLASSID,2);
1649     PetscCheckSameComm(pc,1,A,2);
1650   }
1651   ierr = PetscTryMethod(pc,"PCHYPRESetPoissonMatrix_C",(PC,Mat,PetscBool),(pc,A,PETSC_FALSE));CHKERRQ(ierr);
1652   PetscFunctionReturn(0);
1653 }
1654 
1655 static PetscErrorCode PCHYPRESetEdgeConstantVectors_HYPRE(PC pc,Vec ozz, Vec zoz, Vec zzo)
1656 {
1657   PC_HYPRE           *jac = (PC_HYPRE*)pc->data;
1658   PetscErrorCode     ierr;
1659 
1660   PetscFunctionBegin;
1661   /* throw away any vector if already set */
1662   ierr = VecHYPRE_IJVectorDestroy(&jac->constants[0]);CHKERRQ(ierr);
1663   ierr = VecHYPRE_IJVectorDestroy(&jac->constants[1]);CHKERRQ(ierr);
1664   ierr = VecHYPRE_IJVectorDestroy(&jac->constants[2]);CHKERRQ(ierr);
1665   ierr = VecHYPRE_IJVectorCreate(ozz->map,&jac->constants[0]);CHKERRQ(ierr);
1666   ierr = VecHYPRE_IJVectorCopy(ozz,jac->constants[0]);CHKERRQ(ierr);
1667   ierr = VecHYPRE_IJVectorCreate(zoz->map,&jac->constants[1]);CHKERRQ(ierr);
1668   ierr = VecHYPRE_IJVectorCopy(zoz,jac->constants[1]);CHKERRQ(ierr);
1669   jac->dim = 2;
1670   if (zzo) {
1671     ierr = VecHYPRE_IJVectorCreate(zzo->map,&jac->constants[2]);CHKERRQ(ierr);
1672     ierr = VecHYPRE_IJVectorCopy(zzo,jac->constants[2]);CHKERRQ(ierr);
1673     jac->dim++;
1674   }
1675   PetscFunctionReturn(0);
1676 }
1677 
1678 /*@
1679  PCHYPRESetEdgeConstantVectors - Set the representation of the constant vector fields in edge element basis
1680 
1681    Collective on PC
1682 
1683    Input Parameters:
1684 +  pc - the preconditioning context
1685 -  ozz - vector representing (1,0,0) (or (1,0) in 2D)
1686 -  zoz - vector representing (0,1,0) (or (0,1) in 2D)
1687 -  zzo - vector representing (0,0,1) (use NULL in 2D)
1688 
1689    Level: intermediate
1690 
1691    Notes:
1692 
1693 .seealso:
1694 @*/
1695 PetscErrorCode PCHYPRESetEdgeConstantVectors(PC pc, Vec ozz, Vec zoz, Vec zzo)
1696 {
1697   PetscErrorCode ierr;
1698 
1699   PetscFunctionBegin;
1700   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1701   PetscValidHeaderSpecific(ozz,VEC_CLASSID,2);
1702   PetscValidHeaderSpecific(zoz,VEC_CLASSID,3);
1703   if (zzo) PetscValidHeaderSpecific(zzo,VEC_CLASSID,4);
1704   PetscCheckSameComm(pc,1,ozz,2);
1705   PetscCheckSameComm(pc,1,zoz,3);
1706   if (zzo) PetscCheckSameComm(pc,1,zzo,4);
1707   ierr = PetscTryMethod(pc,"PCHYPRESetEdgeConstantVectors_C",(PC,Vec,Vec,Vec),(pc,ozz,zoz,zzo));CHKERRQ(ierr);
1708   PetscFunctionReturn(0);
1709 }
1710 
1711 static PetscErrorCode PCSetCoordinates_HYPRE(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1712 {
1713   PC_HYPRE        *jac = (PC_HYPRE*)pc->data;
1714   Vec             tv;
1715   PetscInt        i;
1716   PetscErrorCode  ierr;
1717 
1718   PetscFunctionBegin;
1719   /* throw away any coordinate vector if already set */
1720   ierr = VecHYPRE_IJVectorDestroy(&jac->coords[0]);CHKERRQ(ierr);
1721   ierr = VecHYPRE_IJVectorDestroy(&jac->coords[1]);CHKERRQ(ierr);
1722   ierr = VecHYPRE_IJVectorDestroy(&jac->coords[2]);CHKERRQ(ierr);
1723   jac->dim = dim;
1724 
1725   /* compute IJ vector for coordinates */
1726   ierr = VecCreate(PetscObjectComm((PetscObject)pc),&tv);CHKERRQ(ierr);
1727   ierr = VecSetType(tv,VECSTANDARD);CHKERRQ(ierr);
1728   ierr = VecSetSizes(tv,nloc,PETSC_DECIDE);CHKERRQ(ierr);
1729   for (i=0;i<dim;i++) {
1730     PetscScalar *array;
1731     PetscInt    j;
1732 
1733     ierr = VecHYPRE_IJVectorCreate(tv->map,&jac->coords[i]);CHKERRQ(ierr);
1734     ierr = VecGetArrayWrite(tv,&array);CHKERRQ(ierr);
1735     for (j=0;j<nloc;j++) array[j] = coords[j*dim+i];
1736     ierr = VecRestoreArrayWrite(tv,&array);CHKERRQ(ierr);
1737     ierr = VecHYPRE_IJVectorCopy(tv,jac->coords[i]);CHKERRQ(ierr);
1738   }
1739   ierr = VecDestroy(&tv);CHKERRQ(ierr);
1740   PetscFunctionReturn(0);
1741 }
1742 
1743 /* ---------------------------------------------------------------------------------*/
1744 
1745 static PetscErrorCode  PCHYPREGetType_HYPRE(PC pc,const char *name[])
1746 {
1747   PC_HYPRE *jac = (PC_HYPRE*)pc->data;
1748 
1749   PetscFunctionBegin;
1750   *name = jac->hypre_type;
1751   PetscFunctionReturn(0);
1752 }
1753 
1754 static PetscErrorCode  PCHYPRESetType_HYPRE(PC pc,const char name[])
1755 {
1756   PC_HYPRE       *jac = (PC_HYPRE*)pc->data;
1757   PetscErrorCode ierr;
1758   PetscBool      flag;
1759 
1760   PetscFunctionBegin;
1761   if (jac->hypre_type) {
1762     ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr);
1763     if (!flag) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set");
1764     PetscFunctionReturn(0);
1765   } else {
1766     ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr);
1767   }
1768 
1769   jac->maxiter         = PETSC_DEFAULT;
1770   jac->tol             = PETSC_DEFAULT;
1771   jac->printstatistics = PetscLogPrintInfo;
1772 
1773   ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr);
1774   if (flag) {
1775     ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(jac->comm_hypre));CHKERRMPI(ierr);
1776     PetscStackCallStandard(HYPRE_ParCSRPilutCreate,(jac->comm_hypre,&jac->hsolver));
1777     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut;
1778     pc->ops->view           = PCView_HYPRE_Pilut;
1779     jac->destroy            = HYPRE_ParCSRPilutDestroy;
1780     jac->setup              = HYPRE_ParCSRPilutSetup;
1781     jac->solve              = HYPRE_ParCSRPilutSolve;
1782     jac->factorrowsize      = PETSC_DEFAULT;
1783     PetscFunctionReturn(0);
1784   }
1785   ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr);
1786   if (flag) {
1787 #if defined(PETSC_HAVE_64BIT_INDICES)
1788     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Hypre Euclid not support with 64 bit indices");
1789 #endif
1790     ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(jac->comm_hypre));CHKERRMPI(ierr);
1791     PetscStackCallStandard(HYPRE_EuclidCreate,(jac->comm_hypre,&jac->hsolver));
1792     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid;
1793     pc->ops->view           = PCView_HYPRE_Euclid;
1794     jac->destroy            = HYPRE_EuclidDestroy;
1795     jac->setup              = HYPRE_EuclidSetup;
1796     jac->solve              = HYPRE_EuclidSolve;
1797     jac->factorrowsize      = PETSC_DEFAULT;
1798     jac->eu_level           = PETSC_DEFAULT; /* default */
1799     PetscFunctionReturn(0);
1800   }
1801   ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr);
1802   if (flag) {
1803     ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(jac->comm_hypre));CHKERRMPI(ierr);
1804     PetscStackCallStandard(HYPRE_ParaSailsCreate,(jac->comm_hypre,&jac->hsolver));
1805     pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails;
1806     pc->ops->view           = PCView_HYPRE_ParaSails;
1807     jac->destroy            = HYPRE_ParaSailsDestroy;
1808     jac->setup              = HYPRE_ParaSailsSetup;
1809     jac->solve              = HYPRE_ParaSailsSolve;
1810     /* initialize */
1811     jac->nlevels   = 1;
1812     jac->threshold = .1;
1813     jac->filter    = .1;
1814     jac->loadbal   = 0;
1815     if (PetscLogPrintInfo) jac->logging = (int) PETSC_TRUE;
1816     else jac->logging = (int) PETSC_FALSE;
1817 
1818     jac->ruse = (int) PETSC_FALSE;
1819     jac->symt = 0;
1820     PetscStackCallStandard(HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshold,jac->nlevels));
1821     PetscStackCallStandard(HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter));
1822     PetscStackCallStandard(HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal));
1823     PetscStackCallStandard(HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging));
1824     PetscStackCallStandard(HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse));
1825     PetscStackCallStandard(HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt));
1826     PetscFunctionReturn(0);
1827   }
1828   ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr);
1829   if (flag) {
1830     ierr                     = HYPRE_BoomerAMGCreate(&jac->hsolver);
1831     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_BoomerAMG;
1832     pc->ops->view            = PCView_HYPRE_BoomerAMG;
1833     pc->ops->applytranspose  = PCApplyTranspose_HYPRE_BoomerAMG;
1834     pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG;
1835     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",PCGetInterpolations_BoomerAMG);CHKERRQ(ierr);
1836     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",PCGetCoarseOperators_BoomerAMG);CHKERRQ(ierr);
1837     jac->destroy             = HYPRE_BoomerAMGDestroy;
1838     jac->setup               = HYPRE_BoomerAMGSetup;
1839     jac->solve               = HYPRE_BoomerAMGSolve;
1840     jac->applyrichardson     = PETSC_FALSE;
1841     /* these defaults match the hypre defaults */
1842     jac->cycletype        = 1;
1843     jac->maxlevels        = 25;
1844     jac->maxiter          = 1;
1845     jac->tol              = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */
1846     jac->truncfactor      = 0.0;
1847     jac->strongthreshold  = .25;
1848     jac->maxrowsum        = .9;
1849     jac->coarsentype      = 6;
1850     jac->measuretype      = 0;
1851     jac->gridsweeps[0]    = jac->gridsweeps[1] = jac->gridsweeps[2] = 1;
1852     jac->smoothtype       = -1; /* Not set by default */
1853     jac->smoothnumlevels  = 25;
1854     jac->eu_level         = 0;
1855     jac->eu_droptolerance = 0;
1856     jac->eu_bj            = 0;
1857     jac->relaxtype[0]     = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a PC - most likely with CG */
1858     jac->relaxtype[2]     = 9; /*G.E. */
1859     jac->relaxweight      = 1.0;
1860     jac->outerrelaxweight = 1.0;
1861     jac->relaxorder       = 1;
1862     jac->interptype       = 0;
1863     jac->Rtype            = 0;
1864     jac->Rstrongthreshold = 0.25;
1865     jac->Rfilterthreshold = 0.0;
1866     jac->Adroptype        = -1;
1867     jac->Adroptol         = 0.0;
1868     jac->agg_nl           = 0;
1869     jac->agg_interptype   = 4;
1870     jac->pmax             = 0;
1871     jac->truncfactor      = 0.0;
1872     jac->agg_num_paths    = 1;
1873     jac->maxc             = 9;
1874     jac->minc             = 1;
1875 
1876     jac->nodal_coarsening      = 0;
1877     jac->nodal_coarsening_diag = 0;
1878     jac->vec_interp_variant    = 0;
1879     jac->vec_interp_qmax       = 0;
1880     jac->vec_interp_smooth     = PETSC_FALSE;
1881     jac->interp_refine         = 0;
1882     jac->nodal_relax           = PETSC_FALSE;
1883     jac->nodal_relax_levels    = 1;
1884     jac->rap2                  = 0;
1885 
1886     /* GPU defaults
1887          from https://hypre.readthedocs.io/en/latest/solvers-boomeramg.html#gpu-supported-options
1888          and /src/parcsr_ls/par_amg.c */
1889 #if defined(PETSC_HAVE_HYPRE_DEVICE)
1890     jac->keeptranspose         = PETSC_TRUE;
1891     jac->mod_rap2              = 1;
1892     jac->coarsentype           = 8;
1893     jac->relaxorder            = 0;
1894     jac->interptype            = 6;
1895     jac->relaxtype[0]          = 18;
1896     jac->relaxtype[1]          = 18;
1897     jac->agg_interptype        = 7;
1898 #else
1899     jac->keeptranspose         = PETSC_FALSE;
1900     jac->mod_rap2              = 0;
1901 #endif
1902     PetscStackCallStandard(HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype));
1903     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels));
1904     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter));
1905     PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol));
1906     PetscStackCallStandard(HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor));
1907     PetscStackCallStandard(HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold));
1908     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum));
1909     PetscStackCallStandard(HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype));
1910     PetscStackCallStandard(HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype));
1911     PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder));
1912     PetscStackCallStandard(HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype));
1913     PetscStackCallStandard(HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl));
1914     PetscStackCallStandard(HYPRE_BoomerAMGSetAggInterpType,(jac->hsolver,jac->agg_interptype));
1915     PetscStackCallStandard(HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax));
1916     PetscStackCallStandard(HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths));
1917     PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, jac->relaxtype[0]));  /* defaults coarse to 9 */
1918     PetscStackCallStandard(HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver, jac->gridsweeps[0])); /* defaults coarse to 1 */
1919     PetscStackCallStandard(HYPRE_BoomerAMGSetMaxCoarseSize,(jac->hsolver, jac->maxc));
1920     PetscStackCallStandard(HYPRE_BoomerAMGSetMinCoarseSize,(jac->hsolver, jac->minc));
1921 
1922     /* GPU */
1923 #if PETSC_PKG_HYPRE_VERSION_GE(2,18,0)
1924     PetscStackCallStandard(HYPRE_BoomerAMGSetKeepTranspose,(jac->hsolver,jac->keeptranspose ? 1 : 0));
1925     PetscStackCallStandard(HYPRE_BoomerAMGSetRAP2,(jac->hsolver, jac->rap2));
1926     PetscStackCallStandard(HYPRE_BoomerAMGSetModuleRAP2,(jac->hsolver, jac->mod_rap2));
1927 #endif
1928 
1929     /* AIR */
1930 #if PETSC_PKG_HYPRE_VERSION_GE(2,18,0)
1931     PetscStackCallStandard(HYPRE_BoomerAMGSetRestriction,(jac->hsolver,jac->Rtype));
1932     PetscStackCallStandard(HYPRE_BoomerAMGSetStrongThresholdR,(jac->hsolver,jac->Rstrongthreshold));
1933     PetscStackCallStandard(HYPRE_BoomerAMGSetFilterThresholdR,(jac->hsolver,jac->Rfilterthreshold));
1934     PetscStackCallStandard(HYPRE_BoomerAMGSetADropTol,(jac->hsolver,jac->Adroptol));
1935     PetscStackCallStandard(HYPRE_BoomerAMGSetADropType,(jac->hsolver,jac->Adroptype));
1936 #endif
1937     PetscFunctionReturn(0);
1938   }
1939   ierr = PetscStrcmp("ams",jac->hypre_type,&flag);CHKERRQ(ierr);
1940   if (flag) {
1941     ierr                     = HYPRE_AMSCreate(&jac->hsolver);
1942     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_AMS;
1943     pc->ops->view            = PCView_HYPRE_AMS;
1944     jac->destroy             = HYPRE_AMSDestroy;
1945     jac->setup               = HYPRE_AMSSetup;
1946     jac->solve               = HYPRE_AMSSolve;
1947     jac->coords[0]           = NULL;
1948     jac->coords[1]           = NULL;
1949     jac->coords[2]           = NULL;
1950     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE AMS */
1951     jac->as_print           = 0;
1952     jac->as_max_iter        = 1; /* used as a preconditioner */
1953     jac->as_tol             = 0.; /* used as a preconditioner */
1954     jac->ams_cycle_type     = 13;
1955     /* Smoothing options */
1956     jac->as_relax_type      = 2;
1957     jac->as_relax_times     = 1;
1958     jac->as_relax_weight    = 1.0;
1959     jac->as_omega           = 1.0;
1960     /* Vector valued Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1961     jac->as_amg_alpha_opts[0] = 10;
1962     jac->as_amg_alpha_opts[1] = 1;
1963     jac->as_amg_alpha_opts[2] = 6;
1964     jac->as_amg_alpha_opts[3] = 6;
1965     jac->as_amg_alpha_opts[4] = 4;
1966     jac->as_amg_alpha_theta   = 0.25;
1967     /* Scalar Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
1968     jac->as_amg_beta_opts[0] = 10;
1969     jac->as_amg_beta_opts[1] = 1;
1970     jac->as_amg_beta_opts[2] = 6;
1971     jac->as_amg_beta_opts[3] = 6;
1972     jac->as_amg_beta_opts[4] = 4;
1973     jac->as_amg_beta_theta   = 0.25;
1974     PetscStackCallStandard(HYPRE_AMSSetPrintLevel,(jac->hsolver,jac->as_print));
1975     PetscStackCallStandard(HYPRE_AMSSetMaxIter,(jac->hsolver,jac->as_max_iter));
1976     PetscStackCallStandard(HYPRE_AMSSetCycleType,(jac->hsolver,jac->ams_cycle_type));
1977     PetscStackCallStandard(HYPRE_AMSSetTol,(jac->hsolver,jac->as_tol));
1978     PetscStackCallStandard(HYPRE_AMSSetSmoothingOptions,(jac->hsolver,jac->as_relax_type,
1979                                                                       jac->as_relax_times,
1980                                                                       jac->as_relax_weight,
1981                                                                       jac->as_omega));
1982     PetscStackCallStandard(HYPRE_AMSSetAlphaAMGOptions,(jac->hsolver,jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
1983                                                                      jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
1984                                                                      jac->as_amg_alpha_opts[2],       /* AMG relax_type */
1985                                                                      jac->as_amg_alpha_theta,
1986                                                                      jac->as_amg_alpha_opts[3],       /* AMG interp_type */
1987                                                                      jac->as_amg_alpha_opts[4]));     /* AMG Pmax */
1988     PetscStackCallStandard(HYPRE_AMSSetBetaAMGOptions,(jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
1989                                                                     jac->as_amg_beta_opts[1],       /* AMG agg_levels */
1990                                                                     jac->as_amg_beta_opts[2],       /* AMG relax_type */
1991                                                                     jac->as_amg_beta_theta,
1992                                                                     jac->as_amg_beta_opts[3],       /* AMG interp_type */
1993                                                                     jac->as_amg_beta_opts[4]));     /* AMG Pmax */
1994     /* Zero conductivity */
1995     jac->ams_beta_is_zero      = PETSC_FALSE;
1996     jac->ams_beta_is_zero_part = PETSC_FALSE;
1997     PetscFunctionReturn(0);
1998   }
1999   ierr = PetscStrcmp("ads",jac->hypre_type,&flag);CHKERRQ(ierr);
2000   if (flag) {
2001     ierr                     = HYPRE_ADSCreate(&jac->hsolver);
2002     pc->ops->setfromoptions  = PCSetFromOptions_HYPRE_ADS;
2003     pc->ops->view            = PCView_HYPRE_ADS;
2004     jac->destroy             = HYPRE_ADSDestroy;
2005     jac->setup               = HYPRE_ADSSetup;
2006     jac->solve               = HYPRE_ADSSolve;
2007     jac->coords[0]           = NULL;
2008     jac->coords[1]           = NULL;
2009     jac->coords[2]           = NULL;
2010     /* solver parameters: these are borrowed from mfem package, and they are not the default values from HYPRE ADS */
2011     jac->as_print           = 0;
2012     jac->as_max_iter        = 1; /* used as a preconditioner */
2013     jac->as_tol             = 0.; /* used as a preconditioner */
2014     jac->ads_cycle_type     = 13;
2015     /* Smoothing options */
2016     jac->as_relax_type      = 2;
2017     jac->as_relax_times     = 1;
2018     jac->as_relax_weight    = 1.0;
2019     jac->as_omega           = 1.0;
2020     /* AMS solver parameters: cycle_type, coarsen type, agg_levels, relax_type, interp_type, Pmax */
2021     jac->ams_cycle_type       = 14;
2022     jac->as_amg_alpha_opts[0] = 10;
2023     jac->as_amg_alpha_opts[1] = 1;
2024     jac->as_amg_alpha_opts[2] = 6;
2025     jac->as_amg_alpha_opts[3] = 6;
2026     jac->as_amg_alpha_opts[4] = 4;
2027     jac->as_amg_alpha_theta   = 0.25;
2028     /* Vector Poisson AMG solver parameters: coarsen type, agg_levels, relax_type, interp_type, Pmax */
2029     jac->as_amg_beta_opts[0] = 10;
2030     jac->as_amg_beta_opts[1] = 1;
2031     jac->as_amg_beta_opts[2] = 6;
2032     jac->as_amg_beta_opts[3] = 6;
2033     jac->as_amg_beta_opts[4] = 4;
2034     jac->as_amg_beta_theta   = 0.25;
2035     PetscStackCallStandard(HYPRE_ADSSetPrintLevel,(jac->hsolver,jac->as_print));
2036     PetscStackCallStandard(HYPRE_ADSSetMaxIter,(jac->hsolver,jac->as_max_iter));
2037     PetscStackCallStandard(HYPRE_ADSSetCycleType,(jac->hsolver,jac->ams_cycle_type));
2038     PetscStackCallStandard(HYPRE_ADSSetTol,(jac->hsolver,jac->as_tol));
2039     PetscStackCallStandard(HYPRE_ADSSetSmoothingOptions,(jac->hsolver,jac->as_relax_type,
2040                                                                       jac->as_relax_times,
2041                                                                       jac->as_relax_weight,
2042                                                                       jac->as_omega));
2043     PetscStackCallStandard(HYPRE_ADSSetAMSOptions,(jac->hsolver,jac->ams_cycle_type,             /* AMG coarsen type */
2044                                                                 jac->as_amg_alpha_opts[0],       /* AMG coarsen type */
2045                                                                 jac->as_amg_alpha_opts[1],       /* AMG agg_levels */
2046                                                                 jac->as_amg_alpha_opts[2],       /* AMG relax_type */
2047                                                                 jac->as_amg_alpha_theta,
2048                                                                 jac->as_amg_alpha_opts[3],       /* AMG interp_type */
2049                                                                 jac->as_amg_alpha_opts[4]));     /* AMG Pmax */
2050     PetscStackCallStandard(HYPRE_ADSSetAMGOptions,(jac->hsolver,jac->as_amg_beta_opts[0],       /* AMG coarsen type */
2051                                                                 jac->as_amg_beta_opts[1],       /* AMG agg_levels */
2052                                                                 jac->as_amg_beta_opts[2],       /* AMG relax_type */
2053                                                                 jac->as_amg_beta_theta,
2054                                                                 jac->as_amg_beta_opts[3],       /* AMG interp_type */
2055                                                                 jac->as_amg_beta_opts[4]));     /* AMG Pmax */
2056     PetscFunctionReturn(0);
2057   }
2058   ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr);
2059 
2060   jac->hypre_type = NULL;
2061   SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are euclid, pilut, parasails, boomeramg, ams",name);
2062 }
2063 
2064 /*
2065     It only gets here if the HYPRE type has not been set before the call to
2066    ...SetFromOptions() which actually is most of the time
2067 */
2068 PetscErrorCode PCSetFromOptions_HYPRE(PetscOptionItems *PetscOptionsObject,PC pc)
2069 {
2070   PetscErrorCode ierr;
2071   PetscInt       indx;
2072   const char     *type[] = {"euclid","pilut","parasails","boomeramg","ams","ads"};
2073   PetscBool      flg;
2074 
2075   PetscFunctionBegin;
2076   ierr = PetscOptionsHead(PetscOptionsObject,"HYPRE preconditioner options");CHKERRQ(ierr);
2077   ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,ALEN(type),"boomeramg",&indx,&flg);CHKERRQ(ierr);
2078   if (flg) {
2079     ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr);
2080   } else {
2081     ierr = PCHYPRESetType_HYPRE(pc,"boomeramg");CHKERRQ(ierr);
2082   }
2083   if (pc->ops->setfromoptions) {
2084     ierr = pc->ops->setfromoptions(PetscOptionsObject,pc);CHKERRQ(ierr);
2085   }
2086   ierr = PetscOptionsTail();CHKERRQ(ierr);
2087   PetscFunctionReturn(0);
2088 }
2089 
2090 /*@C
2091      PCHYPRESetType - Sets which hypre preconditioner you wish to use
2092 
2093    Input Parameters:
2094 +     pc - the preconditioner context
2095 -     name - either  euclid, pilut, parasails, boomeramg, ams, ads
2096 
2097    Options Database Keys:
2098    -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2099 
2100    Level: intermediate
2101 
2102 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
2103            PCHYPRE
2104 
2105 @*/
2106 PetscErrorCode  PCHYPRESetType(PC pc,const char name[])
2107 {
2108   PetscErrorCode ierr;
2109 
2110   PetscFunctionBegin;
2111   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2112   PetscValidCharPointer(name,2);
2113   ierr = PetscTryMethod(pc,"PCHYPRESetType_C",(PC,const char[]),(pc,name));CHKERRQ(ierr);
2114   PetscFunctionReturn(0);
2115 }
2116 
2117 /*@C
2118      PCHYPREGetType - Gets which hypre preconditioner you are using
2119 
2120    Input Parameter:
2121 .     pc - the preconditioner context
2122 
2123    Output Parameter:
2124 .     name - either  euclid, pilut, parasails, boomeramg, ams, ads
2125 
2126    Level: intermediate
2127 
2128 .seealso:  PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC,
2129            PCHYPRE
2130 
2131 @*/
2132 PetscErrorCode  PCHYPREGetType(PC pc,const char *name[])
2133 {
2134   PetscErrorCode ierr;
2135 
2136   PetscFunctionBegin;
2137   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2138   PetscValidPointer(name,2);
2139   ierr = PetscTryMethod(pc,"PCHYPREGetType_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr);
2140   PetscFunctionReturn(0);
2141 }
2142 
2143 /*MC
2144      PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre
2145 
2146    Options Database Keys:
2147 +   -pc_hypre_type - One of euclid, pilut, parasails, boomeramg, ams, ads
2148 -   Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX
2149           preconditioner
2150 
2151    Level: intermediate
2152 
2153    Notes:
2154     Apart from pc_hypre_type (for which there is PCHYPRESetType()),
2155           the many hypre options can ONLY be set via the options database (e.g. the command line
2156           or with PetscOptionsSetValue(), there are no functions to set them)
2157 
2158           The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_tol refer to the number of iterations
2159           (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if
2160           -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner
2161           (-pc_hypre_boomeramg_tol should be set to 0.0 - the default - to strictly use a fixed number of
2162           iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations
2163           and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10
2164           then AT MOST twenty V-cycles of boomeramg will be called.
2165 
2166            Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation
2167            (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry.
2168            Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi.
2169           If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly
2170           and use -ksp_max_it to control the number of V-cycles.
2171           (see the PETSc FAQ.html at the PETSc website under the Documentation tab).
2172 
2173           2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option
2174           -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L.
2175 
2176           MatSetNearNullSpace() - if you provide a near null space to your matrix it is ignored by hypre UNLESS you also use
2177           the following two options:
2178 
2179    Options Database Keys:
2180 +   -pc_hypre_boomeramg_nodal_coarsen <n> - where n is from 1 to 6 (see HYPRE_BOOMERAMGSetNodal())
2181 -   -pc_hypre_boomeramg_vec_interp_variant <v> - where v is from 1 to 3 (see HYPRE_BoomerAMGSetInterpVecVariant())
2182 
2183           Depending on the linear system you may see the same or different convergence depending on the values you use.
2184 
2185           See PCPFMG for access to the hypre Struct PFMG solver
2186 
2187 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
2188            PCHYPRESetType(), PCPFMG
2189 
2190 M*/
2191 
2192 PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc)
2193 {
2194   PC_HYPRE       *jac;
2195   PetscErrorCode ierr;
2196 
2197   PetscFunctionBegin;
2198   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
2199 
2200   pc->data                = jac;
2201   pc->ops->reset          = PCReset_HYPRE;
2202   pc->ops->destroy        = PCDestroy_HYPRE;
2203   pc->ops->setfromoptions = PCSetFromOptions_HYPRE;
2204   pc->ops->setup          = PCSetUp_HYPRE;
2205   pc->ops->apply          = PCApply_HYPRE;
2206   jac->comm_hypre         = MPI_COMM_NULL;
2207   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C",PCHYPRESetType_HYPRE);CHKERRQ(ierr);
2208   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C",PCHYPREGetType_HYPRE);CHKERRQ(ierr);
2209   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_HYPRE);CHKERRQ(ierr);
2210   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteGradient_C",PCHYPRESetDiscreteGradient_HYPRE);CHKERRQ(ierr);
2211   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetDiscreteCurl_C",PCHYPRESetDiscreteCurl_HYPRE);CHKERRQ(ierr);
2212   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetInterpolations_C",PCHYPRESetInterpolations_HYPRE);CHKERRQ(ierr);
2213   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetEdgeConstantVectors_C",PCHYPRESetEdgeConstantVectors_HYPRE);CHKERRQ(ierr);
2214   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetPoissonMatrix_C",PCHYPRESetPoissonMatrix_HYPRE);CHKERRQ(ierr);
2215 #if defined(PETSC_HAVE_HYPRE_DEVICE)
2216 #if defined(HYPRE_USING_HIP)
2217   ierr = PetscHIPInitializeCheck();CHKERRQ(ierr);
2218 #endif
2219 #if defined(HYPRE_USING_CUDA)
2220   ierr = PetscCUDAInitializeCheck();CHKERRQ(ierr);
2221 #endif
2222 #endif
2223   PetscFunctionReturn(0);
2224 }
2225 
2226 /* ---------------------------------------------------------------------------------------------------------------------------------*/
2227 
2228 typedef struct {
2229   MPI_Comm           hcomm;        /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */
2230   HYPRE_StructSolver hsolver;
2231 
2232   /* keep copy of PFMG options used so may view them */
2233   PetscInt its;
2234   double   tol;
2235   PetscInt relax_type;
2236   PetscInt rap_type;
2237   PetscInt num_pre_relax,num_post_relax;
2238   PetscInt max_levels;
2239 } PC_PFMG;
2240 
2241 PetscErrorCode PCDestroy_PFMG(PC pc)
2242 {
2243   PetscErrorCode ierr;
2244   PC_PFMG        *ex = (PC_PFMG*) pc->data;
2245 
2246   PetscFunctionBegin;
2247   if (ex->hsolver) PetscStackCallStandard(HYPRE_StructPFMGDestroy,(ex->hsolver));
2248   ierr = MPI_Comm_free(&ex->hcomm);CHKERRMPI(ierr);
2249   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2250   PetscFunctionReturn(0);
2251 }
2252 
2253 static const char *PFMGRelaxType[] = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"};
2254 static const char *PFMGRAPType[] = {"Galerkin","non-Galerkin"};
2255 
2256 PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer)
2257 {
2258   PetscErrorCode ierr;
2259   PetscBool      iascii;
2260   PC_PFMG        *ex = (PC_PFMG*) pc->data;
2261 
2262   PetscFunctionBegin;
2263   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2264   if (iascii) {
2265     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE PFMG preconditioning\n");CHKERRQ(ierr);
2266     ierr = PetscViewerASCIIPrintf(viewer,"    max iterations %d\n",ex->its);CHKERRQ(ierr);
2267     ierr = PetscViewerASCIIPrintf(viewer,"    tolerance %g\n",ex->tol);CHKERRQ(ierr);
2268     ierr = PetscViewerASCIIPrintf(viewer,"    relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr);
2269     ierr = PetscViewerASCIIPrintf(viewer,"    RAP type %s\n",PFMGRAPType[ex->rap_type]);CHKERRQ(ierr);
2270     ierr = PetscViewerASCIIPrintf(viewer,"    number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr);
2271     ierr = PetscViewerASCIIPrintf(viewer,"    max levels %d\n",ex->max_levels);CHKERRQ(ierr);
2272   }
2273   PetscFunctionReturn(0);
2274 }
2275 
2276 PetscErrorCode PCSetFromOptions_PFMG(PetscOptionItems *PetscOptionsObject,PC pc)
2277 {
2278   PetscErrorCode ierr;
2279   PC_PFMG        *ex = (PC_PFMG*) pc->data;
2280   PetscBool      flg = PETSC_FALSE;
2281 
2282   PetscFunctionBegin;
2283   ierr = PetscOptionsHead(PetscOptionsObject,"PFMG options");CHKERRQ(ierr);
2284   ierr = PetscOptionsBool("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",flg,&flg,NULL);CHKERRQ(ierr);
2285   if (flg) {
2286     PetscStackCallStandard(HYPRE_StructPFMGSetPrintLevel,(ex->hsolver,3));
2287   }
2288   ierr = PetscOptionsInt("-pc_pfmg_its","Number of iterations of PFMG to use as preconditioner","HYPRE_StructPFMGSetMaxIter",ex->its,&ex->its,NULL);CHKERRQ(ierr);
2289   PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(ex->hsolver,ex->its));
2290   ierr = PetscOptionsInt("-pc_pfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_StructPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,NULL);CHKERRQ(ierr);
2291   PetscStackCallStandard(HYPRE_StructPFMGSetNumPreRelax,(ex->hsolver,ex->num_pre_relax));
2292   ierr = PetscOptionsInt("-pc_pfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_StructPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,NULL);CHKERRQ(ierr);
2293   PetscStackCallStandard(HYPRE_StructPFMGSetNumPostRelax,(ex->hsolver,ex->num_post_relax));
2294 
2295   ierr = PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,NULL);CHKERRQ(ierr);
2296   PetscStackCallStandard(HYPRE_StructPFMGSetMaxLevels,(ex->hsolver,ex->max_levels));
2297 
2298   ierr = PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,NULL);CHKERRQ(ierr);
2299   PetscStackCallStandard(HYPRE_StructPFMGSetTol,(ex->hsolver,ex->tol));
2300   ierr = PetscOptionsEList("-pc_pfmg_relax_type","Relax type for the up and down cycles","HYPRE_StructPFMGSetRelaxType",PFMGRelaxType,ALEN(PFMGRelaxType),PFMGRelaxType[ex->relax_type],&ex->relax_type,NULL);CHKERRQ(ierr);
2301   PetscStackCallStandard(HYPRE_StructPFMGSetRelaxType,(ex->hsolver, ex->relax_type));
2302   ierr = PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,ALEN(PFMGRAPType),PFMGRAPType[ex->rap_type],&ex->rap_type,NULL);CHKERRQ(ierr);
2303   PetscStackCallStandard(HYPRE_StructPFMGSetRAPType,(ex->hsolver, ex->rap_type));
2304   ierr = PetscOptionsTail();CHKERRQ(ierr);
2305   PetscFunctionReturn(0);
2306 }
2307 
2308 PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y)
2309 {
2310   PetscErrorCode    ierr;
2311   PC_PFMG           *ex = (PC_PFMG*) pc->data;
2312   PetscScalar       *yy;
2313   const PetscScalar *xx;
2314   PetscInt          ilower[3],iupper[3];
2315   HYPRE_Int         hlower[3],hupper[3];
2316   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(pc->pmat->data);
2317 
2318   PetscFunctionBegin;
2319   ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
2320   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
2321   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2322   iupper[0] += ilower[0] - 1;
2323   iupper[1] += ilower[1] - 1;
2324   iupper[2] += ilower[2] - 1;
2325   hlower[0]  = (HYPRE_Int)ilower[0];
2326   hlower[1]  = (HYPRE_Int)ilower[1];
2327   hlower[2]  = (HYPRE_Int)ilower[2];
2328   hupper[0]  = (HYPRE_Int)iupper[0];
2329   hupper[1]  = (HYPRE_Int)iupper[1];
2330   hupper[2]  = (HYPRE_Int)iupper[2];
2331 
2332   /* copy x values over to hypre */
2333   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
2334   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
2335   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,hlower,hupper,(HYPRE_Complex*)xx));
2336   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
2337   PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb));
2338   PetscStackCallStandard(HYPRE_StructPFMGSolve,(ex->hsolver,mx->hmat,mx->hb,mx->hx));
2339 
2340   /* copy solution values back to PETSc */
2341   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
2342   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,hlower,hupper,(HYPRE_Complex*)yy));
2343   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
2344   PetscFunctionReturn(0);
2345 }
2346 
2347 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)
2348 {
2349   PC_PFMG        *jac = (PC_PFMG*)pc->data;
2350   PetscErrorCode ierr;
2351   HYPRE_Int      oits;
2352 
2353   PetscFunctionBegin;
2354   ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
2355   PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(jac->hsolver,its*jac->its));
2356   PetscStackCallStandard(HYPRE_StructPFMGSetTol,(jac->hsolver,rtol));
2357 
2358   ierr = PCApply_PFMG(pc,b,y);CHKERRQ(ierr);
2359   PetscStackCallStandard(HYPRE_StructPFMGGetNumIterations,(jac->hsolver,&oits));
2360   *outits = oits;
2361   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2362   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
2363   PetscStackCallStandard(HYPRE_StructPFMGSetTol,(jac->hsolver,jac->tol));
2364   PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(jac->hsolver,jac->its));
2365   PetscFunctionReturn(0);
2366 }
2367 
2368 PetscErrorCode PCSetUp_PFMG(PC pc)
2369 {
2370   PetscErrorCode  ierr;
2371   PC_PFMG         *ex = (PC_PFMG*) pc->data;
2372   Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data);
2373   PetscBool       flg;
2374 
2375   PetscFunctionBegin;
2376   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg);CHKERRQ(ierr);
2377   if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner");
2378 
2379   /* create the hypre solver object and set its information */
2380   if (ex->hsolver) PetscStackCallStandard(HYPRE_StructPFMGDestroy,(ex->hsolver));
2381   PetscStackCallStandard(HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver));
2382   PetscStackCallStandard(HYPRE_StructPFMGSetup,(ex->hsolver,mx->hmat,mx->hb,mx->hx));
2383   PetscStackCallStandard(HYPRE_StructPFMGSetZeroGuess,(ex->hsolver));
2384   PetscFunctionReturn(0);
2385 }
2386 
2387 /*MC
2388      PCPFMG - the hypre PFMG multigrid solver
2389 
2390    Level: advanced
2391 
2392    Options Database:
2393 + -pc_pfmg_its <its> number of iterations of PFMG to use as preconditioner
2394 . -pc_pfmg_num_pre_relax <steps> number of smoothing steps before coarse grid
2395 . -pc_pfmg_num_post_relax <steps> number of smoothing steps after coarse grid
2396 . -pc_pfmg_tol <tol> tolerance of PFMG
2397 . -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
2398 - -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin
2399 
2400    Notes:
2401     This is for CELL-centered descretizations
2402 
2403            This must be used with the MATHYPRESTRUCT matrix type.
2404            This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA.
2405 
2406 .seealso:  PCMG, MATHYPRESTRUCT
2407 M*/
2408 
2409 PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc)
2410 {
2411   PetscErrorCode ierr;
2412   PC_PFMG        *ex;
2413 
2414   PetscFunctionBegin;
2415   ierr     = PetscNew(&ex);CHKERRQ(ierr); \
2416   pc->data = ex;
2417 
2418   ex->its            = 1;
2419   ex->tol            = 1.e-8;
2420   ex->relax_type     = 1;
2421   ex->rap_type       = 0;
2422   ex->num_pre_relax  = 1;
2423   ex->num_post_relax = 1;
2424   ex->max_levels     = 0;
2425 
2426   pc->ops->setfromoptions  = PCSetFromOptions_PFMG;
2427   pc->ops->view            = PCView_PFMG;
2428   pc->ops->destroy         = PCDestroy_PFMG;
2429   pc->ops->apply           = PCApply_PFMG;
2430   pc->ops->applyrichardson = PCApplyRichardson_PFMG;
2431   pc->ops->setup           = PCSetUp_PFMG;
2432 
2433   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ex->hcomm));CHKERRMPI(ierr);
2434   PetscStackCallStandard(HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver));
2435   PetscFunctionReturn(0);
2436 }
2437 
2438 /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/
2439 
2440 /* we know we are working with a HYPRE_SStructMatrix */
2441 typedef struct {
2442   MPI_Comm            hcomm;       /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */
2443   HYPRE_SStructSolver ss_solver;
2444 
2445   /* keep copy of SYSPFMG options used so may view them */
2446   PetscInt its;
2447   double   tol;
2448   PetscInt relax_type;
2449   PetscInt num_pre_relax,num_post_relax;
2450 } PC_SysPFMG;
2451 
2452 PetscErrorCode PCDestroy_SysPFMG(PC pc)
2453 {
2454   PetscErrorCode ierr;
2455   PC_SysPFMG     *ex = (PC_SysPFMG*) pc->data;
2456 
2457   PetscFunctionBegin;
2458   if (ex->ss_solver) PetscStackCallStandard(HYPRE_SStructSysPFMGDestroy,(ex->ss_solver));
2459   ierr = MPI_Comm_free(&ex->hcomm);CHKERRMPI(ierr);
2460   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2461   PetscFunctionReturn(0);
2462 }
2463 
2464 static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"};
2465 
2466 PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer)
2467 {
2468   PetscErrorCode ierr;
2469   PetscBool      iascii;
2470   PC_SysPFMG     *ex = (PC_SysPFMG*) pc->data;
2471 
2472   PetscFunctionBegin;
2473   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2474   if (iascii) {
2475     ierr = PetscViewerASCIIPrintf(viewer,"  HYPRE SysPFMG preconditioning\n");CHKERRQ(ierr);
2476     ierr = PetscViewerASCIIPrintf(viewer,"  max iterations %d\n",ex->its);CHKERRQ(ierr);
2477     ierr = PetscViewerASCIIPrintf(viewer,"  tolerance %g\n",ex->tol);CHKERRQ(ierr);
2478     ierr = PetscViewerASCIIPrintf(viewer,"  relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr);
2479     ierr = PetscViewerASCIIPrintf(viewer,"  number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr);
2480   }
2481   PetscFunctionReturn(0);
2482 }
2483 
2484 PetscErrorCode PCSetFromOptions_SysPFMG(PetscOptionItems *PetscOptionsObject,PC pc)
2485 {
2486   PetscErrorCode ierr;
2487   PC_SysPFMG     *ex = (PC_SysPFMG*) pc->data;
2488   PetscBool      flg = PETSC_FALSE;
2489 
2490   PetscFunctionBegin;
2491   ierr = PetscOptionsHead(PetscOptionsObject,"SysPFMG options");CHKERRQ(ierr);
2492   ierr = PetscOptionsBool("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,NULL);CHKERRQ(ierr);
2493   if (flg) {
2494     PetscStackCallStandard(HYPRE_SStructSysPFMGSetPrintLevel,(ex->ss_solver,3));
2495   }
2496   ierr = PetscOptionsInt("-pc_syspfmg_its","Number of iterations of SysPFMG to use as preconditioner","HYPRE_SStructSysPFMGSetMaxIter",ex->its,&ex->its,NULL);CHKERRQ(ierr);
2497   PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(ex->ss_solver,ex->its));
2498   ierr = PetscOptionsInt("-pc_syspfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_SStructSysPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,NULL);CHKERRQ(ierr);
2499   PetscStackCallStandard(HYPRE_SStructSysPFMGSetNumPreRelax,(ex->ss_solver,ex->num_pre_relax));
2500   ierr = PetscOptionsInt("-pc_syspfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_SStructSysPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,NULL);CHKERRQ(ierr);
2501   PetscStackCallStandard(HYPRE_SStructSysPFMGSetNumPostRelax,(ex->ss_solver,ex->num_post_relax));
2502 
2503   ierr = PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,NULL);CHKERRQ(ierr);
2504   PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(ex->ss_solver,ex->tol));
2505   ierr = PetscOptionsEList("-pc_syspfmg_relax_type","Relax type for the up and down cycles","HYPRE_SStructSysPFMGSetRelaxType",SysPFMGRelaxType,ALEN(SysPFMGRelaxType),SysPFMGRelaxType[ex->relax_type],&ex->relax_type,NULL);CHKERRQ(ierr);
2506   PetscStackCallStandard(HYPRE_SStructSysPFMGSetRelaxType,(ex->ss_solver, ex->relax_type));
2507   ierr = PetscOptionsTail();CHKERRQ(ierr);
2508   PetscFunctionReturn(0);
2509 }
2510 
2511 PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y)
2512 {
2513   PetscErrorCode    ierr;
2514   PC_SysPFMG        *ex = (PC_SysPFMG*) pc->data;
2515   PetscScalar       *yy;
2516   const PetscScalar *xx;
2517   PetscInt          ilower[3],iupper[3];
2518   HYPRE_Int         hlower[3],hupper[3];
2519   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(pc->pmat->data);
2520   PetscInt          ordering= mx->dofs_order;
2521   PetscInt          nvars   = mx->nvars;
2522   PetscInt          part    = 0;
2523   PetscInt          size;
2524   PetscInt          i;
2525 
2526   PetscFunctionBegin;
2527   ierr       = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
2528   ierr       = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
2529   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
2530   iupper[0] += ilower[0] - 1;
2531   iupper[1] += ilower[1] - 1;
2532   iupper[2] += ilower[2] - 1;
2533   hlower[0]  = (HYPRE_Int)ilower[0];
2534   hlower[1]  = (HYPRE_Int)ilower[1];
2535   hlower[2]  = (HYPRE_Int)ilower[2];
2536   hupper[0]  = (HYPRE_Int)iupper[0];
2537   hupper[1]  = (HYPRE_Int)iupper[1];
2538   hupper[2]  = (HYPRE_Int)iupper[2];
2539 
2540   size = 1;
2541   for (i= 0; i< 3; i++) size *= (iupper[i]-ilower[i]+1);
2542 
2543   /* copy x values over to hypre for variable ordering */
2544   if (ordering) {
2545     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
2546     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
2547     for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(xx+(size*i))));
2548     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
2549     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
2550     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
2551     PetscStackCallStandard(HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x));
2552 
2553     /* copy solution values back to PETSc */
2554     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
2555     for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(yy+(size*i))));
2556     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
2557   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
2558     PetscScalar *z;
2559     PetscInt    j, k;
2560 
2561     ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr);
2562     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
2563     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
2564 
2565     /* transform nodal to hypre's variable ordering for sys_pfmg */
2566     for (i= 0; i< size; i++) {
2567       k= i*nvars;
2568       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
2569     }
2570     for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i))));
2571     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
2572     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
2573     PetscStackCallStandard(HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x));
2574 
2575     /* copy solution values back to PETSc */
2576     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
2577     for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i))));
2578     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
2579     for (i= 0; i< size; i++) {
2580       k= i*nvars;
2581       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
2582     }
2583     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
2584     ierr = PetscFree(z);CHKERRQ(ierr);
2585   }
2586   PetscFunctionReturn(0);
2587 }
2588 
2589 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)
2590 {
2591   PC_SysPFMG     *jac = (PC_SysPFMG*)pc->data;
2592   PetscErrorCode ierr;
2593   HYPRE_Int      oits;
2594 
2595   PetscFunctionBegin;
2596   ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr);
2597   PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,its*jac->its));
2598   PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,rtol));
2599   ierr = PCApply_SysPFMG(pc,b,y);CHKERRQ(ierr);
2600   PetscStackCallStandard(HYPRE_SStructSysPFMGGetNumIterations,(jac->ss_solver,&oits));
2601   *outits = oits;
2602   if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS;
2603   else             *reason = PCRICHARDSON_CONVERGED_RTOL;
2604   PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,jac->tol));
2605   PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,jac->its));
2606   PetscFunctionReturn(0);
2607 }
2608 
2609 PetscErrorCode PCSetUp_SysPFMG(PC pc)
2610 {
2611   PetscErrorCode   ierr;
2612   PC_SysPFMG       *ex = (PC_SysPFMG*) pc->data;
2613   Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(pc->pmat->data);
2614   PetscBool        flg;
2615 
2616   PetscFunctionBegin;
2617   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg);CHKERRQ(ierr);
2618   if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner");
2619 
2620   /* create the hypre sstruct solver object and set its information */
2621   if (ex->ss_solver) PetscStackCallStandard(HYPRE_SStructSysPFMGDestroy,(ex->ss_solver));
2622   PetscStackCallStandard(HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver));
2623   PetscStackCallStandard(HYPRE_SStructSysPFMGSetZeroGuess,(ex->ss_solver));
2624   PetscStackCallStandard(HYPRE_SStructSysPFMGSetup,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x));
2625   PetscFunctionReturn(0);
2626 }
2627 
2628 /*MC
2629      PCSysPFMG - the hypre SysPFMG multigrid solver
2630 
2631    Level: advanced
2632 
2633    Options Database:
2634 + -pc_syspfmg_its <its> number of iterations of SysPFMG to use as preconditioner
2635 . -pc_syspfmg_num_pre_relax <steps> number of smoothing steps before coarse grid
2636 . -pc_syspfmg_num_post_relax <steps> number of smoothing steps after coarse grid
2637 . -pc_syspfmg_tol <tol> tolerance of SysPFMG
2638 - -pc_syspfmg_relax_type -relaxation type for the up and down cycles, one of Weighted-Jacobi,Red/Black-Gauss-Seidel
2639 
2640    Notes:
2641     This is for CELL-centered descretizations
2642 
2643            This must be used with the MATHYPRESSTRUCT matrix type.
2644            This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA.
2645            Also, only cell-centered variables.
2646 
2647 .seealso:  PCMG, MATHYPRESSTRUCT
2648 M*/
2649 
2650 PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc)
2651 {
2652   PetscErrorCode ierr;
2653   PC_SysPFMG     *ex;
2654 
2655   PetscFunctionBegin;
2656   ierr     = PetscNew(&ex);CHKERRQ(ierr); \
2657   pc->data = ex;
2658 
2659   ex->its            = 1;
2660   ex->tol            = 1.e-8;
2661   ex->relax_type     = 1;
2662   ex->num_pre_relax  = 1;
2663   ex->num_post_relax = 1;
2664 
2665   pc->ops->setfromoptions  = PCSetFromOptions_SysPFMG;
2666   pc->ops->view            = PCView_SysPFMG;
2667   pc->ops->destroy         = PCDestroy_SysPFMG;
2668   pc->ops->apply           = PCApply_SysPFMG;
2669   pc->ops->applyrichardson = PCApplyRichardson_SysPFMG;
2670   pc->ops->setup           = PCSetUp_SysPFMG;
2671 
2672   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ex->hcomm));CHKERRMPI(ierr);
2673   PetscStackCallStandard(HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver));
2674   PetscFunctionReturn(0);
2675 }
2676