Actual source code: jacobi.c

  1: /*
  2:      This file implements a Jacobi preconditioner in PETSc as part of PC.
  3:      You can use this as a starting point for implementing your own
  4:      preconditioner that is not provided with PETSc. (You might also consider
  5:      just using PCSHELL)

  7:      The following basic routines are required for each preconditioner.
  8:           PCCreate_XXX()          - Creates a preconditioner context
  9:           PCSetFromOptions_XXX()  - Sets runtime options
 10:           PCApply_XXX()           - Applies the preconditioner
 11:           PCDestroy_XXX()         - Destroys the preconditioner context
 12:      where the suffix "_XXX" denotes a particular implementation, in
 13:      this case we use _Jacobi (e.g., PCCreate_Jacobi, PCApply_Jacobi).
 14:      These routines are actually called via the common user interface
 15:      routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(),
 16:      so the application code interface remains identical for all
 17:      preconditioners.

 19:      Another key routine is:
 20:           PCSetUp_XXX()           - Prepares for the use of a preconditioner
 21:      by setting data structures and options.   The interface routine PCSetUp()
 22:      is not usually called directly by the user, but instead is called by
 23:      PCApply() if necessary.

 25:      Additional basic routines are:
 26:           PCView_XXX()            - Prints details of runtime options that
 27:                                     have actually been used.
 28:      These are called by application codes via the interface routines
 29:      PCView().

 31:      The various types of solvers (preconditioners, Krylov subspace methods,
 32:      nonlinear solvers, timesteppers) are all organized similarly, so the
 33:      above description applies to these categories also.  One exception is
 34:      that the analogues of PCApply() for these components are KSPSolve(),
 35:      SNESSolve(), and TSSolve().

 37:      Additional optional functionality unique to preconditioners is left and
 38:      right symmetric preconditioner application via PCApplySymmetricLeft()
 39:      and PCApplySymmetricRight().  The Jacobi implementation is
 40:      PCApplySymmetricLeftOrRight_Jacobi().
 41: */

 43: /*
 44:    Include files needed for the Jacobi preconditioner:
 45:      pcimpl.h - private include file intended for use by all preconditioners
 46: */

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

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

 52: /*
 53:    Private context (data structure) for the Jacobi preconditioner.
 54: */
 55: typedef struct {
 56:   Vec          diag;     /* vector containing the reciprocals of the diagonal elements of the preconditioner matrix */
 57:   Vec          diagsqrt; /* vector containing the reciprocals of the square roots of
 58:                                     the diagonal elements of the preconditioner matrix (used
 59:                                     only for symmetric preconditioner application) */
 60:   PCJacobiType type;
 61:   PetscBool    useabs;  /* use the absolute values of the diagonal entries */
 62:   PetscBool    fixdiag; /* fix zero diagonal terms */
 63:   PetscReal    scale;   /* for scaling rowl1 off-diagonals */
 64: } PC_Jacobi;

 66: static PetscErrorCode PCReset_Jacobi(PC);

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

 73:   PetscFunctionBegin;
 74:   PetscCall(PCJacobiGetType(pc, &old_type));
 75:   if (old_type == type) PetscFunctionReturn(PETSC_SUCCESS);
 76:   PetscCall(PCReset_Jacobi(pc));
 77:   j->type = type;
 78:   PetscFunctionReturn(PETSC_SUCCESS);
 79: }

 81: static PetscErrorCode PCJacobiGetUseAbs_Jacobi(PC pc, PetscBool *flg)
 82: {
 83:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

 85:   PetscFunctionBegin;
 86:   *flg = j->useabs;
 87:   PetscFunctionReturn(PETSC_SUCCESS);
 88: }

 90: static PetscErrorCode PCJacobiSetUseAbs_Jacobi(PC pc, PetscBool flg)
 91: {
 92:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

 94:   PetscFunctionBegin;
 95:   j->useabs = flg;
 96:   PetscFunctionReturn(PETSC_SUCCESS);
 97: }

 99: static PetscErrorCode PCJacobiGetType_Jacobi(PC pc, PCJacobiType *type)
