Actual source code: jacobi.c


  2: /*  --------------------------------------------------------------------

  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)

  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.

 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.

 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().

 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().

 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().

 44:     -------------------------------------------------------------------- */

 46: /*
 47:    Include files needed for the Jacobi preconditioner:
 48:      pcimpl.h - private include file intended for use by all preconditioners
 49: */

 51: #include <petsc/private/pcimpl.h>

 53: const char *const PCJacobiTypes[] = {"DIAGONAL", "ROWMAX", "ROWSUM", "PCJacobiType", "PC_JACOBI_", NULL};

 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:   PetscBool fixdiag; /* fix zero diagonal terms */
 67: } PC_Jacobi;

 69: static PetscErrorCode PCJacobiSetType_Jacobi(PC pc, PCJacobiType type)
 70: {
 71:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

 73:   j->userowmax = PETSC_FALSE;
 74:   j->userowsum = PETSC_FALSE;
 75:   if (type == PC_JACOBI_ROWMAX) {
 76:     j->userowmax = PETSC_TRUE;
 77:   } else if (type == PC_JACOBI_ROWSUM) {
 78:     j->userowsum = PETSC_TRUE;
 79:   }
 80:   return 0;
 81: }

 83: static PetscErrorCode PCJacobiGetType_Jacobi(PC pc, PCJacobiType *type)
 84: {
 85:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

 87:   if (j->userowmax) {
 88:     *type = PC_JACOBI_ROWMAX;
 89:   } else if (j->userowsum) {
 90:     *type = PC_JACOBI_ROWSUM;
 91:   } else {
 92:     *type = PC_JACOBI_DIAGONAL;
 93:   }
 94:   return 0;
 95: }

 97: static PetscErrorCode PCJacobiSetUseAbs_Jacobi(PC pc, PetscBool flg)
 98: {
 99:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

101:   j->useabs = flg;
102:   return 0;
103: }

105: static PetscErrorCode PCJacobiGetUseAbs_Jacobi(PC pc, PetscBool *flg)
106: {
107:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

109:   *flg = j->useabs;
110:   return 0;
111: }

113: static PetscErrorCode PCJacobiSetFixDiagonal_Jacobi(PC pc, PetscBool flg)
114: {
115:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

117:   j->fixdiag = flg;
118:   return 0;
119: }

121: static PetscErrorCode PCJacobiGetFixDiagonal_Jacobi(PC pc, PetscBool *flg)
122: {
123:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

125:   *flg = j->fixdiag;
126:   return 0;
127: }

