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