100: {
101:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

103:   PetscFunctionBegin;
104:   *type = j->type;
105:   PetscFunctionReturn(PETSC_SUCCESS);
106: }

108: static PetscErrorCode PCJacobiSetRowl1Scale_Jacobi(PC pc, PetscReal flg)
109: {
110:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

112:   PetscFunctionBegin;
113:   j->scale = flg;
114:   PetscFunctionReturn(PETSC_SUCCESS);
115: }

117: static PetscErrorCode PCJacobiGetRowl1Scale_Jacobi(PC pc, PetscReal *flg)
118: {
119:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

121:   PetscFunctionBegin;
122:   *flg = j->scale;
123:   PetscFunctionReturn(PETSC_SUCCESS);
124: }

126: static PetscErrorCode PCJacobiSetFixDiagonal_Jacobi(PC pc, PetscBool flg)
127: {
128:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

130:   PetscFunctionBegin;
131:   j->fixdiag = flg;
132:   PetscFunctionReturn(PETSC_SUCCESS);
133: }

135: static PetscErrorCode PCJacobiGetFixDiagonal_Jacobi(PC pc, PetscBool *flg)
136: {
137:   PC_Jacobi *j = (PC_Jacobi *)pc->data;

139:   PetscFunctionBegin;
140:   *flg = j->fixdiag;
141:   PetscFunctionReturn(PETSC_SUCCESS);
142: }

144: static PetscErrorCode PCJacobiGetDiagonal_Jacobi(PC pc, Vec diag, Vec diagsqrt)
145: {
146:   PC_Jacobi *j    = (PC_Jacobi *)pc->data;
147:   MPI_Comm   comm = PetscObjectComm((PetscObject)pc);

149:   PetscFunctionBegin;
150:   PetscCheck(j->diag || j->diagsqrt, comm, PETSC_ERR_ARG_WRONGSTATE, "Jacobi diagonal has not been created yet. Use PCApply to force creation");
151:   PetscCheck(!diag || (diag && j->diag), comm, PETSC_ERR_ARG_WRONGSTATE, "Jacobi diagonal not available. Check if PC is non-symmetric");
152:   PetscCheck(!diagsqrt || (diagsqrt && j->diagsqrt), comm, PETSC_ERR_ARG_WRONGSTATE, "Jacobi diagonal squareroot not available. Check if PC is symmetric");

154:   if (diag) PetscCall(VecCopy(j->diag, diag));
155:   if (diagsqrt) PetscCall(VecCopy(j->diagsqrt, diagsqrt));
156:   PetscFunctionReturn(PETSC_SUCCESS);
157: }