129: /*
130:    PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner
131:                     by setting data structures and options.

133:    Input Parameter:
134: .  pc - the preconditioner context

136:    Application Interface Routine: PCSetUp()

138:    Note:
139:    The interface routine PCSetUp() is not usually called directly by
140:    the user, but instead is called by PCApply() if necessary.
141: */
142: static PetscErrorCode PCSetUp_Jacobi(PC pc)
143: {
144:   PC_Jacobi   *jac = (PC_Jacobi *)pc->data;
145:   Vec          diag, diagsqrt;
146:   PetscInt     n, i;
147:   PetscScalar *x;
148:   PetscBool    zeroflag = PETSC_FALSE;

150:   /*
151:        For most preconditioners the code would begin here something like

153:   if (pc->setupcalled == 0) { allocate space the first time this is ever called
154:     MatCreateVecs(pc->mat,&jac->diag);
155:   }

157:     But for this preconditioner we want to support use of both the matrix' diagonal
158:     elements (for left or right preconditioning) and square root of diagonal elements
159:     (for symmetric preconditioning).  Hence we do not allocate space here, since we
160:     don't know at this point which will be needed (diag and/or diagsqrt) until the user
161:     applies the preconditioner, and we don't want to allocate BOTH unless we need
162:     them both.  Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric()
163:     and PCSetUp_Jacobi_Symmetric(), respectively.
164:   */

166:   /*
167:     Here we set up the preconditioner; that is, we copy the diagonal values from
168:     the matrix and put them into a format to make them quick to apply as a preconditioner.
169:   */
170:   diag     = jac->diag;
171:   diagsqrt = jac->diagsqrt;

173:   if (diag) {
174:     PetscBool isset, isspd;

176:     if (jac->userowmax) {
177:       MatGetRowMaxAbs(pc->pmat, diag, NULL);
178:     } else if (jac->userowsum) {
179:       MatGetRowSum(pc->pmat, diag);
180:     } else {
181:       MatGetDiagonal(pc->pmat, diag);
182:     }
183:     VecReciprocal(diag);
184:     if (jac->useabs) VecAbs(diag);
185:     MatIsSPDKnown(pc->pmat, &isset, &isspd);
186:     if (jac->fixdiag && (!isset || !isspd)) {
187:       VecGetLocalSize(diag, &n);
188:       VecGetArray(diag, &x);
189:       for (i = 0; i < n; i++) {
190:         if (x[i] == 0.0) {
191:           x[i]     = 1.0;
192:           zeroflag = PETSC_TRUE;
193:         }
194:       }
195:       VecRestoreArray(diag, &x);
196:     }
197:   }
198:   if (diagsqrt) {
199:     if (jac->userowmax) {
200:       MatGetRowMaxAbs(pc->pmat, diagsqrt, NULL);
201:     } else if (jac->userowsum) {
202:       MatGetRowSum(pc->pmat, diagsqrt);
203:     } else {
204:       MatGetDiagonal(pc->pmat, diagsqrt);
205:     }
206:     VecGetLocalSize(diagsqrt, &n);
207:     VecGetArray(diagsqrt, &x);
208:     for (i = 0; i < n; i++) {
209:       if (x[i] != 0.0) x[i] = 1.0 / PetscSqrtReal(PetscAbsScalar(x[i]));
210:       else {
211:         x[i]     = 1.0;
212:         zeroflag = PETSC_TRUE;
213:       }
214:     }
215:     VecRestoreArray(diagsqrt, &x);
216:   }
217:   if (zeroflag) PetscInfo(pc, "Zero detected in diagonal of matrix, using 1 at those locations\n");
218:   return 0;
219: }

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.

226:    Input Parameter:
227: .  pc - the preconditioner context
228: */
229: static PetscErrorCode PCSetUp_Jacobi_Symmetric(PC pc)
230: {
231:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

233:   MatCreateVecs(pc->pmat, &jac->diagsqrt, NULL);
234:   PCSetUp_Jacobi(pc);
235:   return 0;
236: }

238: /*
239:    PCSetUp_Jacobi_NonSymmetric - Allocates the vector needed to store the
240:    inverse of the diagonal entries of the matrix.  This is used for left of
241:    right application of the Jacobi preconditioner.

243:    Input Parameter:
244: .  pc - the preconditioner context
245: */
246: static PetscErrorCode PCSetUp_Jacobi_NonSymmetric(PC pc)
247: {
248:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

250:   MatCreateVecs(pc->pmat, &jac->diag, NULL);
251:   PCSetUp_Jacobi(pc);
252:   return 0;
253: }

255: /*
256:    PCApply_Jacobi - Applies the Jacobi preconditioner to a vector.

258:    Input Parameters:
259: .  pc - the preconditioner context
260: .  x - input vector

262:    Output Parameter:
263: .  y - output vector

265:    Application Interface Routine: PCApply()
266:  */
267: static PetscErrorCode PCApply_Jacobi(PC pc, Vec x, Vec y)
268: {
269:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

271:   if (!jac->diag) PCSetUp_Jacobi_NonSymmetric(pc);
272:   VecPointwiseMult(y, x, jac->diag);
273:   return 0;
274: }

276: /*
277:    PCApplySymmetricLeftOrRight_Jacobi - Applies the left or right part of a
278:    symmetric preconditioner to a vector.

280:    Input Parameters:
281: .  pc - the preconditioner context
282: .  x - input vector

284:    Output Parameter:
285: .  y - output vector

287:    Application Interface Routines: PCApplySymmetricLeft(), PCApplySymmetricRight()
288: */
289: static PetscErrorCode PCApplySymmetricLeftOrRight_Jacobi(PC pc, Vec x, Vec y)
290: {
291:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

293:   if (!jac->diagsqrt) PCSetUp_Jacobi_Symmetric(pc);
294:   VecPointwiseMult(y, x, jac->diagsqrt);
295:   return 0;
296: }

