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