159: /*
160:    PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner
161:                     by setting data structures and options.

163:    Input Parameter:
164: .  pc - the preconditioner context

166:    Application Interface Routine: PCSetUp()

168:    Note:
169:    The interface routine PCSetUp() is not usually called directly by
170:    the user, but instead is called by PCApply() if necessary.
171: */
172: static PetscErrorCode PCSetUp_Jacobi(PC pc)
173: {
174:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;
175:   Vec        diag, diagsqrt;
176:   PetscInt   n, i;
177:   PetscBool  zeroflag = PETSC_FALSE, negflag = PETSC_FALSE;

179:   PetscFunctionBegin;
180:   /*
181:        For most preconditioners the code would begin here something like

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

187:     But for this preconditioner we want to support use of both the matrix' diagonal
188:     elements (for left or right preconditioning) and square root of diagonal elements
189:     (for symmetric preconditioning).  Hence we do not allocate space here, since we
190:     don't know at this point which will be needed (diag and/or diagsqrt) until the user
191:     applies the preconditioner, and we don't want to allocate BOTH unless we need
192:     them both.  Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric()
193:     and PCSetUp_Jacobi_Symmetric(), respectively.
194:   */

196:   /*
197:     Here we set up the preconditioner; that is, we copy the diagonal values from
198:     the matrix and put them into a format to make them quick to apply as a preconditioner.
199:   */
200:   diag     = jac->diag;
201:   diagsqrt = jac->diagsqrt;

203:   if (diag) {
204:     PetscBool isset, isspd;

206:     PetscCall(VecLockReadPop(diag));
207:     switch (jac->type) {
208:     case PC_JACOBI_DIAGONAL:
209:       PetscCall(MatGetDiagonal(pc->pmat, diag));
210:       break;
211:     case PC_JACOBI_ROWMAX:
212:       PetscCall(MatGetRowMaxAbs(pc->pmat, diag, NULL));
213:       break;
214:     case PC_JACOBI_ROWL1:
215:       PetscCall(MatGetRowSumAbs(pc->pmat, diag));
216:       // fix negative rows (eg, negative definite) -- this could be done for all, not needed for userowmax
217:       PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd));
218:       if (jac->fixdiag && (!isset || !isspd)) {
219:         PetscScalar       *x2;
220:         const PetscScalar *x;
221:         Vec                true_diag;
222:         PetscCall(VecDuplicate(diag, &true_diag));
223:         PetscCall(MatGetDiagonal(pc->pmat, true_diag));
224:         PetscCall(VecGetLocalSize(diag, &n));
225:         PetscCall(VecGetArrayWrite(diag, &x2));
226:         PetscCall(VecGetArrayRead(true_diag, &x)); // to make more general -todo
227:         for (i = 0; i < n; i++) {
228:           if (PetscRealPart(x[i]) < 0.0) {
229:             x2[i]   = -x2[i]; // flip sign to keep DA > 0
230:             negflag = PETSC_TRUE;
231:           }
232:         }
233:         PetscCall(VecRestoreArrayRead(true_diag, &x));
234:         PetscCall(VecRestoreArrayWrite(diag, &x2));
235:         PetscCheck(!jac->useabs || !negflag, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Jacobi use_abs and l1 not compatible with negative diagonal");
236:         PetscCall(VecDestroy(&true_diag));
237:       }
238:       if (jac->scale != 1.0) {
239:         Vec true_diag;
240:         PetscCall(VecDuplicate(diag, &true_diag));
241:         PetscCall(MatGetDiagonal(pc->pmat, true_diag));
242:         PetscCall(VecAXPY(diag, -1, true_diag)); // subtract off diag
243:         PetscCall(VecScale(diag, jac->scale));   // scale off-diag
244:         PetscCall(VecAXPY(diag, 1, true_diag));  // add diag back in
245:         PetscCall(VecDestroy(&true_diag));
246:       }
247:       break;
248:     case PC_JACOBI_ROWSUM:
249:       PetscCall(MatGetRowSum(pc->pmat, diag));
250:       break;
251:     }
252:     PetscCall(VecReciprocal(diag));
253:     if (jac->useabs) PetscCall(VecAbs(diag));
254:     PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd));
255:     if (jac->fixdiag && (!isset || !isspd)) {
256:       PetscScalar *x;
257:       PetscCall(VecGetLocalSize(diag, &n));
258:       PetscCall(VecGetArray(diag, &x));
259:       for (i = 0; i < n; i++) {
260:         if (x[i] == 0.0) {
261:           x[i]     = 1.0;
262:           zeroflag = PETSC_TRUE;
263:         }
264:       }
265:       PetscCall(VecRestoreArray(diag, &x));
266:     }
267:     PetscCall(VecLockReadPush(diag));
268:   }
269:   if (diagsqrt) {
270:     PetscScalar *x;

272:     PetscCall(VecLockReadPop(diagsqrt));
273:     switch (jac->type) {
274:     case PC_JACOBI_DIAGONAL:
275:       PetscCall(MatGetDiagonal(pc->pmat, diagsqrt));
276:       break;
277:     case PC_JACOBI_ROWMAX:
278:       PetscCall(MatGetRowMaxAbs(pc->pmat, diagsqrt, NULL));
279:       break;
280:     case PC_JACOBI_ROWL1:
281:       PetscCall(MatGetRowSumAbs(pc->pmat, diagsqrt));
282:       break;
283:     case PC_JACOBI_ROWSUM:
284:       PetscCall(MatGetRowSum(pc->pmat, diagsqrt));
285:       break;
286:     }
287:     PetscCall(VecGetLocalSize(diagsqrt, &n));
288:     PetscCall(VecGetArray(diagsqrt, &x));
289:     for (i = 0; i < n; i++) {
290:       if (PetscRealPart(x[i]) < 0.0) x[i] = 1.0 / PetscSqrtReal(PetscAbsScalar(-x[i]));
291:       else if (PetscRealPart(x[i]) > 0.0) x[i] = 1.0 / PetscSqrtReal(PetscAbsScalar(x[i]));
292:       else {
293:         x[i]     = 1.0;
294:         zeroflag = PETSC_TRUE;
295:       }
296:     }
297:     PetscCall(VecRestoreArray(diagsqrt, &x));
298:     PetscCall(VecLockReadPush(diagsqrt));
299:   }
300:   if (zeroflag) PetscCall(PetscInfo(pc, "Zero detected in diagonal of matrix, using 1 at those locations\n"));
301:   PetscFunctionReturn(PETSC_SUCCESS);
302: }