298: static PetscErrorCode PCReset_Jacobi(PC pc)
299: {
300:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

302:   VecDestroy(&jac->diag);
303:   VecDestroy(&jac->diagsqrt);
304:   return 0;
305: }

307: /*
308:    PCDestroy_Jacobi - Destroys the private context for the Jacobi preconditioner
309:    that was created with PCCreate_Jacobi().

311:    Input Parameter:
312: .  pc - the preconditioner context

314:    Application Interface Routine: PCDestroy()
315: */
316: static PetscErrorCode PCDestroy_Jacobi(PC pc)
317: {
318:   PCReset_Jacobi(pc);
319:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetType_C", NULL);
320:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetType_C", NULL);
321:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetUseAbs_C", NULL);
322:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetUseAbs_C", NULL);
323:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetFixDiagonal_C", NULL);
324:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetFixDiagonal_C", NULL);

326:   /*
327:       Free the private data structure that was hanging off the PC
328:   */
329:   PetscFree(pc->data);
330:   return 0;
331: }

333: static PetscErrorCode PCSetFromOptions_Jacobi(PC pc, PetscOptionItems *PetscOptionsObject)
334: {
335:   PC_Jacobi   *jac = (PC_Jacobi *)pc->data;
336:   PetscBool    flg;
337:   PCJacobiType deflt, type;

339:   PCJacobiGetType(pc, &deflt);
340:   PetscOptionsHeadBegin(PetscOptionsObject, "Jacobi options");
341:   PetscOptionsEnum("-pc_jacobi_type", "How to construct diagonal matrix", "PCJacobiSetType", PCJacobiTypes, (PetscEnum)deflt, (PetscEnum *)&type, &flg);
342:   if (flg) PCJacobiSetType(pc, type);
343:   PetscOptionsBool("-pc_jacobi_abs", "Use absolute values of diagonal entries", "PCJacobiSetUseAbs", jac->useabs, &jac->useabs, NULL);
344:   PetscOptionsBool("-pc_jacobi_fixdiagonal", "Fix null terms on diagonal", "PCJacobiSetFixDiagonal", jac->fixdiag, &jac->fixdiag, NULL);
345:   PetscOptionsHeadEnd();
346:   return 0;
347: }

349: static PetscErrorCode PCView_Jacobi(PC pc, PetscViewer viewer)
350: {
351:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;
352:   PetscBool  iascii;

354:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
355:   if (iascii) {
356:     PCJacobiType      type;
357:     PetscBool         useAbs, fixdiag;
358:     PetscViewerFormat format;

360:     PCJacobiGetType(pc, &type);
361:     PCJacobiGetUseAbs(pc, &useAbs);
362:     PCJacobiGetFixDiagonal(pc, &fixdiag);
363:     PetscViewerASCIIPrintf(viewer, "  type %s%s%s\n", PCJacobiTypes[type], useAbs ? ", using absolute value of entries" : "", !fixdiag ? ", not checking null diagonal entries" : "");
364:     PetscViewerGetFormat(viewer, &format);
365:     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) VecView(jac->diag, viewer);
366:   }
367:   return 0;
368: }

370: /*
371:    PCCreate_Jacobi - Creates a Jacobi preconditioner context, PC_Jacobi,
372:    and sets this as the private data within the generic preconditioning
373:    context, PC, that was created within PCCreate().

375:    Input Parameter:
376: .  pc - the preconditioner context

378:    Application Interface Routine: PCCreate()
379: */

