1 2 /* 3 Provides an interface to the LLNL package hypre 4 */ 5 6 /* Must use hypre 2.0.0 or more recent. */ 7 8 #include <petsc-private/pcimpl.h> /*I "petscpc.h" I*/ 9 #include <../src/dm/impls/da/hypre/mhyp.h> 10 11 static PetscBool cite = PETSC_FALSE; 12 static const char hypreCitation[] = "@manual{hypre-web-page,\n title = {{\\sl hypre}: High Performance Preconditioners},\n organization = {Lawrence Livermore National Laboratory},\n note = {\\url{http://www.llnl.gov/CASC/hypre/}}\n}\n"; 13 14 /* 15 Private context (data structure) for the preconditioner. 16 */ 17 typedef struct { 18 HYPRE_Solver hsolver; 19 HYPRE_IJMatrix ij; 20 HYPRE_IJVector b,x; 21 22 HYPRE_Int (*destroy)(HYPRE_Solver); 23 HYPRE_Int (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector); 24 HYPRE_Int (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector); 25 26 MPI_Comm comm_hypre; 27 char *hypre_type; 28 29 /* options for Pilut and BoomerAMG*/ 30 PetscInt maxiter; 31 double tol; 32 33 /* options for Pilut */ 34 PetscInt factorrowsize; 35 36 /* options for ParaSails */ 37 PetscInt nlevels; 38 double threshhold; 39 double filter; 40 PetscInt sym; 41 double loadbal; 42 PetscInt logging; 43 PetscInt ruse; 44 PetscInt symt; 45 46 /* options for Euclid */ 47 PetscBool bjilu; 48 PetscInt levels; 49 50 /* options for Euclid and BoomerAMG */ 51 PetscBool printstatistics; 52 53 /* options for BoomerAMG */ 54 PetscInt cycletype; 55 PetscInt maxlevels; 56 double strongthreshold; 57 double maxrowsum; 58 PetscInt gridsweeps[3]; 59 PetscInt coarsentype; 60 PetscInt measuretype; 61 PetscInt relaxtype[3]; 62 double relaxweight; 63 double outerrelaxweight; 64 PetscInt relaxorder; 65 double truncfactor; 66 PetscBool applyrichardson; 67 PetscInt pmax; 68 PetscInt interptype; 69 PetscInt agg_nl; 70 PetscInt agg_num_paths; 71 PetscInt nodal_coarsen; 72 PetscBool nodal_relax; 73 PetscInt nodal_relax_levels; 74 } PC_HYPRE; 75 76 #undef __FUNCT__ 77 #define __FUNCT__ "PCHYPREGetSolver" 78 PetscErrorCode PCHYPREGetSolver(PC pc,HYPRE_Solver *hsolver) 79 { 80 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 81 82 PetscFunctionBegin; 83 *hsolver = jac->hsolver; 84 PetscFunctionReturn(0); 85 } 86 87 #undef __FUNCT__ 88 #define __FUNCT__ "PCSetUp_HYPRE" 89 static PetscErrorCode PCSetUp_HYPRE(PC pc) 90 { 91 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 92 PetscErrorCode ierr; 93 HYPRE_ParCSRMatrix hmat; 94 HYPRE_ParVector bv,xv; 95 PetscInt bs; 96 97 PetscFunctionBegin; 98 if (!jac->hypre_type) { 99 ierr = PCHYPRESetType(pc,"boomeramg");CHKERRQ(ierr); 100 } 101 102 if (pc->setupcalled) { 103 /* always destroy the old matrix and create a new memory; 104 hope this does not churn the memory too much. The problem 105 is I do not know if it is possible to put the matrix back to 106 its initial state so that we can directly copy the values 107 the second time through. */ 108 PetscStackCallStandard(HYPRE_IJMatrixDestroy,(jac->ij)); 109 jac->ij = 0; 110 } 111 112 if (!jac->ij) { /* create the matrix the first time through */ 113 ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr); 114 } 115 if (!jac->b) { /* create the vectors the first time through */ 116 Vec x,b; 117 ierr = MatCreateVecs(pc->pmat,&x,&b);CHKERRQ(ierr); 118 ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr); 119 ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr); 120 ierr = VecDestroy(&x);CHKERRQ(ierr); 121 ierr = VecDestroy(&b);CHKERRQ(ierr); 122 } 123 124 /* special case for BoomerAMG */ 125 if (jac->setup == HYPRE_BoomerAMGSetup) { 126 ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr); 127 if (bs > 1) PetscStackCallStandard(HYPRE_BoomerAMGSetNumFunctions,(jac->hsolver,bs)); 128 }; 129 ierr = MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);CHKERRQ(ierr); 130 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat)); 131 PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->b,(void**)&bv)); 132 PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->x,(void**)&xv)); 133 PetscStackCall("HYPRE_SetupXXX",ierr = (*jac->setup)(jac->hsolver,hmat,bv,xv);CHKERRQ(ierr);); 134 PetscFunctionReturn(0); 135 } 136 137 /* 138 Replaces the address where the HYPRE vector points to its data with the address of 139 PETSc's data. Saves the old address so it can be reset when we are finished with it. 140 Allows use to get the data into a HYPRE vector without the cost of memcopies 141 */ 142 #define HYPREReplacePointer(b,newvalue,savedvalue) { \ 143 hypre_ParVector *par_vector = (hypre_ParVector*)hypre_IJVectorObject(((hypre_IJVector*)b)); \ 144 hypre_Vector *local_vector = hypre_ParVectorLocalVector(par_vector); \ 145 savedvalue = local_vector->data; \ 146 local_vector->data = newvalue; \ 147 } 148 149 #undef __FUNCT__ 150 #define __FUNCT__ "PCApply_HYPRE" 151 static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x) 152 { 153 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 154 PetscErrorCode ierr; 155 HYPRE_ParCSRMatrix hmat; 156 PetscScalar *bv,*xv; 157 HYPRE_ParVector jbv,jxv; 158 PetscScalar *sbv,*sxv; 159 PetscInt hierr; 160 161 PetscFunctionBegin; 162 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 163 if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);} 164 ierr = VecGetArray(b,&bv);CHKERRQ(ierr); 165 ierr = VecGetArray(x,&xv);CHKERRQ(ierr); 166 HYPREReplacePointer(jac->b,bv,sbv); 167 HYPREReplacePointer(jac->x,xv,sxv); 168 169 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat)); 170 PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->b,(void**)&jbv)); 171 PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->x,(void**)&jxv)); 172 PetscStackCall("Hypre solve",hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv); 173 if (hierr && hierr != HYPRE_ERROR_CONV) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr); 174 if (hierr) hypre__global_error = 0;); 175 176 HYPREReplacePointer(jac->b,sbv,bv); 177 HYPREReplacePointer(jac->x,sxv,xv); 178 ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr); 179 ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr); 180 PetscFunctionReturn(0); 181 } 182 183 #undef __FUNCT__ 184 #define __FUNCT__ "PCDestroy_HYPRE" 185 static PetscErrorCode PCDestroy_HYPRE(PC pc) 186 { 187 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 188 PetscErrorCode ierr; 189 190 PetscFunctionBegin; 191 if (jac->ij) PetscStackCallStandard(HYPRE_IJMatrixDestroy,(jac->ij)); 192 if (jac->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(jac->b)); 193 if (jac->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(jac->x)); 194 if (jac->destroy) PetscStackCall("HYPRE_DestroyXXX",ierr = (*jac->destroy)(jac->hsolver);CHKERRQ(ierr);); 195 ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr); 196 if (jac->comm_hypre != MPI_COMM_NULL) { ierr = MPI_Comm_free(&(jac->comm_hypre));CHKERRQ(ierr);} 197 ierr = PetscFree(pc->data);CHKERRQ(ierr); 198 199 ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr); 200 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C",NULL);CHKERRQ(ierr); 201 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C",NULL);CHKERRQ(ierr); 202 PetscFunctionReturn(0); 203 } 204 205 /* --------------------------------------------------------------------------------------------*/ 206 #undef __FUNCT__ 207 #define __FUNCT__ "PCSetFromOptions_HYPRE_Pilut" 208 static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc) 209 { 210 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 211 PetscErrorCode ierr; 212 PetscBool flag; 213 214 PetscFunctionBegin; 215 ierr = PetscOptionsHead("HYPRE Pilut Options");CHKERRQ(ierr); 216 ierr = PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);CHKERRQ(ierr); 217 if (flag) PetscStackCallStandard(HYPRE_ParCSRPilutSetMaxIter,(jac->hsolver,jac->maxiter)); 218 ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr); 219 if (flag) PetscStackCallStandard(HYPRE_ParCSRPilutSetDropTolerance,(jac->hsolver,jac->tol)); 220 ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr); 221 if (flag) PetscStackCallStandard(HYPRE_ParCSRPilutSetFactorRowSize,(jac->hsolver,jac->factorrowsize)); 222 ierr = PetscOptionsTail();CHKERRQ(ierr); 223 PetscFunctionReturn(0); 224 } 225 226 #undef __FUNCT__ 227 #define __FUNCT__ "PCView_HYPRE_Pilut" 228 static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer) 229 { 230 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 231 PetscErrorCode ierr; 232 PetscBool iascii; 233 234 PetscFunctionBegin; 235 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 236 if (iascii) { 237 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut preconditioning\n");CHKERRQ(ierr); 238 if (jac->maxiter != PETSC_DEFAULT) { 239 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr); 240 } else { 241 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default maximum number of iterations \n");CHKERRQ(ierr); 242 } 243 if (jac->tol != PETSC_DEFAULT) { 244 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: drop tolerance %g\n",(double)jac->tol);CHKERRQ(ierr); 245 } else { 246 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default drop tolerance \n");CHKERRQ(ierr); 247 } 248 if (jac->factorrowsize != PETSC_DEFAULT) { 249 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr); 250 } else { 251 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default factor row size \n");CHKERRQ(ierr); 252 } 253 } 254 PetscFunctionReturn(0); 255 } 256 257 /* --------------------------------------------------------------------------------------------*/ 258 #undef __FUNCT__ 259 #define __FUNCT__ "PCSetFromOptions_HYPRE_Euclid" 260 static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc) 261 { 262 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 263 PetscErrorCode ierr; 264 PetscBool flag; 265 char *args[8],levels[16]; 266 PetscInt cnt = 0; 267 268 PetscFunctionBegin; 269 ierr = PetscOptionsHead("HYPRE Euclid Options");CHKERRQ(ierr); 270 ierr = PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);CHKERRQ(ierr); 271 if (flag) { 272 if (jac->levels < 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be nonegative",jac->levels); 273 ierr = PetscSNPrintf(levels,sizeof(levels),"%D",jac->levels);CHKERRQ(ierr); 274 args[cnt++] = (char*)"-level"; args[cnt++] = levels; 275 } 276 ierr = PetscOptionsBool("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,NULL);CHKERRQ(ierr); 277 if (jac->bjilu) { 278 args[cnt++] =(char*) "-bj"; args[cnt++] = (char*)"1"; 279 } 280 281 ierr = PetscOptionsBool("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,NULL);CHKERRQ(ierr); 282 if (jac->printstatistics) { 283 args[cnt++] = (char*)"-eu_stats"; args[cnt++] = (char*)"1"; 284 args[cnt++] = (char*)"-eu_mem"; args[cnt++] = (char*)"1"; 285 } 286 ierr = PetscOptionsTail();CHKERRQ(ierr); 287 if (cnt) PetscStackCallStandard(HYPRE_EuclidSetParams,(jac->hsolver,cnt,args)); 288 PetscFunctionReturn(0); 289 } 290 291 #undef __FUNCT__ 292 #define __FUNCT__ "PCView_HYPRE_Euclid" 293 static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer) 294 { 295 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 296 PetscErrorCode ierr; 297 PetscBool iascii; 298 299 PetscFunctionBegin; 300 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 301 if (iascii) { 302 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid preconditioning\n");CHKERRQ(ierr); 303 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid: number of levels %d\n",jac->levels);CHKERRQ(ierr); 304 if (jac->bjilu) { 305 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");CHKERRQ(ierr); 306 } 307 } 308 PetscFunctionReturn(0); 309 } 310 311 /* --------------------------------------------------------------------------------------------*/ 312 313 #undef __FUNCT__ 314 #define __FUNCT__ "PCApplyTranspose_HYPRE_BoomerAMG" 315 static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x) 316 { 317 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 318 PetscErrorCode ierr; 319 HYPRE_ParCSRMatrix hmat; 320 PetscScalar *bv,*xv; 321 HYPRE_ParVector jbv,jxv; 322 PetscScalar *sbv,*sxv; 323 PetscInt hierr; 324 325 PetscFunctionBegin; 326 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 327 ierr = VecSet(x,0.0);CHKERRQ(ierr); 328 ierr = VecGetArray(b,&bv);CHKERRQ(ierr); 329 ierr = VecGetArray(x,&xv);CHKERRQ(ierr); 330 HYPREReplacePointer(jac->b,bv,sbv); 331 HYPREReplacePointer(jac->x,xv,sxv); 332 333 PetscStackCallStandard(HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat)); 334 PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->b,(void**)&jbv)); 335 PetscStackCallStandard(HYPRE_IJVectorGetObject,(jac->x,(void**)&jxv)); 336 337 hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv); 338 /* error code of 1 in BoomerAMG merely means convergence not achieved */ 339 if (hierr && (hierr != 1)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr); 340 if (hierr) hypre__global_error = 0; 341 342 HYPREReplacePointer(jac->b,sbv,bv); 343 HYPREReplacePointer(jac->x,sxv,xv); 344 ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr); 345 ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr); 346 PetscFunctionReturn(0); 347 } 348 349 /* static array length */ 350 #define ALEN(a) (sizeof(a)/sizeof((a)[0])) 351 352 static const char *HYPREBoomerAMGCycleType[] = {"","V","W"}; 353 static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout", "", "PMIS", "", "HMIS"}; 354 static const char *HYPREBoomerAMGMeasureType[] = {"local","global"}; 355 /* The following corresponds to HYPRE_BoomerAMGSetRelaxType which has many missing numbers in the enum */ 356 static const char *HYPREBoomerAMGRelaxType[] = {"Jacobi","sequential-Gauss-Seidel","seqboundary-Gauss-Seidel","SOR/Jacobi","backward-SOR/Jacobi", 357 "" /* [5] hybrid chaotic Gauss-Seidel (works only with OpenMP) */,"symmetric-SOR/Jacobi", 358 "" /* 7 */,"l1scaled-SOR/Jacobi","Gaussian-elimination", 359 "" /* 10 */, "" /* 11 */, "" /* 12 */, "" /* 13 */, "" /* 14 */, 360 "CG" /* non-stationary */,"Chebyshev","FCF-Jacobi","l1scaled-Jacobi"}; 361 static const char *HYPREBoomerAMGInterpType[] = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i", 362 "ext+i-cc", "standard", "standard-wts", "", "", "FF", "FF1"}; 363 #undef __FUNCT__ 364 #define __FUNCT__ "PCSetFromOptions_HYPRE_BoomerAMG" 365 static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc) 366 { 367 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 368 PetscErrorCode ierr; 369 PetscInt n,indx,level; 370 PetscBool flg, tmp_truth; 371 double tmpdbl, twodbl[2]; 372 373 PetscFunctionBegin; 374 ierr = PetscOptionsHead("HYPRE BoomerAMG Options");CHKERRQ(ierr); 375 ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType+1,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr); 376 if (flg) { 377 jac->cycletype = indx+1; 378 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype)); 379 } 380 ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr); 381 if (flg) { 382 if (jac->maxlevels < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels); 383 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels)); 384 } 385 ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr); 386 if (flg) { 387 if (jac->maxiter < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter); 388 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter)); 389 } 390 ierr = PetscOptionsScalar("-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); 391 if (flg) { 392 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); 393 PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol)); 394 } 395 396 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_truncfactor","Truncation factor for interpolation (0=no truncation)","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr); 397 if (flg) { 398 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); 399 PetscStackCallStandard(HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor)); 400 } 401 402 ierr = PetscOptionsInt("-pc_hypre_boomeramg_P_max","Max elements per row for interpolation operator (0=unlimited)","None",jac->pmax,&jac->pmax,&flg);CHKERRQ(ierr); 403 if (flg) { 404 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); 405 PetscStackCallStandard(HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax)); 406 } 407 408 ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_nl","Number of levels of aggressive coarsening","None",jac->agg_nl,&jac->agg_nl,&flg);CHKERRQ(ierr); 409 if (flg) { 410 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); 411 412 PetscStackCallStandard(HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl)); 413 } 414 415 416 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); 417 if (flg) { 418 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); 419 420 PetscStackCallStandard(HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths)); 421 } 422 423 424 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr); 425 if (flg) { 426 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); 427 PetscStackCallStandard(HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold)); 428 } 429 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr); 430 if (flg) { 431 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); 432 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); 433 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum)); 434 } 435 436 /* Grid sweeps */ 437 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); 438 if (flg) { 439 PetscStackCallStandard(HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver,indx)); 440 /* modify the jac structure so we can view the updated options with PC_View */ 441 jac->gridsweeps[0] = indx; 442 jac->gridsweeps[1] = indx; 443 /*defaults coarse to 1 */ 444 jac->gridsweeps[2] = 1; 445 } 446 447 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[0], &indx,&flg);CHKERRQ(ierr); 448 if (flg) { 449 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 1)); 450 jac->gridsweeps[0] = indx; 451 } 452 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr); 453 if (flg) { 454 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 2)); 455 jac->gridsweeps[1] = indx; 456 } 457 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr); 458 if (flg) { 459 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 3)); 460 jac->gridsweeps[2] = indx; 461 } 462 463 /* Relax type */ 464 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); 465 if (flg) { 466 jac->relaxtype[0] = jac->relaxtype[1] = indx; 467 PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, indx)); 468 /* by default, coarse type set to 9 */ 469 jac->relaxtype[2] = 9; 470 471 } 472 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr); 473 if (flg) { 474 jac->relaxtype[0] = indx; 475 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 1)); 476 } 477 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr); 478 if (flg) { 479 jac->relaxtype[1] = indx; 480 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 2)); 481 } 482 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,ALEN(HYPREBoomerAMGRelaxType),HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr); 483 if (flg) { 484 jac->relaxtype[2] = indx; 485 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 3)); 486 } 487 488 /* Relaxation Weight */ 489 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); 490 if (flg) { 491 PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxWt,(jac->hsolver,tmpdbl)); 492 jac->relaxweight = tmpdbl; 493 } 494 495 n = 2; 496 twodbl[0] = twodbl[1] = 1.0; 497 ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr); 498 if (flg) { 499 if (n == 2) { 500 indx = (int)PetscAbsReal(twodbl[1]); 501 PetscStackCallStandard(HYPRE_BoomerAMGSetLevelRelaxWt,(jac->hsolver,twodbl[0],indx)); 502 } 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); 503 } 504 505 /* Outer relaxation Weight */ 506 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); 507 if (flg) { 508 PetscStackCallStandard(HYPRE_BoomerAMGSetOuterWt,(jac->hsolver, tmpdbl)); 509 jac->outerrelaxweight = tmpdbl; 510 } 511 512 n = 2; 513 twodbl[0] = twodbl[1] = 1.0; 514 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); 515 if (flg) { 516 if (n == 2) { 517 indx = (int)PetscAbsReal(twodbl[1]); 518 PetscStackCallStandard(HYPRE_BoomerAMGSetLevelOuterWt,(jac->hsolver, twodbl[0], indx)); 519 } 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); 520 } 521 522 /* the Relax Order */ 523 ierr = PetscOptionsBool("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 524 525 if (flg && tmp_truth) { 526 jac->relaxorder = 0; 527 PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder)); 528 } 529 ierr = PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,ALEN(HYPREBoomerAMGMeasureType),HYPREBoomerAMGMeasureType[0],&indx,&flg);CHKERRQ(ierr); 530 if (flg) { 531 jac->measuretype = indx; 532 PetscStackCallStandard(HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype)); 533 } 534 /* update list length 3/07 */ 535 ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,ALEN(HYPREBoomerAMGCoarsenType),HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr); 536 if (flg) { 537 jac->coarsentype = indx; 538 PetscStackCallStandard(HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype)); 539 } 540 541 /* new 3/07 */ 542 ierr = PetscOptionsEList("-pc_hypre_boomeramg_interp_type","Interpolation type","None",HYPREBoomerAMGInterpType,ALEN(HYPREBoomerAMGInterpType),HYPREBoomerAMGInterpType[0],&indx,&flg);CHKERRQ(ierr); 543 if (flg) { 544 jac->interptype = indx; 545 PetscStackCallStandard(HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype)); 546 } 547 548 ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr); 549 if (flg) { 550 level = 3; 551 ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,NULL);CHKERRQ(ierr); 552 553 jac->printstatistics = PETSC_TRUE; 554 PetscStackCallStandard(HYPRE_BoomerAMGSetPrintLevel,(jac->hsolver,level)); 555 } 556 557 ierr = PetscOptionsName("-pc_hypre_boomeramg_print_debug","Print debug information","None",&flg);CHKERRQ(ierr); 558 if (flg) { 559 level = 3; 560 ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_debug","Print debug information","None",level,&level,NULL);CHKERRQ(ierr); 561 562 jac->printstatistics = PETSC_TRUE; 563 PetscStackCallStandard(HYPRE_BoomerAMGSetDebugFlag,(jac->hsolver,level)); 564 } 565 566 ierr = PetscOptionsBool("-pc_hypre_boomeramg_nodal_coarsen", "HYPRE_BoomerAMGSetNodal()", "None", jac->nodal_coarsen ? PETSC_TRUE : PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 567 if (flg && tmp_truth) { 568 jac->nodal_coarsen = 1; 569 PetscStackCallStandard(HYPRE_BoomerAMGSetNodal,(jac->hsolver,1)); 570 } 571 572 ierr = PetscOptionsBool("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 573 if (flg && tmp_truth) { 574 PetscInt tmp_int; 575 ierr = PetscOptionsInt("-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg);CHKERRQ(ierr); 576 if (flg) jac->nodal_relax_levels = tmp_int; 577 PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothType,(jac->hsolver,6)); 578 PetscStackCallStandard(HYPRE_BoomerAMGSetDomainType,(jac->hsolver,1)); 579 PetscStackCallStandard(HYPRE_BoomerAMGSetOverlap,(jac->hsolver,0)); 580 PetscStackCallStandard(HYPRE_BoomerAMGSetSmoothNumLevels,(jac->hsolver,jac->nodal_relax_levels)); 581 } 582 583 ierr = PetscOptionsTail();CHKERRQ(ierr); 584 PetscFunctionReturn(0); 585 } 586 587 #undef __FUNCT__ 588 #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG" 589 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) 590 { 591 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 592 PetscErrorCode ierr; 593 PetscInt oits; 594 595 PetscFunctionBegin; 596 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 597 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,its*jac->maxiter)); 598 PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,rtol)); 599 jac->applyrichardson = PETSC_TRUE; 600 ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr); 601 jac->applyrichardson = PETSC_FALSE; 602 PetscStackCallStandard(HYPRE_BoomerAMGGetNumIterations,(jac->hsolver,(HYPRE_Int *)&oits)); 603 *outits = oits; 604 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 605 else *reason = PCRICHARDSON_CONVERGED_RTOL; 606 PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol)); 607 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter)); 608 PetscFunctionReturn(0); 609 } 610 611 612 #undef __FUNCT__ 613 #define __FUNCT__ "PCView_HYPRE_BoomerAMG" 614 static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer) 615 { 616 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 617 PetscErrorCode ierr; 618 PetscBool iascii; 619 620 PetscFunctionBegin; 621 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 622 if (iascii) { 623 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr); 624 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr); 625 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr); 626 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr); 627 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Convergence tolerance PER hypre call %g\n",(double)jac->tol);CHKERRQ(ierr); 628 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Threshold for strong coupling %g\n",(double)jac->strongthreshold);CHKERRQ(ierr); 629 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation truncation factor %g\n",(double)jac->truncfactor);CHKERRQ(ierr); 630 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation: max elements per row %d\n",jac->pmax);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Number of levels of aggressive coarsening %d\n",jac->agg_nl);CHKERRQ(ierr); 632 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Number of paths for aggressive coarsening %d\n",jac->agg_num_paths);CHKERRQ(ierr); 633 634 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum row sums %g\n",(double)jac->maxrowsum);CHKERRQ(ierr); 635 636 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps down %d\n",jac->gridsweeps[0]);CHKERRQ(ierr); 637 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps up %d\n",jac->gridsweeps[1]);CHKERRQ(ierr); 638 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on coarse %d\n",jac->gridsweeps[2]);CHKERRQ(ierr); 639 640 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax down %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr); 641 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax up %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr); 642 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on coarse %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr); 643 644 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax weight (all) %g\n",(double)jac->relaxweight);CHKERRQ(ierr); 645 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Outer relax weight (all) %g\n",(double)jac->outerrelaxweight);CHKERRQ(ierr); 646 647 if (jac->relaxorder) { 648 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr); 649 } else { 650 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr); 651 } 652 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Measure type %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr); 653 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Coarsen type %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr); 654 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation type %s\n",HYPREBoomerAMGInterpType[jac->interptype]);CHKERRQ(ierr); 655 if (jac->nodal_coarsen) { 656 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal coarsening (with HYPRE_BOOMERAMGSetNodal())\n");CHKERRQ(ierr); 657 } 658 if (jac->nodal_relax) { 659 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal relaxation via Schwarz smoothing on levels %d\n",jac->nodal_relax_levels);CHKERRQ(ierr); 660 } 661 } 662 PetscFunctionReturn(0); 663 } 664 665 /* --------------------------------------------------------------------------------------------*/ 666 #undef __FUNCT__ 667 #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails" 668 static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc) 669 { 670 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 671 PetscErrorCode ierr; 672 PetscInt indx; 673 PetscBool flag; 674 const char *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"}; 675 676 PetscFunctionBegin; 677 ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr); 678 ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr); 679 ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr); 680 if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshhold,jac->nlevels)); 681 682 ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr); 683 if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter)); 684 685 ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr); 686 if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal)); 687 688 ierr = PetscOptionsBool("-pc_hypre_parasails_logging","Print info to screen","None",(PetscBool)jac->logging,(PetscBool*)&jac->logging,&flag);CHKERRQ(ierr); 689 if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging)); 690 691 ierr = PetscOptionsBool("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscBool)jac->ruse,(PetscBool*)&jac->ruse,&flag);CHKERRQ(ierr); 692 if (flag) PetscStackCallStandard(HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse)); 693 694 ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,ALEN(symtlist),symtlist[0],&indx,&flag);CHKERRQ(ierr); 695 if (flag) { 696 jac->symt = indx; 697 PetscStackCallStandard(HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt)); 698 } 699 700 ierr = PetscOptionsTail();CHKERRQ(ierr); 701 PetscFunctionReturn(0); 702 } 703 704 #undef __FUNCT__ 705 #define __FUNCT__ "PCView_HYPRE_ParaSails" 706 static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer) 707 { 708 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 709 PetscErrorCode ierr; 710 PetscBool iascii; 711 const char *symt = 0;; 712 713 PetscFunctionBegin; 714 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 715 if (iascii) { 716 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails preconditioning\n");CHKERRQ(ierr); 717 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr); 718 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: threshold %g\n",(double)jac->threshhold);CHKERRQ(ierr); 719 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: filter %g\n",(double)jac->filter);CHKERRQ(ierr); 720 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: load balance %g\n",(double)jac->loadbal);CHKERRQ(ierr); 721 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: reuse nonzero structure %s\n",PetscBools[jac->ruse]);CHKERRQ(ierr); 722 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: print info to screen %s\n",PetscBools[jac->logging]);CHKERRQ(ierr); 723 if (!jac->symt) symt = "nonsymmetric matrix and preconditioner"; 724 else if (jac->symt == 1) symt = "SPD matrix and preconditioner"; 725 else if (jac->symt == 2) symt = "nonsymmetric matrix but SPD preconditioner"; 726 else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt); 727 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr); 728 } 729 PetscFunctionReturn(0); 730 } 731 /* ---------------------------------------------------------------------------------*/ 732 733 #undef __FUNCT__ 734 #define __FUNCT__ "PCHYPREGetType_HYPRE" 735 static PetscErrorCode PCHYPREGetType_HYPRE(PC pc,const char *name[]) 736 { 737 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 738 739 PetscFunctionBegin; 740 *name = jac->hypre_type; 741 PetscFunctionReturn(0); 742 } 743 744 #undef __FUNCT__ 745 #define __FUNCT__ "PCHYPRESetType_HYPRE" 746 static PetscErrorCode PCHYPRESetType_HYPRE(PC pc,const char name[]) 747 { 748 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 749 PetscErrorCode ierr; 750 PetscBool flag; 751 752 PetscFunctionBegin; 753 if (jac->hypre_type) { 754 ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr); 755 if (!flag) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set"); 756 PetscFunctionReturn(0); 757 } else { 758 ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr); 759 } 760 761 jac->maxiter = PETSC_DEFAULT; 762 jac->tol = PETSC_DEFAULT; 763 jac->printstatistics = PetscLogPrintInfo; 764 765 ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr); 766 if (flag) { 767 PetscStackCallStandard(HYPRE_ParCSRPilutCreate,(jac->comm_hypre,&jac->hsolver)); 768 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut; 769 pc->ops->view = PCView_HYPRE_Pilut; 770 jac->destroy = HYPRE_ParCSRPilutDestroy; 771 jac->setup = HYPRE_ParCSRPilutSetup; 772 jac->solve = HYPRE_ParCSRPilutSolve; 773 jac->factorrowsize = PETSC_DEFAULT; 774 PetscFunctionReturn(0); 775 } 776 ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr); 777 if (flag) { 778 PetscStackCallStandard(HYPRE_ParaSailsCreate,(jac->comm_hypre,&jac->hsolver)); 779 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails; 780 pc->ops->view = PCView_HYPRE_ParaSails; 781 jac->destroy = HYPRE_ParaSailsDestroy; 782 jac->setup = HYPRE_ParaSailsSetup; 783 jac->solve = HYPRE_ParaSailsSolve; 784 /* initialize */ 785 jac->nlevels = 1; 786 jac->threshhold = .1; 787 jac->filter = .1; 788 jac->loadbal = 0; 789 if (PetscLogPrintInfo) jac->logging = (int) PETSC_TRUE; 790 else jac->logging = (int) PETSC_FALSE; 791 792 jac->ruse = (int) PETSC_FALSE; 793 jac->symt = 0; 794 PetscStackCallStandard(HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshhold,jac->nlevels)); 795 PetscStackCallStandard(HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter)); 796 PetscStackCallStandard(HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal)); 797 PetscStackCallStandard(HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging)); 798 PetscStackCallStandard(HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse)); 799 PetscStackCallStandard(HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt)); 800 PetscFunctionReturn(0); 801 } 802 ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr); 803 if (flag) { 804 ierr = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver); 805 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid; 806 pc->ops->view = PCView_HYPRE_Euclid; 807 jac->destroy = HYPRE_EuclidDestroy; 808 jac->setup = HYPRE_EuclidSetup; 809 jac->solve = HYPRE_EuclidSolve; 810 /* initialization */ 811 jac->bjilu = PETSC_FALSE; 812 jac->levels = 1; 813 PetscFunctionReturn(0); 814 } 815 ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr); 816 if (flag) { 817 ierr = HYPRE_BoomerAMGCreate(&jac->hsolver); 818 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG; 819 pc->ops->view = PCView_HYPRE_BoomerAMG; 820 pc->ops->applytranspose = PCApplyTranspose_HYPRE_BoomerAMG; 821 pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG; 822 jac->destroy = HYPRE_BoomerAMGDestroy; 823 jac->setup = HYPRE_BoomerAMGSetup; 824 jac->solve = HYPRE_BoomerAMGSolve; 825 jac->applyrichardson = PETSC_FALSE; 826 /* these defaults match the hypre defaults */ 827 jac->cycletype = 1; 828 jac->maxlevels = 25; 829 jac->maxiter = 1; 830 jac->tol = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */ 831 jac->truncfactor = 0.0; 832 jac->strongthreshold = .25; 833 jac->maxrowsum = .9; 834 jac->coarsentype = 6; 835 jac->measuretype = 0; 836 jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1; 837 jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a a PC - most likely with CG */ 838 jac->relaxtype[2] = 9; /*G.E. */ 839 jac->relaxweight = 1.0; 840 jac->outerrelaxweight = 1.0; 841 jac->relaxorder = 1; 842 jac->interptype = 0; 843 jac->agg_nl = 0; 844 jac->pmax = 0; 845 jac->truncfactor = 0.0; 846 jac->agg_num_paths = 1; 847 848 jac->nodal_coarsen = 0; 849 jac->nodal_relax = PETSC_FALSE; 850 jac->nodal_relax_levels = 1; 851 PetscStackCallStandard(HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype)); 852 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels)); 853 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter)); 854 PetscStackCallStandard(HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol)); 855 PetscStackCallStandard(HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor)); 856 PetscStackCallStandard(HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold)); 857 PetscStackCallStandard(HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum)); 858 PetscStackCallStandard(HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype)); 859 PetscStackCallStandard(HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype)); 860 PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder)); 861 PetscStackCallStandard(HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype)); 862 PetscStackCallStandard(HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl)); 863 PetscStackCallStandard(HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax)); 864 PetscStackCallStandard(HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths)); 865 PetscStackCallStandard(HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, jac->relaxtype[0])); /*defaults coarse to 9*/ 866 PetscStackCallStandard(HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver, jac->gridsweeps[0])); /*defaults coarse to 1 */ 867 PetscFunctionReturn(0); 868 } 869 ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr); 870 871 jac->hypre_type = NULL; 872 SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name); 873 PetscFunctionReturn(0); 874 } 875 876 /* 877 It only gets here if the HYPRE type has not been set before the call to 878 ...SetFromOptions() which actually is most of the time 879 */ 880 #undef __FUNCT__ 881 #define __FUNCT__ "PCSetFromOptions_HYPRE" 882 static PetscErrorCode PCSetFromOptions_HYPRE(PC pc) 883 { 884 PetscErrorCode ierr; 885 PetscInt indx; 886 const char *type[] = {"pilut","parasails","boomeramg","euclid"}; 887 PetscBool flg; 888 889 PetscFunctionBegin; 890 ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr); 891 ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"boomeramg",&indx,&flg);CHKERRQ(ierr); 892 if (flg) { 893 ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr); 894 } else { 895 ierr = PCHYPRESetType_HYPRE(pc,"boomeramg");CHKERRQ(ierr); 896 } 897 if (pc->ops->setfromoptions) { 898 ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr); 899 } 900 ierr = PetscOptionsTail();CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 #undef __FUNCT__ 905 #define __FUNCT__ "PCHYPRESetType" 906 /*@C 907 PCHYPRESetType - Sets which hypre preconditioner you wish to use 908 909 Input Parameters: 910 + pc - the preconditioner context 911 - name - either pilut, parasails, boomeramg, euclid 912 913 Options Database Keys: 914 -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 915 916 Level: intermediate 917 918 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 919 PCHYPRE 920 921 @*/ 922 PetscErrorCode PCHYPRESetType(PC pc,const char name[]) 923 { 924 PetscErrorCode ierr; 925 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 928 PetscValidCharPointer(name,2); 929 ierr = PetscTryMethod(pc,"PCHYPRESetType_C",(PC,const char[]),(pc,name));CHKERRQ(ierr); 930 PetscFunctionReturn(0); 931 } 932 933 #undef __FUNCT__ 934 #define __FUNCT__ "PCHYPREGetType" 935 /*@C 936 PCHYPREGetType - Gets which hypre preconditioner you are using 937 938 Input Parameter: 939 . pc - the preconditioner context 940 941 Output Parameter: 942 . name - either pilut, parasails, boomeramg, euclid 943 944 Level: intermediate 945 946 .seealso: PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC, 947 PCHYPRE 948 949 @*/ 950 PetscErrorCode PCHYPREGetType(PC pc,const char *name[]) 951 { 952 PetscErrorCode ierr; 953 954 PetscFunctionBegin; 955 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 956 PetscValidPointer(name,2); 957 ierr = PetscTryMethod(pc,"PCHYPREGetType_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr); 958 PetscFunctionReturn(0); 959 } 960 961 /*MC 962 PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre 963 964 Options Database Keys: 965 + -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 966 - Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX 967 preconditioner 968 969 Level: intermediate 970 971 Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()), 972 the many hypre options can ONLY be set via the options database (e.g. the command line 973 or with PetscOptionsSetValue(), there are no functions to set them) 974 975 The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations 976 (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if 977 -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner 978 (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of 979 iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations 980 and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10 981 then AT MOST twenty V-cycles of boomeramg will be called. 982 983 Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation 984 (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry. 985 Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi. 986 If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly 987 and use -ksp_max_it to control the number of V-cycles. 988 (see the PETSc FAQ.html at the PETSc website under the Documentation tab). 989 990 2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option 991 -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L. 992 993 See PCPFMG for access to the hypre Struct PFMG solver 994 995 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 996 PCHYPRESetType(), PCPFMG 997 998 M*/ 999 1000 #undef __FUNCT__ 1001 #define __FUNCT__ "PCCreate_HYPRE" 1002 PETSC_EXTERN PetscErrorCode PCCreate_HYPRE(PC pc) 1003 { 1004 PC_HYPRE *jac; 1005 PetscErrorCode ierr; 1006 1007 PetscFunctionBegin; 1008 ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 1009 1010 pc->data = jac; 1011 pc->ops->destroy = PCDestroy_HYPRE; 1012 pc->ops->setfromoptions = PCSetFromOptions_HYPRE; 1013 pc->ops->setup = PCSetUp_HYPRE; 1014 pc->ops->apply = PCApply_HYPRE; 1015 jac->comm_hypre = MPI_COMM_NULL; 1016 jac->hypre_type = NULL; 1017 /* duplicate communicator for hypre */ 1018 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(jac->comm_hypre));CHKERRQ(ierr); 1019 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C",PCHYPRESetType_HYPRE);CHKERRQ(ierr); 1020 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C",PCHYPREGetType_HYPRE);CHKERRQ(ierr); 1021 PetscFunctionReturn(0); 1022 } 1023 1024 /* ---------------------------------------------------------------------------------------------------------------------------------*/ 1025 1026 /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */ 1027 #include <petsc-private/matimpl.h> 1028 1029 typedef struct { 1030 MPI_Comm hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */ 1031 HYPRE_StructSolver hsolver; 1032 1033 /* keep copy of PFMG options used so may view them */ 1034 PetscInt its; 1035 double tol; 1036 PetscInt relax_type; 1037 PetscInt rap_type; 1038 PetscInt num_pre_relax,num_post_relax; 1039 PetscInt max_levels; 1040 } PC_PFMG; 1041 1042 #undef __FUNCT__ 1043 #define __FUNCT__ "PCDestroy_PFMG" 1044 PetscErrorCode PCDestroy_PFMG(PC pc) 1045 { 1046 PetscErrorCode ierr; 1047 PC_PFMG *ex = (PC_PFMG*) pc->data; 1048 1049 PetscFunctionBegin; 1050 if (ex->hsolver) PetscStackCallStandard(HYPRE_StructPFMGDestroy,(ex->hsolver)); 1051 ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr); 1052 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1053 PetscFunctionReturn(0); 1054 } 1055 1056 static const char *PFMGRelaxType[] = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"}; 1057 static const char *PFMGRAPType[] = {"Galerkin","non-Galerkin"}; 1058 1059 #undef __FUNCT__ 1060 #define __FUNCT__ "PCView_PFMG" 1061 PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer) 1062 { 1063 PetscErrorCode ierr; 1064 PetscBool iascii; 1065 PC_PFMG *ex = (PC_PFMG*) pc->data; 1066 1067 PetscFunctionBegin; 1068 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1069 if (iascii) { 1070 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG preconditioning\n");CHKERRQ(ierr); 1071 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: max iterations %d\n",ex->its);CHKERRQ(ierr); 1072 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr); 1073 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr); 1074 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: RAP type %s\n",PFMGRAPType[ex->rap_type]);CHKERRQ(ierr); 1075 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr); 1076 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: max levels %d\n",ex->max_levels);CHKERRQ(ierr); 1077 } 1078 PetscFunctionReturn(0); 1079 } 1080 1081 1082 #undef __FUNCT__ 1083 #define __FUNCT__ "PCSetFromOptions_PFMG" 1084 PetscErrorCode PCSetFromOptions_PFMG(PC pc) 1085 { 1086 PetscErrorCode ierr; 1087 PC_PFMG *ex = (PC_PFMG*) pc->data; 1088 PetscBool flg = PETSC_FALSE; 1089 1090 PetscFunctionBegin; 1091 ierr = PetscOptionsHead("PFMG options");CHKERRQ(ierr); 1092 ierr = PetscOptionsBool("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",flg,&flg,NULL);CHKERRQ(ierr); 1093 if (flg) { 1094 int level=3; 1095 PetscStackCallStandard(HYPRE_StructPFMGSetPrintLevel,(ex->hsolver,level)); 1096 } 1097 ierr = PetscOptionsInt("-pc_pfmg_its","Number of iterations of PFMG to use as preconditioner","HYPRE_StructPFMGSetMaxIter",ex->its,&ex->its,NULL);CHKERRQ(ierr); 1098 PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(ex->hsolver,ex->its)); 1099 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); 1100 PetscStackCallStandard(HYPRE_StructPFMGSetNumPreRelax,(ex->hsolver,ex->num_pre_relax)); 1101 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); 1102 PetscStackCallStandard(HYPRE_StructPFMGSetNumPostRelax,(ex->hsolver,ex->num_post_relax)); 1103 1104 ierr = PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,NULL);CHKERRQ(ierr); 1105 PetscStackCallStandard(HYPRE_StructPFMGSetMaxLevels,(ex->hsolver,ex->max_levels)); 1106 1107 ierr = PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,NULL);CHKERRQ(ierr); 1108 PetscStackCallStandard(HYPRE_StructPFMGSetTol,(ex->hsolver,ex->tol)); 1109 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); 1110 PetscStackCallStandard(HYPRE_StructPFMGSetRelaxType,(ex->hsolver, ex->relax_type)); 1111 ierr = PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,ALEN(PFMGRAPType),PFMGRAPType[ex->rap_type],&ex->rap_type,NULL);CHKERRQ(ierr); 1112 PetscStackCallStandard(HYPRE_StructPFMGSetRAPType,(ex->hsolver, ex->rap_type)); 1113 ierr = PetscOptionsTail();CHKERRQ(ierr); 1114 PetscFunctionReturn(0); 1115 } 1116 1117 #undef __FUNCT__ 1118 #define __FUNCT__ "PCApply_PFMG" 1119 PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y) 1120 { 1121 PetscErrorCode ierr; 1122 PC_PFMG *ex = (PC_PFMG*) pc->data; 1123 PetscScalar *xx,*yy; 1124 PetscInt ilower[3],iupper[3]; 1125 Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data); 1126 1127 PetscFunctionBegin; 1128 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 1129 ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 1130 iupper[0] += ilower[0] - 1; 1131 iupper[1] += ilower[1] - 1; 1132 iupper[2] += ilower[2] - 1; 1133 1134 /* copy x values over to hypre */ 1135 PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0)); 1136 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1137 PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,xx)); 1138 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1139 PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb)); 1140 PetscStackCallStandard(HYPRE_StructPFMGSolve,(ex->hsolver,mx->hmat,mx->hb,mx->hx)); 1141 1142 /* copy solution values back to PETSc */ 1143 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1144 PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,yy)); 1145 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 #undef __FUNCT__ 1150 #define __FUNCT__ "PCApplyRichardson_PFMG" 1151 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) 1152 { 1153 PC_PFMG *jac = (PC_PFMG*)pc->data; 1154 PetscErrorCode ierr; 1155 PetscInt oits; 1156 1157 PetscFunctionBegin; 1158 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 1159 PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(jac->hsolver,its*jac->its)); 1160 PetscStackCallStandard(HYPRE_StructPFMGSetTol,(jac->hsolver,rtol)); 1161 1162 ierr = PCApply_PFMG(pc,b,y);CHKERRQ(ierr); 1163 PetscStackCallStandard(HYPRE_StructPFMGGetNumIterations,(jac->hsolver,(HYPRE_Int *)&oits)); 1164 *outits = oits; 1165 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 1166 else *reason = PCRICHARDSON_CONVERGED_RTOL; 1167 PetscStackCallStandard(HYPRE_StructPFMGSetTol,(jac->hsolver,jac->tol)); 1168 PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(jac->hsolver,jac->its)); 1169 PetscFunctionReturn(0); 1170 } 1171 1172 1173 #undef __FUNCT__ 1174 #define __FUNCT__ "PCSetUp_PFMG" 1175 PetscErrorCode PCSetUp_PFMG(PC pc) 1176 { 1177 PetscErrorCode ierr; 1178 PC_PFMG *ex = (PC_PFMG*) pc->data; 1179 Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data); 1180 PetscBool flg; 1181 1182 PetscFunctionBegin; 1183 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg);CHKERRQ(ierr); 1184 if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner"); 1185 1186 /* create the hypre solver object and set its information */ 1187 if (ex->hsolver) PetscStackCallStandard(HYPRE_StructPFMGDestroy,(ex->hsolver)); 1188 PetscStackCallStandard(HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver)); 1189 ierr = PCSetFromOptions_PFMG(pc);CHKERRQ(ierr); 1190 PetscStackCallStandard(HYPRE_StructPFMGSetup,(ex->hsolver,mx->hmat,mx->hb,mx->hx)); 1191 PetscStackCallStandard(HYPRE_StructPFMGSetZeroGuess,(ex->hsolver)); 1192 PetscFunctionReturn(0); 1193 } 1194 1195 1196 /*MC 1197 PCPFMG - the hypre PFMG multigrid solver 1198 1199 Level: advanced 1200 1201 Options Database: 1202 + -pc_pfmg_its <its> number of iterations of PFMG to use as preconditioner 1203 . -pc_pfmg_num_pre_relax <steps> number of smoothing steps before coarse grid 1204 . -pc_pfmg_num_post_relax <steps> number of smoothing steps after coarse grid 1205 . -pc_pfmg_tol <tol> tolerance of PFMG 1206 . -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 1207 - -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin 1208 1209 Notes: This is for CELL-centered descretizations 1210 1211 This must be used with the MATHYPRESTRUCT matrix type. 1212 This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA. 1213 1214 .seealso: PCMG, MATHYPRESTRUCT 1215 M*/ 1216 1217 #undef __FUNCT__ 1218 #define __FUNCT__ "PCCreate_PFMG" 1219 PETSC_EXTERN PetscErrorCode PCCreate_PFMG(PC pc) 1220 { 1221 PetscErrorCode ierr; 1222 PC_PFMG *ex; 1223 1224 PetscFunctionBegin; 1225 ierr = PetscNew(&ex);CHKERRQ(ierr); \ 1226 pc->data = ex; 1227 1228 ex->its = 1; 1229 ex->tol = 1.e-8; 1230 ex->relax_type = 1; 1231 ex->rap_type = 0; 1232 ex->num_pre_relax = 1; 1233 ex->num_post_relax = 1; 1234 ex->max_levels = 0; 1235 1236 pc->ops->setfromoptions = PCSetFromOptions_PFMG; 1237 pc->ops->view = PCView_PFMG; 1238 pc->ops->destroy = PCDestroy_PFMG; 1239 pc->ops->apply = PCApply_PFMG; 1240 pc->ops->applyrichardson = PCApplyRichardson_PFMG; 1241 pc->ops->setup = PCSetUp_PFMG; 1242 1243 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ex->hcomm));CHKERRQ(ierr); 1244 PetscStackCallStandard(HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver)); 1245 PetscFunctionReturn(0); 1246 } 1247 1248 /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/ 1249 1250 /* we know we are working with a HYPRE_SStructMatrix */ 1251 typedef struct { 1252 MPI_Comm hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */ 1253 HYPRE_SStructSolver ss_solver; 1254 1255 /* keep copy of SYSPFMG options used so may view them */ 1256 PetscInt its; 1257 double tol; 1258 PetscInt relax_type; 1259 PetscInt num_pre_relax,num_post_relax; 1260 } PC_SysPFMG; 1261 1262 #undef __FUNCT__ 1263 #define __FUNCT__ "PCDestroy_SysPFMG" 1264 PetscErrorCode PCDestroy_SysPFMG(PC pc) 1265 { 1266 PetscErrorCode ierr; 1267 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1268 1269 PetscFunctionBegin; 1270 if (ex->ss_solver) PetscStackCallStandard(HYPRE_SStructSysPFMGDestroy,(ex->ss_solver)); 1271 ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr); 1272 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1273 PetscFunctionReturn(0); 1274 } 1275 1276 static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"}; 1277 1278 #undef __FUNCT__ 1279 #define __FUNCT__ "PCView_SysPFMG" 1280 PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer) 1281 { 1282 PetscErrorCode ierr; 1283 PetscBool iascii; 1284 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1285 1286 PetscFunctionBegin; 1287 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1288 if (iascii) { 1289 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG preconditioning\n");CHKERRQ(ierr); 1290 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: max iterations %d\n",ex->its);CHKERRQ(ierr); 1291 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr); 1292 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr); 1293 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr); 1294 } 1295 PetscFunctionReturn(0); 1296 } 1297 1298 1299 #undef __FUNCT__ 1300 #define __FUNCT__ "PCSetFromOptions_SysPFMG" 1301 PetscErrorCode PCSetFromOptions_SysPFMG(PC pc) 1302 { 1303 PetscErrorCode ierr; 1304 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1305 PetscBool flg = PETSC_FALSE; 1306 1307 PetscFunctionBegin; 1308 ierr = PetscOptionsHead("SysPFMG options");CHKERRQ(ierr); 1309 ierr = PetscOptionsBool("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,NULL);CHKERRQ(ierr); 1310 if (flg) { 1311 int level=3; 1312 PetscStackCallStandard(HYPRE_SStructSysPFMGSetPrintLevel,(ex->ss_solver,level)); 1313 } 1314 ierr = PetscOptionsInt("-pc_syspfmg_its","Number of iterations of SysPFMG to use as preconditioner","HYPRE_SStructSysPFMGSetMaxIter",ex->its,&ex->its,NULL);CHKERRQ(ierr); 1315 PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(ex->ss_solver,ex->its)); 1316 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); 1317 PetscStackCallStandard(HYPRE_SStructSysPFMGSetNumPreRelax,(ex->ss_solver,ex->num_pre_relax)); 1318 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); 1319 PetscStackCallStandard(HYPRE_SStructSysPFMGSetNumPostRelax,(ex->ss_solver,ex->num_post_relax)); 1320 1321 ierr = PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,NULL);CHKERRQ(ierr); 1322 PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(ex->ss_solver,ex->tol)); 1323 ierr = PetscOptionsEList("-pc_syspfmg_relax_type","Relax type for the up and down cycles","HYPRE_SStructSysPFMGSetRelaxType",SysPFMGRelaxType,4,SysPFMGRelaxType[ex->relax_type],&ex->relax_type,NULL);CHKERRQ(ierr); 1324 PetscStackCallStandard(HYPRE_SStructSysPFMGSetRelaxType,(ex->ss_solver, ex->relax_type)); 1325 ierr = PetscOptionsTail();CHKERRQ(ierr); 1326 PetscFunctionReturn(0); 1327 } 1328 1329 #undef __FUNCT__ 1330 #define __FUNCT__ "PCApply_SysPFMG" 1331 PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y) 1332 { 1333 PetscErrorCode ierr; 1334 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1335 PetscScalar *xx,*yy; 1336 PetscInt ilower[3],iupper[3]; 1337 Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(pc->pmat->data); 1338 PetscInt ordering= mx->dofs_order; 1339 PetscInt nvars = mx->nvars; 1340 PetscInt part = 0; 1341 PetscInt size; 1342 PetscInt i; 1343 1344 PetscFunctionBegin; 1345 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 1346 ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 1347 iupper[0] += ilower[0] - 1; 1348 iupper[1] += ilower[1] - 1; 1349 iupper[2] += ilower[2] - 1; 1350 1351 size = 1; 1352 for (i= 0; i< 3; i++) size *= (iupper[i]-ilower[i]+1); 1353 1354 /* copy x values over to hypre for variable ordering */ 1355 if (ordering) { 1356 PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 1357 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1358 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,xx+(size*i))); 1359 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1360 PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b)); 1361 PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x)); 1362 PetscStackCallStandard(HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1363 1364 /* copy solution values back to PETSc */ 1365 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1366 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,yy+(size*i))); 1367 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1368 } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */ 1369 PetscScalar *z; 1370 PetscInt j, k; 1371 1372 ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr); 1373 PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 1374 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1375 1376 /* transform nodal to hypre's variable ordering for sys_pfmg */ 1377 for (i= 0; i< size; i++) { 1378 k= i*nvars; 1379 for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j]; 1380 } 1381 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i))); 1382 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1383 PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b)); 1384 PetscStackCallStandard(HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1385 1386 /* copy solution values back to PETSc */ 1387 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1388 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i))); 1389 /* transform hypre's variable ordering for sys_pfmg to nodal ordering */ 1390 for (i= 0; i< size; i++) { 1391 k= i*nvars; 1392 for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i]; 1393 } 1394 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1395 ierr = PetscFree(z);CHKERRQ(ierr); 1396 } 1397 PetscFunctionReturn(0); 1398 } 1399 1400 #undef __FUNCT__ 1401 #define __FUNCT__ "PCApplyRichardson_SysPFMG" 1402 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) 1403 { 1404 PC_SysPFMG *jac = (PC_SysPFMG*)pc->data; 1405 PetscErrorCode ierr; 1406 PetscInt oits; 1407 1408 PetscFunctionBegin; 1409 ierr = PetscCitationsRegister(hypreCitation,&cite);CHKERRQ(ierr); 1410 PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,its*jac->its)); 1411 PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,rtol)); 1412 ierr = PCApply_SysPFMG(pc,b,y);CHKERRQ(ierr); 1413 PetscStackCallStandard(HYPRE_SStructSysPFMGGetNumIterations,(jac->ss_solver,(HYPRE_Int *)&oits)); 1414 *outits = oits; 1415 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 1416 else *reason = PCRICHARDSON_CONVERGED_RTOL; 1417 PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,jac->tol)); 1418 PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,jac->its)); 1419 PetscFunctionReturn(0); 1420 } 1421 1422 1423 #undef __FUNCT__ 1424 #define __FUNCT__ "PCSetUp_SysPFMG" 1425 PetscErrorCode PCSetUp_SysPFMG(PC pc) 1426 { 1427 PetscErrorCode ierr; 1428 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1429 Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(pc->pmat->data); 1430 PetscBool flg; 1431 1432 PetscFunctionBegin; 1433 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg);CHKERRQ(ierr); 1434 if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner"); 1435 1436 /* create the hypre sstruct solver object and set its information */ 1437 if (ex->ss_solver) PetscStackCallStandard(HYPRE_SStructSysPFMGDestroy,(ex->ss_solver)); 1438 PetscStackCallStandard(HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver)); 1439 ierr = PCSetFromOptions_SysPFMG(pc);CHKERRQ(ierr); 1440 PetscStackCallStandard(HYPRE_SStructSysPFMGSetZeroGuess,(ex->ss_solver)); 1441 PetscStackCallStandard(HYPRE_SStructSysPFMGSetup,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1442 PetscFunctionReturn(0); 1443 } 1444 1445 1446 /*MC 1447 PCSysPFMG - the hypre SysPFMG multigrid solver 1448 1449 Level: advanced 1450 1451 Options Database: 1452 + -pc_syspfmg_its <its> number of iterations of SysPFMG to use as preconditioner 1453 . -pc_syspfmg_num_pre_relax <steps> number of smoothing steps before coarse grid 1454 . -pc_syspfmg_num_post_relax <steps> number of smoothing steps after coarse grid 1455 . -pc_syspfmg_tol <tol> tolerance of SysPFMG 1456 . -pc_syspfmg_relax_type -relaxation type for the up and down cycles, one of Weighted-Jacobi,Red/Black-Gauss-Seidel 1457 1458 Notes: This is for CELL-centered descretizations 1459 1460 This must be used with the MATHYPRESSTRUCT matrix type. 1461 This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA. 1462 Also, only cell-centered variables. 1463 1464 .seealso: PCMG, MATHYPRESSTRUCT 1465 M*/ 1466 1467 #undef __FUNCT__ 1468 #define __FUNCT__ "PCCreate_SysPFMG" 1469 PETSC_EXTERN PetscErrorCode PCCreate_SysPFMG(PC pc) 1470 { 1471 PetscErrorCode ierr; 1472 PC_SysPFMG *ex; 1473 1474 PetscFunctionBegin; 1475 ierr = PetscNew(&ex);CHKERRQ(ierr); \ 1476 pc->data = ex; 1477 1478 ex->its = 1; 1479 ex->tol = 1.e-8; 1480 ex->relax_type = 1; 1481 ex->num_pre_relax = 1; 1482 ex->num_post_relax = 1; 1483 1484 pc->ops->setfromoptions = PCSetFromOptions_SysPFMG; 1485 pc->ops->view = PCView_SysPFMG; 1486 pc->ops->destroy = PCDestroy_SysPFMG; 1487 pc->ops->apply = PCApply_SysPFMG; 1488 pc->ops->applyrichardson = PCApplyRichardson_SysPFMG; 1489 pc->ops->setup = PCSetUp_SysPFMG; 1490 1491 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ex->hcomm));CHKERRQ(ierr); 1492 PetscStackCallStandard(HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver)); 1493 PetscFunctionReturn(0); 1494 } 1495