304: /*
305:    PCSetUp_Jacobi_Symmetric - Allocates the vector needed to store the
306:    inverse of the square root of the diagonal entries of the matrix.  This
307:    is used for symmetric application of the Jacobi preconditioner.

309:    Input Parameter:
310: .  pc - the preconditioner context
311: */
312: static PetscErrorCode PCSetUp_Jacobi_Symmetric(PC pc)
313: {
314:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

316:   PetscFunctionBegin;
317:   PetscCall(MatCreateVecs(pc->pmat, &jac->diagsqrt, NULL));
318:   PetscCall(VecLockReadPush(jac->diagsqrt));
319:   PetscCall(PCSetUp_Jacobi(pc));
320:   PetscFunctionReturn(PETSC_SUCCESS);
321: }

323: /*
324:    PCSetUp_Jacobi_NonSymmetric - Allocates the vector needed to store the
325:    inverse of the diagonal entries of the matrix.  This is used for left of
326:    right application of the Jacobi preconditioner.

328:    Input Parameter:
329: .  pc - the preconditioner context
330: */
331: static PetscErrorCode PCSetUp_Jacobi_NonSymmetric(PC pc)
332: {
333:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

335:   PetscFunctionBegin;
336:   PetscCall(MatCreateVecs(pc->pmat, &jac->diag, NULL));
337:   PetscCall(VecLockReadPush(jac->diag));
338:   PetscCall(PCSetUp_Jacobi(pc));
339:   PetscFunctionReturn(PETSC_SUCCESS);
340: }

342: /*
343:    PCApply_Jacobi - Applies the Jacobi preconditioner to a vector.

345:    Input Parameters:
346: .  pc - the preconditioner context
347: .  x - input vector

349:    Output Parameter:
350: .  y - output vector

352:    Application Interface Routine: PCApply()
353:  */
354: static PetscErrorCode PCApply_Jacobi(PC pc, Vec x, Vec y)
355: {
356:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

358:   PetscFunctionBegin;
359:   if (!jac->diag) PetscCall(PCSetUp_Jacobi_NonSymmetric(pc));
360:   PetscCall(VecPointwiseMult(y, x, jac->diag));
361:   PetscFunctionReturn(PETSC_SUCCESS);
362: }

364: /*
365:    PCApplySymmetricLeftOrRight_Jacobi - Applies the left or right part of a
366:    symmetric preconditioner to a vector.

368:    Input Parameters:
369: .  pc - the preconditioner context
370: .  x - input vector

372:    Output Parameter:
373: .  y - output vector

375:    Application Interface Routines: PCApplySymmetricLeft(), PCApplySymmetricRight()
376: */
377: static PetscErrorCode PCApplySymmetricLeftOrRight_Jacobi(PC pc, Vec x, Vec y)
378: {
379:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

381:   PetscFunctionBegin;
382:   if (!jac->diagsqrt) PetscCall(PCSetUp_Jacobi_Symmetric(pc));
383:   PetscCall(VecPointwiseMult(y, x, jac->diagsqrt));
384:   PetscFunctionReturn(PETSC_SUCCESS);
385: }