381: /*MC
382:      PCJACOBI - Jacobi (i.e. diagonal scaling preconditioning)

384:    Options Database Keys:
385: +    -pc_jacobi_type <diagonal,rowmax,rowsum> - approach for forming the preconditioner
386: .    -pc_jacobi_abs - use the absolute value of the diagonal entry
387: -    -pc_jacobi_fixdiag - fix for zero diagonal terms by placing 1.0 in those locations

389:    Level: beginner

391:   Notes:
392:     By using `KSPSetPCSide`(ksp,`PC_SYMMETRIC`) or -ksp_pc_side symmetric
393:     can scale each side of the matrix by the square root of the diagonal entries.

395:     Zero entries along the diagonal are replaced with the value 1.0

397:     See `PCPBJACOBI` for fixed-size point block, `PCVPBJACOBI` for variable-sized point block, and `PCBJACOBI` for large size blocks

399: .seealso:  `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
400:            `PCJacobiSetType()`, `PCJacobiSetUseAbs()`, `PCJacobiGetUseAbs()`, `PCASM`,
401:            `PCJacobiSetFixDiagonal()`, `PCJacobiGetFixDiagonal()`
402:            `PCJacobiSetType()`, `PCJacobiSetUseAbs()`, `PCJacobiGetUseAbs()`, `PCPBJACOBI`, `PCBJACOBI`, `PCVPBJACOBI`
403: M*/

405: PETSC_EXTERN PetscErrorCode PCCreate_Jacobi(PC pc)
406: {
407:   PC_Jacobi *jac;

409:   /*
410:      Creates the private data structure for this preconditioner and
411:      attach it to the PC object.
412:   */
413:   PetscNew(&jac);
414:   pc->data = (void *)jac;

416:   /*
417:      Initialize the pointers to vectors to ZERO; these will be used to store
418:      diagonal entries of the matrix for fast preconditioner application.
419:   */
420:   jac->diag      = NULL;
421:   jac->diagsqrt  = NULL;
422:   jac->userowmax = PETSC_FALSE;
423:   jac->userowsum = PETSC_FALSE;
424:   jac->useabs    = PETSC_FALSE;
425:   jac->fixdiag   = PETSC_TRUE;

427:   /*
428:       Set the pointers for the functions that are provided above.
429:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
430:       are called, they will automatically call these functions.  Note we
431:       choose not to provide a couple of these functions since they are
432:       not needed.
433:   */
434:   pc->ops->apply               = PCApply_Jacobi;
435:   pc->ops->applytranspose      = PCApply_Jacobi;
436:   pc->ops->setup               = PCSetUp_Jacobi;
437:   pc->ops->reset               = PCReset_Jacobi;
438:   pc->ops->destroy             = PCDestroy_Jacobi;
439:   pc->ops->setfromoptions      = PCSetFromOptions_Jacobi;
440:   pc->ops->view                = PCView_Jacobi;
441:   pc->ops->applyrichardson     = NULL;
442:   pc->ops->applysymmetricleft  = PCApplySymmetricLeftOrRight_Jacobi;
443:   pc->ops->applysymmetricright = PCApplySymmetricLeftOrRight_Jacobi;

445:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetType_C", PCJacobiSetType_Jacobi);
446:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetType_C", PCJacobiGetType_Jacobi);
447:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetUseAbs_C", PCJacobiSetUseAbs_Jacobi);
448:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetUseAbs_C", PCJacobiGetUseAbs_Jacobi);
449:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetFixDiagonal_C", PCJacobiSetFixDiagonal_Jacobi);
450:   PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetFixDiagonal_C", PCJacobiGetFixDiagonal_Jacobi);
451:   return 0;
452: }

454: /*@
455:    PCJacobiSetUseAbs - Causes the Jacobi preconditioner `PCJACOBI` to use the
456:       absolute values of the diagonal divisors in the preconditioner

458:    Logically Collective

460:    Input Parameters:
461: +  pc - the preconditioner context
462: -  flg - whether to use absolute values or not

464:    Options Database Key:
465: .  -pc_jacobi_abs <bool> - use absolute values

467:    Note:
468:     This takes affect at the next construction of the preconditioner

470:    Level: intermediate

472: .seealso: `PCJACOBI`, `PCJacobiaSetType()`, `PCJacobiGetUseAbs()`
473: @*/
474: PetscErrorCode PCJacobiSetUseAbs(PC pc, PetscBool flg)
475: {
477:   PetscTryMethod(pc, "PCJacobiSetUseAbs_C", (PC, PetscBool), (pc, flg));
478:   return 0;
479: }

