1 2 /* -------------------------------------------------------------------- 3 4 This file implements a Jacobi preconditioner in PETSc as part of PC. 5 You can use this as a starting point for implementing your own 6 preconditioner that is not provided with PETSc. (You might also consider 7 just using PCSHELL) 8 9 The following basic routines are required for each preconditioner. 10 PCCreate_XXX() - Creates a preconditioner context 11 PCSetFromOptions_XXX() - Sets runtime options 12 PCApply_XXX() - Applies the preconditioner 13 PCDestroy_XXX() - Destroys the preconditioner context 14 where the suffix "_XXX" denotes a particular implementation, in 15 this case we use _Jacobi (e.g., PCCreate_Jacobi, PCApply_Jacobi). 16 These routines are actually called via the common user interface 17 routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(), 18 so the application code interface remains identical for all 19 preconditioners. 20 21 Another key routine is: 22 PCSetUp_XXX() - Prepares for the use of a preconditioner 23 by setting data structures and options. The interface routine PCSetUp() 24 is not usually called directly by the user, but instead is called by 25 PCApply() if necessary. 26 27 Additional basic routines are: 28 PCView_XXX() - Prints details of runtime options that 29 have actually been used. 30 These are called by application codes via the interface routines 31 PCView(). 32 33 The various types of solvers (preconditioners, Krylov subspace methods, 34 nonlinear solvers, timesteppers) are all organized similarly, so the 35 above description applies to these categories also. One exception is 36 that the analogues of PCApply() for these components are KSPSolve(), 37 SNESSolve(), and TSSolve(). 38 39 Additional optional functionality unique to preconditioners is left and 40 right symmetric preconditioner application via PCApplySymmetricLeft() 41 and PCApplySymmetricRight(). The Jacobi implementation is 42 PCApplySymmetricLeftOrRight_Jacobi(). 43 44 -------------------------------------------------------------------- */ 45 46 /* 47 Include files needed for the Jacobi preconditioner: 48 pcimpl.h - private include file intended for use by all preconditioners 49 */ 50 51 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 52 53 const char *const PCJacobiTypes[] = {"DIAGONAL","ROWMAX","ROWSUM","PCJacobiType","PC_JACOBI_",0}; 54 55 /* 56 Private context (data structure) for the Jacobi preconditioner. 57 */ 58 typedef struct { 59 Vec diag; /* vector containing the reciprocals of the diagonal elements of the preconditioner matrix */ 60 Vec diagsqrt; /* vector containing the reciprocals of the square roots of 61 the diagonal elements of the preconditioner matrix (used 62 only for symmetric preconditioner application) */ 63 PetscBool userowmax; /* set with PCJacobiSetType() */ 64 PetscBool userowsum; 65 PetscBool useabs; /* use the absolute values of the diagonal entries */ 66 } PC_Jacobi; 67 68 #undef __FUNCT__ 69 #define __FUNCT__ "PCJacobiSetType_Jacobi" 70 static PetscErrorCode PCJacobiSetType_Jacobi(PC pc,PCJacobiType type) 71 { 72 PC_Jacobi *j = (PC_Jacobi*)pc->data; 73 74 PetscFunctionBegin; 75 j->userowmax = PETSC_FALSE; 76 j->userowsum = PETSC_FALSE; 77 if (type == PC_JACOBI_ROWMAX) { 78 j->userowmax = PETSC_TRUE; 79 } else if (type == PC_JACOBI_ROWSUM) { 80 j->userowsum = PETSC_TRUE; 81 } 82 PetscFunctionReturn(0); 83 } 84 85 #undef __FUNCT__ 86 #define __FUNCT__ "PCJacobiGetType_Jacobi" 87 static PetscErrorCode PCJacobiGetType_Jacobi(PC pc,PCJacobiType *type) 88 { 89 PC_Jacobi *j = (PC_Jacobi*)pc->data; 90 91 PetscFunctionBegin; 92 if (j->userowmax) { 93 *type = PC_JACOBI_ROWMAX; 94 } else if (j->userowsum) { 95 *type = PC_JACOBI_ROWSUM; 96 } else { 97 *type = PC_JACOBI_DIAGONAL; 98 } 99 PetscFunctionReturn(0); 100 } 101 102 #undef __FUNCT__ 103 #define __FUNCT__ "PCJacobiSetUseAbs_Jacobi" 104 static PetscErrorCode PCJacobiSetUseAbs_Jacobi(PC pc,PetscBool flg) 105 { 106 PC_Jacobi *j = (PC_Jacobi*)pc->data; 107 108 PetscFunctionBegin; 109 j->useabs = flg; 110 PetscFunctionReturn(0); 111 } 112 113 #undef __FUNCT__ 114 #define __FUNCT__ "PCJacobiGetUseAbs_Jacobi" 115 static PetscErrorCode PCJacobiGetUseAbs_Jacobi(PC pc,PetscBool *flg) 116 { 117 PC_Jacobi *j = (PC_Jacobi*)pc->data; 118 119 PetscFunctionBegin; 120 *flg = j->useabs; 121 PetscFunctionReturn(0); 122 } 123 124 /* -------------------------------------------------------------------------- */ 125 /* 126 PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner 127 by setting data structures and options. 128 129 Input Parameter: 130 . pc - the preconditioner context 131 132 Application Interface Routine: PCSetUp() 133 134 Notes: 135 The interface routine PCSetUp() is not usually called directly by 136 the user, but instead is called by PCApply() if necessary. 137 */ 138 #undef __FUNCT__ 139 #define __FUNCT__ "PCSetUp_Jacobi" 140 static PetscErrorCode PCSetUp_Jacobi(PC pc) 141 { 142 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 143 Vec diag,diagsqrt; 144 PetscErrorCode ierr; 145 PetscInt n,i; 146 PetscScalar *x; 147 PetscBool zeroflag = PETSC_FALSE; 148 149 PetscFunctionBegin; 150 /* 151 For most preconditioners the code would begin here something like 152 153 if (pc->setupcalled == 0) { allocate space the first time this is ever called 154 ierr = MatCreateVecs(pc->mat,&jac->diag);CHKERRQ(ierr); 155 PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->diag); 156 } 157 158 But for this preconditioner we want to support use of both the matrix' diagonal 159 elements (for left or right preconditioning) and square root of diagonal elements 160 (for symmetric preconditioning). Hence we do not allocate space here, since we 161 don't know at this point which will be needed (diag and/or diagsqrt) until the user 162 applies the preconditioner, and we don't want to allocate BOTH unless we need 163 them both. Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric() 164 and PCSetUp_Jacobi_Symmetric(), respectively. 165 */ 166 167 /* 168 Here we set up the preconditioner; that is, we copy the diagonal values from 169 the matrix and put them into a format to make them quick to apply as a preconditioner. 170 */ 171 diag = jac->diag; 172 diagsqrt = jac->diagsqrt; 173 174 if (diag) { 175 if (jac->userowmax) { 176 ierr = MatGetRowMaxAbs(pc->pmat,diag,NULL);CHKERRQ(ierr); 177 } else if (jac->userowsum) { 178 ierr = MatGetRowSum(pc->pmat,diag);CHKERRQ(ierr); 179 } else { 180 ierr = MatGetDiagonal(pc->pmat,diag);CHKERRQ(ierr); 181 } 182 ierr = VecReciprocal(diag);CHKERRQ(ierr); 183 ierr = VecGetLocalSize(diag,&n);CHKERRQ(ierr); 184 ierr = VecGetArray(diag,&x);CHKERRQ(ierr); 185 if (jac->useabs) { 186 for (i=0; i<n; i++) x[i] = PetscAbsScalar(x[i]); 187 } 188 for (i=0; i<n; i++) { 189 if (x[i] == 0.0) { 190 x[i] = 1.0; 191 zeroflag = PETSC_TRUE; 192 } 193 } 194 ierr = VecRestoreArray(diag,&x);CHKERRQ(ierr); 195 } 196 if (diagsqrt) { 197 if (jac->userowmax) { 198 ierr = MatGetRowMaxAbs(pc->pmat,diagsqrt,NULL);CHKERRQ(ierr); 199 } else if (jac->userowsum) { 200 ierr = MatGetRowSum(pc->pmat,diagsqrt);CHKERRQ(ierr); 201 } else { 202 ierr = MatGetDiagonal(pc->pmat,diagsqrt);CHKERRQ(ierr); 203 } 204 ierr = VecGetLocalSize(diagsqrt,&n);CHKERRQ(ierr); 205 ierr = VecGetArray(diagsqrt,&x);CHKERRQ(ierr); 206 for (i=0; i<n; i++) { 207 if (x[i] != 0.0) x[i] = 1.0/PetscSqrtReal(PetscAbsScalar(x[i])); 208 else { 209 x[i] = 1.0; 210 zeroflag = PETSC_TRUE; 211 } 212 } 213 ierr = VecRestoreArray(diagsqrt,&x);CHKERRQ(ierr); 214 } 215 if (zeroflag) { 216 ierr = PetscInfo(pc,"Zero detected in diagonal of matrix, using 1 at those locations\n");CHKERRQ(ierr); 217 } 218 PetscFunctionReturn(0); 219 } 220 /* -------------------------------------------------------------------------- */ 221 /* 222 PCSetUp_Jacobi_Symmetric - Allocates the vector needed to store the 223 inverse of the square root of the diagonal entries of the matrix. This 224 is used for symmetric application of the Jacobi preconditioner. 225 226 Input Parameter: 227 . pc - the preconditioner context 228 */ 229 #undef __FUNCT__ 230 #define __FUNCT__ "PCSetUp_Jacobi_Symmetric" 231 static PetscErrorCode PCSetUp_Jacobi_Symmetric(PC pc) 232 { 233 PetscErrorCode ierr; 234 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 235 236 PetscFunctionBegin; 237 ierr = MatCreateVecs(pc->pmat,&jac->diagsqrt,0);CHKERRQ(ierr); 238 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->diagsqrt);CHKERRQ(ierr); 239 ierr = PCSetUp_Jacobi(pc);CHKERRQ(ierr); 240 PetscFunctionReturn(0); 241 } 242 /* -------------------------------------------------------------------------- */ 243 /* 244 PCSetUp_Jacobi_NonSymmetric - Allocates the vector needed to store the 245 inverse of the diagonal entries of the matrix. This is used for left of 246 right application of the Jacobi preconditioner. 247 248 Input Parameter: 249 . pc - the preconditioner context 250 */ 251 #undef __FUNCT__ 252 #define __FUNCT__ "PCSetUp_Jacobi_NonSymmetric" 253 static PetscErrorCode PCSetUp_Jacobi_NonSymmetric(PC pc) 254 { 255 PetscErrorCode ierr; 256 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 257 258 PetscFunctionBegin; 259 ierr = MatCreateVecs(pc->pmat,&jac->diag,0);CHKERRQ(ierr); 260 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->diag);CHKERRQ(ierr); 261 ierr = PCSetUp_Jacobi(pc);CHKERRQ(ierr); 262 PetscFunctionReturn(0); 263 } 264 /* -------------------------------------------------------------------------- */ 265 /* 266 PCApply_Jacobi - Applies the Jacobi preconditioner to a vector. 267 268 Input Parameters: 269 . pc - the preconditioner context 270 . x - input vector 271 272 Output Parameter: 273 . y - output vector 274 275 Application Interface Routine: PCApply() 276 */ 277 #undef __FUNCT__ 278 #define __FUNCT__ "PCApply_Jacobi" 279 static PetscErrorCode PCApply_Jacobi(PC pc,Vec x,Vec y) 280 { 281 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 if (!jac->diag) { 286 ierr = PCSetUp_Jacobi_NonSymmetric(pc);CHKERRQ(ierr); 287 } 288 ierr = VecPointwiseMult(y,x,jac->diag);CHKERRQ(ierr); 289 PetscFunctionReturn(0); 290 } 291 /* -------------------------------------------------------------------------- */ 292 /* 293 PCApplySymmetricLeftOrRight_Jacobi - Applies the left or right part of a 294 symmetric preconditioner to a vector. 295 296 Input Parameters: 297 . pc - the preconditioner context 298 . x - input vector 299 300 Output Parameter: 301 . y - output vector 302 303 Application Interface Routines: PCApplySymmetricLeft(), PCApplySymmetricRight() 304 */ 305 #undef __FUNCT__ 306 #define __FUNCT__ "PCApplySymmetricLeftOrRight_Jacobi" 307 static PetscErrorCode PCApplySymmetricLeftOrRight_Jacobi(PC pc,Vec x,Vec y) 308 { 309 PetscErrorCode ierr; 310 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 311 312 PetscFunctionBegin; 313 if (!jac->diagsqrt) { 314 ierr = PCSetUp_Jacobi_Symmetric(pc);CHKERRQ(ierr); 315 } 316 VecPointwiseMult(y,x,jac->diagsqrt); 317 PetscFunctionReturn(0); 318 } 319 /* -------------------------------------------------------------------------- */ 320 #undef __FUNCT__ 321 #define __FUNCT__ "PCReset_Jacobi" 322 static PetscErrorCode PCReset_Jacobi(PC pc) 323 { 324 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 325 PetscErrorCode ierr; 326 327 PetscFunctionBegin; 328 ierr = VecDestroy(&jac->diag);CHKERRQ(ierr); 329 ierr = VecDestroy(&jac->diagsqrt);CHKERRQ(ierr); 330 PetscFunctionReturn(0); 331 } 332 333 /* 334 PCDestroy_Jacobi - Destroys the private context for the Jacobi preconditioner 335 that was created with PCCreate_Jacobi(). 336 337 Input Parameter: 338 . pc - the preconditioner context 339 340 Application Interface Routine: PCDestroy() 341 */ 342 #undef __FUNCT__ 343 #define __FUNCT__ "PCDestroy_Jacobi" 344 static PetscErrorCode PCDestroy_Jacobi(PC pc) 345 { 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 ierr = PCReset_Jacobi(pc);CHKERRQ(ierr); 350 351 /* 352 Free the private data structure that was hanging off the PC 353 */ 354 ierr = PetscFree(pc->data);CHKERRQ(ierr); 355 PetscFunctionReturn(0); 356 } 357 358 #undef __FUNCT__ 359 #define __FUNCT__ "PCSetFromOptions_Jacobi" 360 static PetscErrorCode PCSetFromOptions_Jacobi(PetscOptions *PetscOptionsObject,PC pc) 361 { 362 PC_Jacobi *jac = (PC_Jacobi*)pc->data; 363 PetscErrorCode ierr; 364 PetscBool flg; 365 PCJacobiType deflt,type; 366 367 PetscFunctionBegin; 368 ierr = PCJacobiGetType(pc,&deflt);CHKERRQ(ierr); 369 ierr = PetscOptionsHead(PetscOptionsObject,"Jacobi options");CHKERRQ(ierr); 370 ierr = PetscOptionsEnum("-pc_jacobi_type","How to construct diagonal matrix","PCJacobiSetType",PCJacobiTypes,(PetscEnum)deflt,(PetscEnum*)&type,&flg);CHKERRQ(ierr); 371 if (flg) { 372 ierr = PCJacobiSetType(pc,type);CHKERRQ(ierr); 373 } 374 ierr = PetscOptionsBool("-pc_jacobi_abs","Use absolute values of diagaonal entries","PCJacobiSetUseAbs",jac->useabs,&jac->useabs,NULL);CHKERRQ(ierr); 375 ierr = PetscOptionsTail();CHKERRQ(ierr); 376 PetscFunctionReturn(0); 377 } 378 379 /* -------------------------------------------------------------------------- */ 380 /* 381 PCCreate_Jacobi - Creates a Jacobi preconditioner context, PC_Jacobi, 382 and sets this as the private data within the generic preconditioning 383 context, PC, that was created within PCCreate(). 384 385 Input Parameter: 386 . pc - the preconditioner context 387 388 Application Interface Routine: PCCreate() 389 */ 390 391 /*MC 392 PCJACOBI - Jacobi (i.e. diagonal scaling preconditioning) 393 394 Options Database Key: 395 + -pc_jacobi_type <diagonal,rowmax,rowsum> - approach for forming the preconditioner 396 - -pc_jacobi_abs - use the absolute value of the diagonal entry 397 398 Level: beginner 399 400 Concepts: Jacobi, diagonal scaling, preconditioners 401 402 Notes: By using KSPSetPCSide(ksp,PC_SYMMETRIC) or -ksp_pc_side symmetric 403 can scale each side of the matrix by the square root of the diagonal entries. 404 405 Zero entries along the diagonal are replaced with the value 1.0 406 407 See PCPBJACOBI for a point-block Jacobi preconditioner 408 409 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 410 PCJacobiSetType(), PCJacobiSetUseAbs(), PCJacobiGetUseAbs(), PCPBJACOBI 411 M*/ 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "PCCreate_Jacobi" 415 PETSC_EXTERN PetscErrorCode PCCreate_Jacobi(PC pc) 416 { 417 PC_Jacobi *jac; 418 PetscErrorCode ierr; 419 420 PetscFunctionBegin; 421 /* 422 Creates the private data structure for this preconditioner and 423 attach it to the PC object. 424 */ 425 ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 426 pc->data = (void*)jac; 427 428 /* 429 Initialize the pointers to vectors to ZERO; these will be used to store 430 diagonal entries of the matrix for fast preconditioner application. 431 */ 432 jac->diag = 0; 433 jac->diagsqrt = 0; 434 jac->userowmax = PETSC_FALSE; 435 jac->userowsum = PETSC_FALSE; 436 jac->useabs = PETSC_FALSE; 437 438 /* 439 Set the pointers for the functions that are provided above. 440 Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 441 are called, they will automatically call these functions. Note we 442 choose not to provide a couple of these functions since they are 443 not needed. 444 */ 445 pc->ops->apply = PCApply_Jacobi; 446 pc->ops->applytranspose = PCApply_Jacobi; 447 pc->ops->setup = PCSetUp_Jacobi; 448 pc->ops->reset = PCReset_Jacobi; 449 pc->ops->destroy = PCDestroy_Jacobi; 450 pc->ops->setfromoptions = PCSetFromOptions_Jacobi; 451 pc->ops->view = 0; 452 pc->ops->applyrichardson = 0; 453 pc->ops->applysymmetricleft = PCApplySymmetricLeftOrRight_Jacobi; 454 pc->ops->applysymmetricright = PCApplySymmetricLeftOrRight_Jacobi; 455 456 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCJacobiSetType_C",PCJacobiSetType_Jacobi);CHKERRQ(ierr); 457 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCJacobiGetType_C",PCJacobiGetType_Jacobi);CHKERRQ(ierr); 458 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCJacobiSetUseAbs_C",PCJacobiSetUseAbs_Jacobi);CHKERRQ(ierr); 459 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCJacobiGetUseAbs_C",PCJacobiGetUseAbs_Jacobi);CHKERRQ(ierr); 460 PetscFunctionReturn(0); 461 } 462 463 #undef __FUNCT__ 464 #define __FUNCT__ "PCJacobiSetUseAbs" 465 /*@ 466 PCJacobiSetUseAbs - Causes the Jacobi preconditioner to use the 467 absolute values of the digonal divisors in the preconditioner 468 469 Logically Collective on PC 470 471 Input Parameters: 472 + pc - the preconditioner context 473 - flg - whether to use absolute values or not 474 475 Options Database Key: 476 . -pc_jacobi_abs 477 478 Notes: This takes affect at the next construction of the preconditioner 479 480 Level: intermediate 481 482 Concepts: Jacobi preconditioner 483 484 .seealso: PCJacobiaSetType(), PCJacobiGetUseAbs() 485 486 @*/ 487 PetscErrorCode PCJacobiSetUseAbs(PC pc,PetscBool flg) 488 { 489 PetscErrorCode ierr; 490 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 493 ierr = PetscTryMethod(pc,"PCJacobiSetUseAbs_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr); 494 PetscFunctionReturn(0); 495 } 496 497 #undef __FUNCT__ 498 #define __FUNCT__ "PCJacobiGetUseAbs" 499 /*@ 500 PCJacobiGetUseAbs - Determines if the Jacobi preconditioner uses the 501 absolute values of the digonal divisors in the preconditioner 502 503 Logically Collective on PC 504 505 Input Parameter: 506 . pc - the preconditioner context 507 508 Output Parameter: 509 . flg - whether to use absolute values or not 510 511 Options Database Key: 512 . -pc_jacobi_abs 513 514 Level: intermediate 515 516 Concepts: Jacobi preconditioner 517 518 .seealso: PCJacobiaSetType(), PCJacobiSetUseAbs(), PCJacobiGetType() 519 520 @*/ 521 PetscErrorCode PCJacobiGetUseAbs(PC pc,PetscBool *flg) 522 { 523 PetscErrorCode ierr; 524 525 PetscFunctionBegin; 526 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 527 ierr = PetscUseMethod(pc,"PCJacobiGetUseAbs_C",(PC,PetscBool*),(pc,flg));CHKERRQ(ierr); 528 PetscFunctionReturn(0); 529 } 530 531 #undef __FUNCT__ 532 #define __FUNCT__ "PCJacobiSetType" 533 /*@ 534 PCJacobiSetType - Causes the Jacobi preconditioner to use either the diagonal, the maximum entry in each row, 535 of the sum of rows entries for the diagonal preconditioner 536 537 Logically Collective on PC 538 539 Input Parameters: 540 + pc - the preconditioner context 541 - type - PC_JACOBI_DIAGONAL, PC_JACOBI_ROWMAX, PC_JACOBI_ROWSUM 542 543 Options Database Key: 544 . -pc_jacobi_type <diagonal,rowmax,rowsum> 545 546 Level: intermediate 547 548 Concepts: Jacobi preconditioner 549 550 .seealso: PCJacobiaUseAbs(), PCJacobiGetType() 551 @*/ 552 PetscErrorCode PCJacobiSetType(PC pc,PCJacobiType type) 553 { 554 PetscErrorCode ierr; 555 556 PetscFunctionBegin; 557 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 558 ierr = PetscTryMethod(pc,"PCJacobiSetType_C",(PC,PCJacobiType),(pc,type));CHKERRQ(ierr); 559 PetscFunctionReturn(0); 560 } 561 562 #undef __FUNCT__ 563 #define __FUNCT__ "PCJacobiGetType" 564 /*@ 565 PCJacobiGetType - Gets how the diagonal matrix is produced for the preconditioner 566 567 Not Collective on PC 568 569 Input Parameter: 570 . pc - the preconditioner context 571 572 Output Parameter: 573 . type - PC_JACOBI_DIAGONAL, PC_JACOBI_ROWMAX, PC_JACOBI_ROWSUM 574 575 Level: intermediate 576 577 Concepts: Jacobi preconditioner 578 579 .seealso: PCJacobiaUseAbs(), PCJacobiSetType() 580 @*/ 581 PetscErrorCode PCJacobiGetType(PC pc,PCJacobiType *type) 582 { 583 PetscErrorCode ierr; 584 585 PetscFunctionBegin; 586 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 587 ierr = PetscUseMethod(pc,"PCJacobiGetType_C",(PC,PCJacobiType*),(pc,type));CHKERRQ(ierr); 588 PetscFunctionReturn(0); 589 } 590