387: static PetscErrorCode PCReset_Jacobi(PC pc)
388: {
389:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;

391:   PetscFunctionBegin;
392:   if (jac->diag) PetscCall(VecLockReadPop(jac->diag));
393:   if (jac->diagsqrt) PetscCall(VecLockReadPop(jac->diagsqrt));
394:   PetscCall(VecDestroy(&jac->diag));
395:   PetscCall(VecDestroy(&jac->diagsqrt));
396:   PetscFunctionReturn(PETSC_SUCCESS);
397: }

399: /*
400:    PCDestroy_Jacobi - Destroys the private context for the Jacobi preconditioner
401:    that was created with PCCreate_Jacobi().

403:    Input Parameter:
404: .  pc - the preconditioner context

406:    Application Interface Routine: PCDestroy()
407: */
408: static PetscErrorCode PCDestroy_Jacobi(PC pc)
409: {
410:   PetscFunctionBegin;
411:   PetscCall(PCReset_Jacobi(pc));
412:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetType_C", NULL));
413:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetType_C", NULL));
414:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetUseAbs_C", NULL));
415:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetUseAbs_C", NULL));
416:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetRowl1Scale_C", NULL));
417:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetRowl1Scale_C", NULL));
418:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetFixDiagonal_C", NULL));
419:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetFixDiagonal_C", NULL));
420:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetDiagonal_C", NULL));

422:   /*
423:       Free the private data structure that was hanging off the PC
424:   */
425:   PetscCall(PetscFree(pc->data));
426:   PetscFunctionReturn(PETSC_SUCCESS);
427: }

429: static PetscErrorCode PCSetFromOptions_Jacobi(PC pc, PetscOptionItems *PetscOptionsObject)
430: {
431:   PC_Jacobi   *jac = (PC_Jacobi *)pc->data;
432:   PetscBool    flg;
433:   PCJacobiType deflt, type;

435:   PetscFunctionBegin;
436:   PetscCall(PCJacobiGetType(pc, &deflt));
437:   PetscOptionsHeadBegin(PetscOptionsObject, "Jacobi options");
438:   PetscCall(PetscOptionsEnum("-pc_jacobi_type", "How to construct diagonal matrix", "PCJacobiSetType", PCJacobiTypes, (PetscEnum)deflt, (PetscEnum *)&type, &flg));
439:   if (flg) PetscCall(PCJacobiSetType(pc, type));
440:   PetscCall(PetscOptionsBool("-pc_jacobi_abs", "Use absolute values of diagonal entries", "PCJacobiSetUseAbs", jac->useabs, &jac->useabs, NULL));
441:   PetscCall(PetscOptionsBool("-pc_jacobi_fixdiagonal", "Fix null terms on diagonal", "PCJacobiSetFixDiagonal", jac->fixdiag, &jac->fixdiag, NULL));
442:   PetscCall(PetscOptionsRangeReal("-pc_jacobi_rowl1_scale", "scaling of off-diagonal elements for rowl1", "PCJacobiSetRowl1Scale", jac->scale, &jac->scale, NULL, 0.0, 1.0));
443:   PetscOptionsHeadEnd();
444:   PetscFunctionReturn(PETSC_SUCCESS);
445: }