481: /*@
482:    PCJacobiGetUseAbs - Determines if the Jacobi preconditioner `PCJACOBI` uses the
483:       absolute values of the diagonal divisors in the preconditioner

485:    Logically Collective

487:    Input Parameter:
488: .  pc - the preconditioner context

490:    Output Parameter:
491: .  flg - whether to use absolute values or not

493:    Level: intermediate

495: .seealso: `PCJACOBI`, `PCJacobiaSetType()`, `PCJacobiSetUseAbs()`, `PCJacobiGetType()`
496: @*/
497: PetscErrorCode PCJacobiGetUseAbs(PC pc, PetscBool *flg)
498: {
500:   PetscUseMethod(pc, "PCJacobiGetUseAbs_C", (PC, PetscBool *), (pc, flg));
501:   return 0;
502: }

504: /*@
505:    PCJacobiSetFixDiagonal - Check for zero values on the diagonal and replace them with 1.0

507:    Logically Collective

509:    Input Parameters:
510: +  pc - the preconditioner context
511: -  flg - the boolean flag

513:    Options Database Key:
514: .  -pc_jacobi_fixdiagonal <bool> - check for zero values on the diagonal

516:    Note:
517:    This takes affect at the next construction of the preconditioner

519:    Level: intermediate

521: .seealso: `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiGetFixDiagonal()`, `PCJacobiSetUseAbs()`
522: @*/
523: PetscErrorCode PCJacobiSetFixDiagonal(PC pc, PetscBool flg)
524: {
526:   PetscTryMethod(pc, "PCJacobiSetFixDiagonal_C", (PC, PetscBool), (pc, flg));
527:   return 0;
528: }

530: /*@
531:    PCJacobiGetFixDiagonal - Determines if the Jacobi preconditioner `PCJACOBI` checks for zero diagonal terms

533:    Logically Collective

535:    Input Parameter:
536: .  pc - the preconditioner context

538:    Output Parameter:
539: .  flg - the boolean flag

541:    Options Database Key:
542: .  -pc_jacobi_fixdiagonal <bool> - Fix 0 terms on diagonal by using 1

544:    Level: intermediate

546: .seealso: `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiSetFixDiagonal()`
547: @*/
548: PetscErrorCode PCJacobiGetFixDiagonal(PC pc, PetscBool *flg)
549: {
551:   PetscUseMethod(pc, "PCJacobiGetFixDiagonal_C", (PC, PetscBool *), (pc, flg));
552:   return 0;
553: }

555: /*@
556:    PCJacobiSetType - Causes the Jacobi preconditioner to use either the diagonal, the maximum entry in each row,
557:       of the sum of rows entries for the diagonal preconditioner

559:    Logically Collective

561:    Input Parameters:
562: +  pc - the preconditioner context
563: -  type - `PC_JACOBI_DIAGONAL`, `PC_JACOBI_ROWMAX`, `PC_JACOBI_ROWSUM`

565:    Options Database Key:
566: .  -pc_jacobi_type <diagonal,rowmax,rowsum> - the type of diagonal matrix to use for Jacobi

568:    Level: intermediate

570:    Developer Note:
571:    Why is there a separate function for using the absolute value?

573: .seealso: `PCJACOBI`, `PCJacobiSetUseAbs()`, `PCJacobiGetType()`
574: @*/
575: PetscErrorCode PCJacobiSetType(PC pc, PCJacobiType type)
576: {
578:   PetscTryMethod(pc, "PCJacobiSetType_C", (PC, PCJacobiType), (pc, type));
579:   return 0;
580: }

582: /*@
583:    PCJacobiGetType - Gets how the diagonal matrix is produced for the preconditioner

585:    Not Collective

587:    Input Parameter:
588: .  pc - the preconditioner context

590:    Output Parameter:
591: .  type - `PC_JACOBI_DIAGONAL`, `PC_JACOBI_ROWMAX`, `PC_JACOBI_ROWSUM`

593:    Level: intermediate

595: .seealso: `PCJACOBI`, `PCJacobiaUseAbs()`, `PCJacobiSetType()`
596: @*/
597: PetscErrorCode PCJacobiGetType(PC pc, PCJacobiType *type)
598: {
600:   PetscUseMethod(pc, "PCJacobiGetType_C", (PC, PCJacobiType *), (pc, type));
601:   return 0;
602: }