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 EXTERN_C_BEGIN 995 #undef __FUNCT__ 996 #define __FUNCT__ "PCCreate_HYPRE" 997 PetscErrorCode PCCreate_HYPRE(PC pc) 998 { 999 PC_HYPRE *jac; 1000 PetscErrorCode ierr; 1001 1002 PetscFunctionBegin; 1003 ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr); 1004 1005 pc->data = jac; 1006 pc->ops->destroy = PCDestroy_HYPRE; 1007 pc->ops->setfromoptions = PCSetFromOptions_HYPRE; 1008 pc->ops->setup = PCSetUp_HYPRE; 1009 pc->ops->apply = PCApply_HYPRE; 1010 jac->comm_hypre = MPI_COMM_NULL; 1011 jac->hypre_type = NULL; 1012 /* duplicate communicator for hypre */ 1013 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(jac->comm_hypre));CHKERRQ(ierr); 1014 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr); 1015 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr); 1016 PetscFunctionReturn(0); 1017 } 1018 EXTERN_C_END 1019 1020 /* ---------------------------------------------------------------------------------------------------------------------------------*/ 1021 1022 /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */ 1023 #include <petsc-private/matimpl.h> 1024 1025 typedef struct { 1026 MPI_Comm hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */ 1027 HYPRE_StructSolver hsolver; 1028 1029 /* keep copy of PFMG options used so may view them */ 1030 PetscInt its; 1031 double tol; 1032 PetscInt relax_type; 1033 PetscInt rap_type; 1034 PetscInt num_pre_relax,num_post_relax; 1035 PetscInt max_levels; 1036 } PC_PFMG; 1037 1038 #undef __FUNCT__ 1039 #define __FUNCT__ "PCDestroy_PFMG" 1040 PetscErrorCode PCDestroy_PFMG(PC pc) 1041 { 1042 PetscErrorCode ierr; 1043 PC_PFMG *ex = (PC_PFMG*) pc->data; 1044 1045 PetscFunctionBegin; 1046 if (ex->hsolver) PetscStackCallStandard(HYPRE_StructPFMGDestroy,(ex->hsolver)); 1047 ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr); 1048 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1049 PetscFunctionReturn(0); 1050 } 1051 1052 static const char *PFMGRelaxType[] = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"}; 1053 static const char *PFMGRAPType[] = {"Galerkin","non-Galerkin"}; 1054 1055 #undef __FUNCT__ 1056 #define __FUNCT__ "PCView_PFMG" 1057 PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer) 1058 { 1059 PetscErrorCode ierr; 1060 PetscBool iascii; 1061 PC_PFMG *ex = (PC_PFMG*) pc->data; 1062 1063 PetscFunctionBegin; 1064 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1065 if (iascii) { 1066 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG preconditioning\n");CHKERRQ(ierr); 1067 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: max iterations %d\n",ex->its);CHKERRQ(ierr); 1068 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr); 1069 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr); 1070 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: RAP type %s\n",PFMGRAPType[ex->rap_type]);CHKERRQ(ierr); 1071 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr); 1072 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: max levels %d\n",ex->max_levels);CHKERRQ(ierr); 1073 } 1074 PetscFunctionReturn(0); 1075 } 1076 1077 1078 #undef __FUNCT__ 1079 #define __FUNCT__ "PCSetFromOptions_PFMG" 1080 PetscErrorCode PCSetFromOptions_PFMG(PC pc) 1081 { 1082 PetscErrorCode ierr; 1083 PC_PFMG *ex = (PC_PFMG*) pc->data; 1084 PetscBool flg = PETSC_FALSE; 1085 1086 PetscFunctionBegin; 1087 ierr = PetscOptionsHead("PFMG options");CHKERRQ(ierr); 1088 ierr = PetscOptionsBool("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",flg,&flg,NULL);CHKERRQ(ierr); 1089 if (flg) { 1090 int level=3; 1091 PetscStackCallStandard(HYPRE_StructPFMGSetPrintLevel,(ex->hsolver,level)); 1092 } 1093 ierr = PetscOptionsInt("-pc_pfmg_its","Number of iterations of PFMG to use as preconditioner","HYPRE_StructPFMGSetMaxIter",ex->its,&ex->its,NULL);CHKERRQ(ierr); 1094 PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(ex->hsolver,ex->its)); 1095 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); 1096 PetscStackCallStandard(HYPRE_StructPFMGSetNumPreRelax,(ex->hsolver,ex->num_pre_relax)); 1097 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); 1098 PetscStackCallStandard(HYPRE_StructPFMGSetNumPostRelax,(ex->hsolver,ex->num_post_relax)); 1099 1100 ierr = PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,NULL);CHKERRQ(ierr); 1101 PetscStackCallStandard(HYPRE_StructPFMGSetMaxLevels,(ex->hsolver,ex->max_levels)); 1102 1103 ierr = PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,NULL);CHKERRQ(ierr); 1104 PetscStackCallStandard(HYPRE_StructPFMGSetTol,(ex->hsolver,ex->tol)); 1105 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); 1106 PetscStackCallStandard(HYPRE_StructPFMGSetRelaxType,(ex->hsolver, ex->relax_type)); 1107 ierr = PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,ALEN(PFMGRAPType),PFMGRAPType[ex->rap_type],&ex->rap_type,NULL);CHKERRQ(ierr); 1108 PetscStackCallStandard(HYPRE_StructPFMGSetRAPType,(ex->hsolver, ex->rap_type)); 1109 ierr = PetscOptionsTail();CHKERRQ(ierr); 1110 PetscFunctionReturn(0); 1111 } 1112 1113 #undef __FUNCT__ 1114 #define __FUNCT__ "PCApply_PFMG" 1115 PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y) 1116 { 1117 PetscErrorCode ierr; 1118 PC_PFMG *ex = (PC_PFMG*) pc->data; 1119 PetscScalar *xx,*yy; 1120 PetscInt ilower[3],iupper[3]; 1121 Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data); 1122 1123 PetscFunctionBegin; 1124 ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 1125 iupper[0] += ilower[0] - 1; 1126 iupper[1] += ilower[1] - 1; 1127 iupper[2] += ilower[2] - 1; 1128 1129 /* copy x values over to hypre */ 1130 PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0)); 1131 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1132 PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,ilower,iupper,xx)); 1133 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1134 PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb)); 1135 PetscStackCallStandard(HYPRE_StructPFMGSolve,(ex->hsolver,mx->hmat,mx->hb,mx->hx)); 1136 1137 /* copy solution values back to PETSc */ 1138 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1139 PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,ilower,iupper,yy)); 1140 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1141 PetscFunctionReturn(0); 1142 } 1143 1144 #undef __FUNCT__ 1145 #define __FUNCT__ "PCApplyRichardson_PFMG" 1146 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) 1147 { 1148 PC_PFMG *jac = (PC_PFMG*)pc->data; 1149 PetscErrorCode ierr; 1150 PetscInt oits; 1151 1152 PetscFunctionBegin; 1153 PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(jac->hsolver,its*jac->its)); 1154 PetscStackCallStandard(HYPRE_StructPFMGSetTol,(jac->hsolver,rtol)); 1155 1156 ierr = PCApply_PFMG(pc,b,y);CHKERRQ(ierr); 1157 PetscStackCallStandard(HYPRE_StructPFMGGetNumIterations,(jac->hsolver,&oits)); 1158 *outits = oits; 1159 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 1160 else *reason = PCRICHARDSON_CONVERGED_RTOL; 1161 PetscStackCallStandard(HYPRE_StructPFMGSetTol,(jac->hsolver,jac->tol)); 1162 PetscStackCallStandard(HYPRE_StructPFMGSetMaxIter,(jac->hsolver,jac->its)); 1163 PetscFunctionReturn(0); 1164 } 1165 1166 1167 #undef __FUNCT__ 1168 #define __FUNCT__ "PCSetUp_PFMG" 1169 PetscErrorCode PCSetUp_PFMG(PC pc) 1170 { 1171 PetscErrorCode ierr; 1172 PC_PFMG *ex = (PC_PFMG*) pc->data; 1173 Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(pc->pmat->data); 1174 PetscBool flg; 1175 1176 PetscFunctionBegin; 1177 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg);CHKERRQ(ierr); 1178 if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner"); 1179 1180 /* create the hypre solver object and set its information */ 1181 if (ex->hsolver) PetscStackCallStandard(HYPRE_StructPFMGDestroy,(ex->hsolver)); 1182 PetscStackCallStandard(HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver)); 1183 ierr = PCSetFromOptions_PFMG(pc);CHKERRQ(ierr); 1184 PetscStackCallStandard(HYPRE_StructPFMGSetup,(ex->hsolver,mx->hmat,mx->hb,mx->hx)); 1185 PetscStackCallStandard(HYPRE_StructPFMGSetZeroGuess,(ex->hsolver)); 1186 PetscFunctionReturn(0); 1187 } 1188 1189 1190 /*MC 1191 PCPFMG - the hypre PFMG multigrid solver 1192 1193 Level: advanced 1194 1195 Options Database: 1196 + -pc_pfmg_its <its> number of iterations of PFMG to use as preconditioner 1197 . -pc_pfmg_num_pre_relax <steps> number of smoothing steps before coarse grid 1198 . -pc_pfmg_num_post_relax <steps> number of smoothing steps after coarse grid 1199 . -pc_pfmg_tol <tol> tolerance of PFMG 1200 . -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 1201 - -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin 1202 1203 Notes: This is for CELL-centered descretizations 1204 1205 This must be used with the MATHYPRESTRUCT matrix type. 1206 This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA. 1207 1208 .seealso: PCMG, MATHYPRESTRUCT 1209 M*/ 1210 1211 EXTERN_C_BEGIN 1212 #undef __FUNCT__ 1213 #define __FUNCT__ "PCCreate_PFMG" 1214 PetscErrorCode PCCreate_PFMG(PC pc) 1215 { 1216 PetscErrorCode ierr; 1217 PC_PFMG *ex; 1218 1219 PetscFunctionBegin; 1220 ierr = PetscNew(PC_PFMG,&ex);CHKERRQ(ierr); \ 1221 pc->data = ex; 1222 1223 ex->its = 1; 1224 ex->tol = 1.e-8; 1225 ex->relax_type = 1; 1226 ex->rap_type = 0; 1227 ex->num_pre_relax = 1; 1228 ex->num_post_relax = 1; 1229 ex->max_levels = 0; 1230 1231 pc->ops->setfromoptions = PCSetFromOptions_PFMG; 1232 pc->ops->view = PCView_PFMG; 1233 pc->ops->destroy = PCDestroy_PFMG; 1234 pc->ops->apply = PCApply_PFMG; 1235 pc->ops->applyrichardson = PCApplyRichardson_PFMG; 1236 pc->ops->setup = PCSetUp_PFMG; 1237 1238 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ex->hcomm));CHKERRQ(ierr); 1239 PetscStackCallStandard(HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver)); 1240 PetscFunctionReturn(0); 1241 } 1242 EXTERN_C_END 1243 1244 /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/ 1245 1246 /* we know we are working with a HYPRE_SStructMatrix */ 1247 typedef struct { 1248 MPI_Comm hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */ 1249 HYPRE_SStructSolver ss_solver; 1250 1251 /* keep copy of SYSPFMG options used so may view them */ 1252 PetscInt its; 1253 double tol; 1254 PetscInt relax_type; 1255 PetscInt num_pre_relax,num_post_relax; 1256 } PC_SysPFMG; 1257 1258 #undef __FUNCT__ 1259 #define __FUNCT__ "PCDestroy_SysPFMG" 1260 PetscErrorCode PCDestroy_SysPFMG(PC pc) 1261 { 1262 PetscErrorCode ierr; 1263 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1264 1265 PetscFunctionBegin; 1266 if (ex->ss_solver) PetscStackCallStandard(HYPRE_SStructSysPFMGDestroy,(ex->ss_solver)); 1267 ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr); 1268 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1269 PetscFunctionReturn(0); 1270 } 1271 1272 static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"}; 1273 1274 #undef __FUNCT__ 1275 #define __FUNCT__ "PCView_SysPFMG" 1276 PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer) 1277 { 1278 PetscErrorCode ierr; 1279 PetscBool iascii; 1280 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1281 1282 PetscFunctionBegin; 1283 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1284 if (iascii) { 1285 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG preconditioning\n");CHKERRQ(ierr); 1286 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: max iterations %d\n",ex->its);CHKERRQ(ierr); 1287 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr); 1288 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr); 1289 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr); 1290 } 1291 PetscFunctionReturn(0); 1292 } 1293 1294 1295 #undef __FUNCT__ 1296 #define __FUNCT__ "PCSetFromOptions_SysPFMG" 1297 PetscErrorCode PCSetFromOptions_SysPFMG(PC pc) 1298 { 1299 PetscErrorCode ierr; 1300 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1301 PetscBool flg = PETSC_FALSE; 1302 1303 PetscFunctionBegin; 1304 ierr = PetscOptionsHead("SysPFMG options");CHKERRQ(ierr); 1305 ierr = PetscOptionsBool("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,NULL);CHKERRQ(ierr); 1306 if (flg) { 1307 int level=3; 1308 PetscStackCallStandard(HYPRE_SStructSysPFMGSetPrintLevel,(ex->ss_solver,level)); 1309 } 1310 ierr = PetscOptionsInt("-pc_syspfmg_its","Number of iterations of SysPFMG to use as preconditioner","HYPRE_SStructSysPFMGSetMaxIter",ex->its,&ex->its,NULL);CHKERRQ(ierr); 1311 PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(ex->ss_solver,ex->its)); 1312 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); 1313 PetscStackCallStandard(HYPRE_SStructSysPFMGSetNumPreRelax,(ex->ss_solver,ex->num_pre_relax)); 1314 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); 1315 PetscStackCallStandard(HYPRE_SStructSysPFMGSetNumPostRelax,(ex->ss_solver,ex->num_post_relax)); 1316 1317 ierr = PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,NULL);CHKERRQ(ierr); 1318 PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(ex->ss_solver,ex->tol)); 1319 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); 1320 PetscStackCallStandard(HYPRE_SStructSysPFMGSetRelaxType,(ex->ss_solver, ex->relax_type)); 1321 ierr = PetscOptionsTail();CHKERRQ(ierr); 1322 PetscFunctionReturn(0); 1323 } 1324 1325 #undef __FUNCT__ 1326 #define __FUNCT__ "PCApply_SysPFMG" 1327 PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y) 1328 { 1329 PetscErrorCode ierr; 1330 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1331 PetscScalar *xx,*yy; 1332 PetscInt ilower[3],iupper[3]; 1333 Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(pc->pmat->data); 1334 PetscInt ordering= mx->dofs_order; 1335 PetscInt nvars = mx->nvars; 1336 PetscInt part = 0; 1337 PetscInt size; 1338 PetscInt i; 1339 1340 PetscFunctionBegin; 1341 ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 1342 iupper[0] += ilower[0] - 1; 1343 iupper[1] += ilower[1] - 1; 1344 iupper[2] += ilower[2] - 1; 1345 1346 size = 1; 1347 for (i= 0; i< 3; i++) size *= (iupper[i]-ilower[i]+1); 1348 1349 /* copy x values over to hypre for variable ordering */ 1350 if (ordering) { 1351 PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 1352 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1353 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,xx+(size*i))); 1354 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1355 PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b)); 1356 PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x)); 1357 PetscStackCallStandard(HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1358 1359 /* copy solution values back to PETSc */ 1360 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1361 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,yy+(size*i))); 1362 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1363 } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */ 1364 PetscScalar *z; 1365 PetscInt j, k; 1366 1367 ierr = PetscMalloc(nvars*size*sizeof(PetscScalar),&z);CHKERRQ(ierr); 1368 PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 1369 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1370 1371 /* transform nodal to hypre's variable ordering for sys_pfmg */ 1372 for (i= 0; i< size; i++) { 1373 k= i*nvars; 1374 for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j]; 1375 } 1376 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,z+(size*i))); 1377 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1378 PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b)); 1379 PetscStackCallStandard(HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1380 1381 /* copy solution values back to PETSc */ 1382 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1383 for (i= 0; i< nvars; i++) PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,z+(size*i))); 1384 /* transform hypre's variable ordering for sys_pfmg to nodal ordering */ 1385 for (i= 0; i< size; i++) { 1386 k= i*nvars; 1387 for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i]; 1388 } 1389 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1390 ierr = PetscFree(z);CHKERRQ(ierr); 1391 } 1392 PetscFunctionReturn(0); 1393 } 1394 1395 #undef __FUNCT__ 1396 #define __FUNCT__ "PCApplyRichardson_SysPFMG" 1397 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) 1398 { 1399 PC_SysPFMG *jac = (PC_SysPFMG*)pc->data; 1400 PetscErrorCode ierr; 1401 PetscInt oits; 1402 1403 PetscFunctionBegin; 1404 PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,its*jac->its)); 1405 PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,rtol)); 1406 ierr = PCApply_SysPFMG(pc,b,y);CHKERRQ(ierr); 1407 PetscStackCallStandard(HYPRE_SStructSysPFMGGetNumIterations,(jac->ss_solver,&oits)); 1408 *outits = oits; 1409 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 1410 else *reason = PCRICHARDSON_CONVERGED_RTOL; 1411 PetscStackCallStandard(HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,jac->tol)); 1412 PetscStackCallStandard(HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,jac->its)); 1413 PetscFunctionReturn(0); 1414 } 1415 1416 1417 #undef __FUNCT__ 1418 #define __FUNCT__ "PCSetUp_SysPFMG" 1419 PetscErrorCode PCSetUp_SysPFMG(PC pc) 1420 { 1421 PetscErrorCode ierr; 1422 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1423 Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(pc->pmat->data); 1424 PetscBool flg; 1425 1426 PetscFunctionBegin; 1427 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg);CHKERRQ(ierr); 1428 if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner"); 1429 1430 /* create the hypre sstruct solver object and set its information */ 1431 if (ex->ss_solver) PetscStackCallStandard(HYPRE_SStructSysPFMGDestroy,(ex->ss_solver)); 1432 PetscStackCallStandard(HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver)); 1433 ierr = PCSetFromOptions_SysPFMG(pc);CHKERRQ(ierr); 1434 PetscStackCallStandard(HYPRE_SStructSysPFMGSetZeroGuess,(ex->ss_solver)); 1435 PetscStackCallStandard(HYPRE_SStructSysPFMGSetup,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1436 PetscFunctionReturn(0); 1437 } 1438 1439 1440 /*MC 1441 PCSysPFMG - the hypre SysPFMG multigrid solver 1442 1443 Level: advanced 1444 1445 Options Database: 1446 + -pc_syspfmg_its <its> number of iterations of SysPFMG to use as preconditioner 1447 . -pc_syspfmg_num_pre_relax <steps> number of smoothing steps before coarse grid 1448 . -pc_syspfmg_num_post_relax <steps> number of smoothing steps after coarse grid 1449 . -pc_syspfmg_tol <tol> tolerance of SysPFMG 1450 . -pc_syspfmg_relax_type -relaxation type for the up and down cycles, one of Weighted-Jacobi,Red/Black-Gauss-Seidel 1451 1452 Notes: This is for CELL-centered descretizations 1453 1454 This must be used with the MATHYPRESSTRUCT matrix type. 1455 This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA. 1456 Also, only cell-centered variables. 1457 1458 .seealso: PCMG, MATHYPRESSTRUCT 1459 M*/ 1460 1461 EXTERN_C_BEGIN 1462 #undef __FUNCT__ 1463 #define __FUNCT__ "PCCreate_SysPFMG" 1464 PetscErrorCode PCCreate_SysPFMG(PC pc) 1465 { 1466 PetscErrorCode ierr; 1467 PC_SysPFMG *ex; 1468 1469 PetscFunctionBegin; 1470 ierr = PetscNew(PC_SysPFMG,&ex);CHKERRQ(ierr); \ 1471 pc->data = ex; 1472 1473 ex->its = 1; 1474 ex->tol = 1.e-8; 1475 ex->relax_type = 1; 1476 ex->num_pre_relax = 1; 1477 ex->num_post_relax = 1; 1478 1479 pc->ops->setfromoptions = PCSetFromOptions_SysPFMG; 1480 pc->ops->view = PCView_SysPFMG; 1481 pc->ops->destroy = PCDestroy_SysPFMG; 1482 pc->ops->apply = PCApply_SysPFMG; 1483 pc->ops->applyrichardson = PCApplyRichardson_SysPFMG; 1484 pc->ops->setup = PCSetUp_SysPFMG; 1485 1486 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ex->hcomm));CHKERRQ(ierr); 1487 PetscStackCallStandard(HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver)); 1488 PetscFunctionReturn(0); 1489 } 1490 EXTERN_C_END 1491