447: static PetscErrorCode PCView_Jacobi(PC pc, PetscViewer viewer)
448: {
449:   PC_Jacobi *jac = (PC_Jacobi *)pc->data;
450:   PetscBool  iascii;

452:   PetscFunctionBegin;
453:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
454:   if (iascii) {
455:     PCJacobiType      type;
456:     PetscBool         useAbs, fixdiag;
457:     PetscViewerFormat format;
458:     PetscReal         scale;

460:     PetscCall(PCJacobiGetType(pc, &type));
461:     PetscCall(PCJacobiGetUseAbs(pc, &useAbs));
462:     PetscCall(PCJacobiGetFixDiagonal(pc, &fixdiag));
463:     PetscCall(PCJacobiGetRowl1Scale(pc, &scale));
464:     if (type == PC_JACOBI_ROWL1)
465:       PetscCall(PetscViewerASCIIPrintf(viewer, "  type %s%s%s (l1-norm off-diagonal scaling %e)\n", PCJacobiTypes[type], useAbs ? ", using absolute value of entries" : "", !fixdiag ? ", not checking null diagonal entries" : "", (double)scale));
466:     else PetscCall(PetscViewerASCIIPrintf(viewer, "  type %s%s%s\n", PCJacobiTypes[type], useAbs ? ", using absolute value of entries" : "", !fixdiag ? ", not checking null diagonal entries" : ""));
467:     PetscCall(PetscViewerGetFormat(viewer, &format));
468:     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL && jac->diag) PetscCall(VecView(jac->diag, viewer));
469:   }
470:   PetscFunctionReturn(PETSC_SUCCESS);
471: }

473: /*
474:    PCCreate_Jacobi - Creates a Jacobi preconditioner context, PC_Jacobi,
475:    and sets this as the private data within the generic preconditioning
476:    context, PC, that was created within PCCreate().

478:    Input Parameter:
479: .  pc - the preconditioner context

481:    Application Interface Routine: PCCreate()
482: */

484: /*MC
485:      PCJACOBI - Jacobi (i.e. diagonal scaling preconditioning)

487:    Options Database Keys:
488: +    -pc_jacobi_type <diagonal,rowl1,rowmax,rowsum> - approach for forming the preconditioner
489: .    -pc_jacobi_abs - use the absolute value of the diagonal entry
490: .    -pc_jacobi_rowl1_scale - scaling of off-diagonal terms
491: -    -pc_jacobi_fixdiag - fix for zero diagonal terms by placing 1.0 in those locations

493:    Level: beginner

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

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

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

503: .seealso:  `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
504:            `PCJacobiSetType()`, `PCJacobiSetUseAbs()`, `PCJacobiGetUseAbs()`, `PCASM`,
505:            `PCJacobiSetFixDiagonal()`, `PCJacobiGetFixDiagonal()`
506:            `PCJacobiSetType()`, `PCJacobiSetUseAbs()`, `PCJacobiGetUseAbs()`, `PCPBJACOBI`, `PCBJACOBI`, `PCVPBJACOBI`
507: M*/

509: PETSC_EXTERN PetscErrorCode PCCreate_Jacobi(PC pc)
510: {
511:   PC_Jacobi *jac;

513:   PetscFunctionBegin;
514:   /*
515:      Creates the private data structure for this preconditioner and
516:      attach it to the PC object.
517:   */
518:   PetscCall(PetscNew(&jac));
519:   pc->data = (void *)jac;

521:   /*
522:      Initialize the pointers to vectors to ZERO; these will be used to store
523:      diagonal entries of the matrix for fast preconditioner application.
524:   */
525:   jac->diag     = NULL;
526:   jac->diagsqrt = NULL;
527:   jac->type     = PC_JACOBI_DIAGONAL;
528:   jac->useabs   = PETSC_FALSE;
529:   jac->fixdiag  = PETSC_TRUE;
530:   jac->scale    = 1.0;

532:   /*
533:       Set the pointers for the functions that are provided above.
534:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
535:       are called, they will automatically call these functions.  Note we
536:       choose not to provide a couple of these functions since they are
537:       not needed.
538:   */
539:   pc->ops->apply               = PCApply_Jacobi;
540:   pc->ops->applytranspose      = PCApply_Jacobi;
541:   pc->ops->setup               = PCSetUp_Jacobi;
542:   pc->ops->reset               = PCReset_Jacobi;
543:   pc->ops->destroy             = PCDestroy_Jacobi;
544:   pc->ops->setfromoptions      = PCSetFromOptions_Jacobi;
545:   pc->ops->view                = PCView_Jacobi;
546:   pc->ops->applyrichardson     = NULL;
547:   pc->ops->applysymmetricleft  = PCApplySymmetricLeftOrRight_Jacobi;
548:   pc->ops->applysymmetricright = PCApplySymmetricLeftOrRight_Jacobi;

550:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetType_C", PCJacobiSetType_Jacobi));
551:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetType_C", PCJacobiGetType_Jacobi));
552:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetRowl1Scale_C", PCJacobiSetRowl1Scale_Jacobi));
553:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetRowl1Scale_C", PCJacobiGetRowl1Scale_Jacobi));
554:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetUseAbs_C", PCJacobiSetUseAbs_Jacobi));
555:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetUseAbs_C", PCJacobiGetUseAbs_Jacobi));
556:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiSetFixDiagonal_C", PCJacobiSetFixDiagonal_Jacobi));
557:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetFixDiagonal_C", PCJacobiGetFixDiagonal_Jacobi));
558:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCJacobiGetDiagonal_C", PCJacobiGetDiagonal_Jacobi));
559:   PetscFunctionReturn(PETSC_SUCCESS);
560: }

