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