562: /*@
563:   PCJacobiSetUseAbs - Causes the Jacobi preconditioner `PCJACOBI` to use the
564:   absolute values of the diagonal divisors in the preconditioner

566:   Logically Collective

568:   Input Parameters:
569: + pc  - the preconditioner context
570: - flg - whether to use absolute values or not

572:   Options Database Key:
573: . -pc_jacobi_abs <bool> - use absolute values

575:   Note:
576:   This takes affect at the next construction of the preconditioner

578:   Level: intermediate

580: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiGetUseAbs()`
581: @*/
582: PetscErrorCode PCJacobiSetUseAbs(PC pc, PetscBool flg)
583: {
584:   PetscFunctionBegin;
586:   PetscTryMethod(pc, "PCJacobiSetUseAbs_C", (PC, PetscBool), (pc, flg));
587:   PetscFunctionReturn(PETSC_SUCCESS);
588: }

590: /*@
591:   PCJacobiGetUseAbs - Determines if the Jacobi preconditioner `PCJACOBI` uses the
592:   absolute values of the diagonal divisors in the preconditioner

594:   Logically Collective

596:   Input Parameter:
597: . pc - the preconditioner context

599:   Output Parameter:
600: . flg - whether to use absolute values or not

602:   Level: intermediate

604: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiSetUseAbs()`, `PCJacobiGetType()`
605: @*/
606: PetscErrorCode PCJacobiGetUseAbs(PC pc, PetscBool *flg)
607: {
608:   PetscFunctionBegin;
610:   PetscUseMethod(pc, "PCJacobiGetUseAbs_C", (PC, PetscBool *), (pc, flg));
611:   PetscFunctionReturn(PETSC_SUCCESS);
612: }

614: /*@
615:   PCJacobiSetRowl1Scale - Set scaling of off-diagonal of operator when computing l1 row norms, eg,
616:   Remark 6.1 in "Multigrid Smoothers for Ultraparallel Computing", Baker et al, with 0.5 scaling

618:   Logically Collective

620:   Input Parameters:
621: + pc    - the preconditioner context
622: - scale - scaling

624:   Options Database Key:
625: . -pc_jacobi_rowl1_scale <real> - use absolute values

627:   Level: intermediate

629: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiGetRowl1Scale()`
630: @*/
631: PetscErrorCode PCJacobiSetRowl1Scale(PC pc, PetscReal scale)
632: {
633:   PetscFunctionBegin;
635:   PetscTryMethod(pc, "PCJacobiSetRowl1Scale_C", (PC, PetscReal), (pc, scale));
636:   PetscFunctionReturn(PETSC_SUCCESS);
637: }

639: /*@
640:   PCJacobiGetRowl1Scale - Get scaling of off-diagonal elements summed into l1-norm diagonal

642:   Logically Collective

644:   Input Parameter:
645: . pc - the preconditioner context

647:   Output Parameter:
648: . scale - scaling

650:   Level: intermediate

652: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiSetRowl1Scale()`, `PCJacobiGetType()`
653: @*/
654: PetscErrorCode PCJacobiGetRowl1Scale(PC pc, PetscReal *scale)
655: {
656:   PetscFunctionBegin;
658:   PetscUseMethod(pc, "PCJacobiGetRowl1Scale_C", (PC, PetscReal *), (pc, scale));
659:   PetscFunctionReturn(PETSC_SUCCESS);
660: }

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

665:   Logically Collective

667:   Input Parameters:
668: + pc  - the preconditioner context
669: - flg - the boolean flag

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

674:   Note:
675:   This takes affect at the next construction of the preconditioner

677:   Level: intermediate

679: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiGetFixDiagonal()`, `PCJacobiSetUseAbs()`
680: @*/
681: PetscErrorCode PCJacobiSetFixDiagonal(PC pc, PetscBool flg)
682: {
683:   PetscFunctionBegin;
685:   PetscTryMethod(pc, "PCJacobiSetFixDiagonal_C", (PC, PetscBool), (pc, flg));
686:   PetscFunctionReturn(PETSC_SUCCESS);
687: }

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

692:   Logically Collective

694:   Input Parameter:
695: . pc - the preconditioner context

697:   Output Parameter:
698: . flg - the boolean flag

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

703:   Level: intermediate

705: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`, `PCJacobiSetFixDiagonal()`
706: @*/
707: PetscErrorCode PCJacobiGetFixDiagonal(PC pc, PetscBool *flg)
708: {
709:   PetscFunctionBegin;
711:   PetscUseMethod(pc, "PCJacobiGetFixDiagonal_C", (PC, PetscBool *), (pc, flg));
712:   PetscFunctionReturn(PETSC_SUCCESS);
713: }

715: /*@
716:   PCJacobiGetDiagonal - Returns copy of the diagonal and/or diagonal squareroot `Vec`

718:   Logically Collective

720:   Input Parameter:
721: . pc - the preconditioner context

723:   Output Parameters:
724: + diagonal      - Copy of `Vec` of the inverted diagonal
725: - diagonal_sqrt - Copy of `Vec` of the inverted square root diagonal

727:   Level: developer

729: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetType()`
730: @*/
731: PetscErrorCode PCJacobiGetDiagonal(PC pc, Vec diagonal, Vec diagonal_sqrt)
732: {
733:   PetscFunctionBegin;
735:   PetscUseMethod(pc, "PCJacobiGetDiagonal_C", (PC, Vec, Vec), (pc, diagonal, diagonal_sqrt));
736:   PetscFunctionReturn(PETSC_SUCCESS);
737: }

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

743:   Logically Collective

745:   Input Parameters:
746: + pc   - the preconditioner context
747: - type - `PC_JACOBI_DIAGONAL`, `PC_JACOBI_ROWL1`, `PC_JACOBI_ROWMAX`, `PC_JACOBI_ROWSUM`

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

752:   Level: intermediate

754:   Developer Notes:
755:   Why is there a separate function for using the absolute value?

757: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiSetUseAbs()`, `PCJacobiGetType()`
758: @*/
759: PetscErrorCode PCJacobiSetType(PC pc, PCJacobiType type)
760: {
761:   PetscFunctionBegin;
763:   PetscTryMethod(pc, "PCJacobiSetType_C", (PC, PCJacobiType), (pc, type));
764:   PetscFunctionReturn(PETSC_SUCCESS);
765: }

767: /*@
768:   PCJacobiGetType - Gets how the diagonal matrix is produced for the preconditioner

770:   Not Collective

772:   Input Parameter:
773: . pc - the preconditioner context

775:   Output Parameter:
776: . type - `PC_JACOBI_DIAGONAL`, `PC_JACOBI_ROWL1`, `PC_JACOBI_ROWMAX`, `PC_JACOBI_ROWSUM`

778:   Level: intermediate

780: .seealso: [](ch_ksp), `PCJACOBI`, `PCJacobiaUseAbs()`, `PCJacobiSetType()`
781: @*/
782: PetscErrorCode PCJacobiGetType(PC pc, PCJacobiType *type)
783: {
784:   PetscFunctionBegin;
786:   PetscUseMethod(pc, "PCJacobiGetType_C", (PC, PCJacobiType *), (pc, type));
787:   PetscFunctionReturn(PETSC_SUCCESS);
788: }