Actual source code: precon.c


  2: /*
  3:     The PC (preconditioner) interface routines, callable by users.
  4: */
  5: #include <petsc/private/pcimpl.h>
  6: #include <petscdm.h>

  8: /* Logging support */
  9: PetscClassId  PC_CLASSID;
 10: PetscLogEvent PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_MatApply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;
 11: PetscLogEvent PC_ApplySymmetricRight, PC_ModifySubMatrices, PC_ApplyOnBlocks, PC_ApplyTransposeOnBlocks;
 12: PetscInt      PetscMGLevelId;

 14: PetscErrorCode PCGetDefaultType_Private(PC pc, const char *type[])
 15: {
 16:   PetscMPIInt size;
 17:   PetscBool   hasop, flg1, flg2, set, flg3, isnormal;

 19:   MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size);
 20:   if (pc->pmat) {
 21:     MatHasOperation(pc->pmat, MATOP_GET_DIAGONAL_BLOCK, &hasop);
 22:     if (size == 1) {
 23:       MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ICC, &flg1);
 24:       MatGetFactorAvailable(pc->pmat, "petsc", MAT_FACTOR_ILU, &flg2);
 25:       MatIsSymmetricKnown(pc->pmat, &set, &flg3);
 26:       PetscObjectTypeCompareAny((PetscObject)pc->pmat, &isnormal, MATNORMAL, MATNORMALHERMITIAN, NULL);
 27:       if (flg1 && (!flg2 || (set && flg3))) {
 28:         *type = PCICC;
 29:       } else if (flg2) {
 30:         *type = PCILU;
 31:       } else if (isnormal) {
 32:         *type = PCNONE;
 33:       } else if (hasop) { /* likely is a parallel matrix run on one processor */
 34:         *type = PCBJACOBI;
 35:       } else {
 36:         *type = PCNONE;
 37:       }
 38:     } else {
 39:       if (hasop) {
 40:         *type = PCBJACOBI;
 41:       } else {
 42:         *type = PCNONE;
 43:       }
 44:     }
 45:   } else {
 46:     if (size == 1) {
 47:       *type = PCILU;
 48:     } else {
 49:       *type = PCBJACOBI;
 50:     }
 51:   }
 52:   return 0;
 53: }

 55: /*@
 56:    PCReset - Resets a PC context to the pcsetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s

 58:    Collective on pc

 60:    Input Parameter:
 61: .  pc - the preconditioner context

 63:    Level: developer

 65:    Note:
 66:     This allows a `PC` to be reused for a different sized linear system but using the same options that have been previously set in the PC

 68: .seealso: `PC`, `PCCreate()`, `PCSetUp()`
 69: @*/
 70: PetscErrorCode PCReset(PC pc)
 71: {
 73:   PetscTryTypeMethod(pc, reset);
 74:   VecDestroy(&pc->diagonalscaleright);
 75:   VecDestroy(&pc->diagonalscaleleft);
 76:   MatDestroy(&pc->pmat);
 77:   MatDestroy(&pc->mat);

 79:   pc->setupcalled = 0;
 80:   return 0;
 81: }

 83: /*@C
 84:    PCDestroy - Destroys `PC` context that was created with `PCCreate()`.

 86:    Collective on pc

 88:    Input Parameter:
 89: .  pc - the preconditioner context

 91:    Level: developer

 93: .seealso: `PC`, `PCCreate()`, `PCSetUp()`
 94: @*/
 95: PetscErrorCode PCDestroy(PC *pc)
 96: {
 97:   if (!*pc) return 0;
 99:   if (--((PetscObject)(*pc))->refct > 0) {
100:     *pc = NULL;
101:     return 0;
102:   }

104:   PCReset(*pc);

106:   /* if memory was published with SAWs then destroy it */
107:   PetscObjectSAWsViewOff((PetscObject)*pc);
108:   PetscTryTypeMethod((*pc), destroy);
109:   DMDestroy(&(*pc)->dm);
110:   PetscHeaderDestroy(pc);
111:   return 0;
112: }

114: /*@C
115:    PCGetDiagonalScale - Indicates if the preconditioner applies an additional left and right
116:       scaling as needed by certain time-stepping codes.

118:    Logically Collective on pc

120:    Input Parameter:
121: .  pc - the preconditioner context

123:    Output Parameter:
124: .  flag - `PETSC_TRUE` if it applies the scaling

126:    Level: developer

128:    Note:
129:     If this returns `PETSC_TRUE` then the system solved via the Krylov method is
130: .vb
131:       D M A D^{-1} y = D M b  for left preconditioning or
132:       D A M D^{-1} z = D b for right preconditioning
133: .ve

135: .seealso: `PC`, `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCSetDiagonalScale()`
136: @*/
137: PetscErrorCode PCGetDiagonalScale(PC pc, PetscBool *flag)
138: {
141:   *flag = pc->diagonalscale;
142:   return 0;
143: }

145: /*@
146:    PCSetDiagonalScale - Indicates the left scaling to use to apply an additional left and right
147:       scaling as needed by certain time-stepping codes.

149:    Logically Collective on pc

151:    Input Parameters:
152: +  pc - the preconditioner context
153: -  s - scaling vector

155:    Level: intermediate

157:    Notes:
158:     The system solved via the Krylov method is
159: .vb
160:            D M A D^{-1} y = D M b  for left preconditioning or
161:            D A M D^{-1} z = D b for right preconditioning
162: .ve

164:    `PCDiagonalScaleLeft()` scales a vector by D. `PCDiagonalScaleRight()` scales a vector by D^{-1}.

166: .seealso: `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleRight()`, `PCGetDiagonalScale()`
167: @*/
168: PetscErrorCode PCSetDiagonalScale(PC pc, Vec s)
169: {
172:   pc->diagonalscale = PETSC_TRUE;

174:   PetscObjectReference((PetscObject)s);
175:   VecDestroy(&pc->diagonalscaleleft);

177:   pc->diagonalscaleleft = s;

179:   VecDuplicate(s, &pc->diagonalscaleright);
180:   VecCopy(s, pc->diagonalscaleright);
181:   VecReciprocal(pc->diagonalscaleright);
182:   return 0;
183: }

185: /*@
186:    PCDiagonalScaleLeft - Scales a vector by the left scaling as needed by certain time-stepping codes.

188:    Logically Collective on pc

190:    Input Parameters:
191: +  pc - the preconditioner context
192: .  in - input vector
193: -  out - scaled vector (maybe the same as in)

195:    Level: intermediate

197:    Notes:
198:     The system solved via the Krylov method is
199: .vb
200:         D M A D^{-1} y = D M b  for left preconditioning or
201:         D A M D^{-1} z = D b for right preconditioning
202: .ve

204:    `PCDiagonalScaleLeft()` scales a vector by D. `PCDiagonalScaleRight()` scales a vector by D^{-1}.

206:    If diagonal scaling is turned off and in is not out then in is copied to out

208: .seealso: `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleSet()`, `PCDiagonalScaleRight()`, `PCDiagonalScale()`
209: @*/
210: PetscErrorCode PCDiagonalScaleLeft(PC pc, Vec in, Vec out)
211: {
215:   if (pc->diagonalscale) {
216:     VecPointwiseMult(out, pc->diagonalscaleleft, in);
217:   } else if (in != out) {
218:     VecCopy(in, out);
219:   }
220:   return 0;
221: }

223: /*@
224:    PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.

226:    Logically Collective on pc

228:    Input Parameters:
229: +  pc - the preconditioner context
230: .  in - input vector
231: -  out - scaled vector (maybe the same as in)

233:    Level: intermediate

235:    Notes:
236:     The system solved via the Krylov method is
237: .vb
238:         D M A D^{-1} y = D M b  for left preconditioning or
239:         D A M D^{-1} z = D b for right preconditioning
240: .ve

242:    `PCDiagonalScaleLeft()` scales a vector by D. `PCDiagonalScaleRight()` scales a vector by D^{-1}.

244:    If diagonal scaling is turned off and in is not out then in is copied to out

246: .seealso: `PCCreate()`, `PCSetUp()`, `PCDiagonalScaleLeft()`, `PCDiagonalScaleSet()`, `PCDiagonalScale()`
247: @*/
248: PetscErrorCode PCDiagonalScaleRight(PC pc, Vec in, Vec out)
249: {
253:   if (pc->diagonalscale) {
254:     VecPointwiseMult(out, pc->diagonalscaleright, in);
255:   } else if (in != out) {
256:     VecCopy(in, out);
257:   }
258:   return 0;
259: }

261: /*@
262:    PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the
263:    operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
264:    `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.

266:    Logically Collective on pc

268:    Input Parameters:
269: +  pc - the preconditioner context
270: -  flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)

272:    Options Database Key:
273: .  -pc_use_amat <true,false> - use the amat to apply the operator

275:    Note:
276:    For the common case in which the linear system matrix and the matrix used to construct the
277:    preconditioner are identical, this routine is does nothing.

279:    Level: intermediate

281: .seealso: `PC`, `PCGetUseAmat()`, `PCBJACOBI`, `PGMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
282: @*/
283: PetscErrorCode PCSetUseAmat(PC pc, PetscBool flg)
284: {
286:   pc->useAmat = flg;
287:   return 0;
288: }

290: /*@
291:    PCSetErrorIfFailure - Causes `PC` to generate an error if a FPE, for example a zero pivot, is detected.

293:    Logically Collective on pc

295:    Input Parameters:
296: +  pc - iterative context obtained from PCCreate()
297: -  flg - `PETSC_TRUE` indicates you want the error generated

299:    Level: advanced

301:    Notes:
302:     Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call `KSPGetConvergedReason()` after a `KSPSolve()`
303:     to determine if it has converged or failed. Or use -ksp_error_if_not_converged to cause the program to terminate as soon as lack of convergence is
304:     detected.

306:     This is propagated into KSPs used by this PC, which then propagate it into PCs used by those KSPs

308: .seealso: `PC`, `KSPSetErrorIfNotConverged()`, `PCGetInitialGuessNonzero()`, `PCSetInitialGuessKnoll()`, `PCGetInitialGuessKnoll()`
309: @*/
310: PetscErrorCode PCSetErrorIfFailure(PC pc, PetscBool flg)
311: {
314:   pc->erroriffailure = flg;
315:   return 0;
316: }

318: /*@
319:    PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the
320:    operator during the preconditioning process it applies the Amat provided to `TSSetRHSJacobian()`,
321:    `TSSetIJacobian()`, `SNESSetJacobian()`, `KSPSetOperators()` or `PCSetOperators()` not the Pmat.

323:    Logically Collective on pc

325:    Input Parameter:
326: .  pc - the preconditioner context

328:    Output Parameter:
329: .  flg - `PETSC_TRUE` to use the Amat, `PETSC_FALSE` to use the Pmat (default is false)

331:    Note:
332:    For the common case in which the linear system matrix and the matrix used to construct the
333:    preconditioner are identical, this routine is does nothing.

335:    Level: intermediate

337: .seealso: `PC`, `PCSetUseAmat()`, `PCBJACOBI`, `PGMG`, `PCFIELDSPLIT`, `PCCOMPOSITE`
338: @*/
339: PetscErrorCode PCGetUseAmat(PC pc, PetscBool *flg)
340: {
342:   *flg = pc->useAmat;
343:   return 0;
344: }

346: /*@
347:    PCCreate - Creates a preconditioner context, `PC`

349:    Collective

351:    Input Parameter:
352: .  comm - MPI communicator

354:    Output Parameter:
355: .  pc - location to put the preconditioner context

357:    Note:
358:    The default preconditioner for sparse matrices is `PCILU` or `PCICC` with 0 fill on one process and block Jacobi (`PCBJACOBI`) with `PCILU` or `PCICC`
359:    in parallel. For dense matrices it is always `PCNONE`.

361:    Level: developer

363: .seealso: `PC`, `PCSetUp()`, `PCApply()`, `PCDestroy()`
364: @*/
365: PetscErrorCode PCCreate(MPI_Comm comm, PC *newpc)
366: {
367:   PC pc;

370:   *newpc = NULL;
371:   PCInitializePackage();

373:   PetscHeaderCreate(pc, PC_CLASSID, "PC", "Preconditioner", "PC", comm, PCDestroy, PCView);

375:   pc->mat                  = NULL;
376:   pc->pmat                 = NULL;
377:   pc->setupcalled          = 0;
378:   pc->setfromoptionscalled = 0;
379:   pc->data                 = NULL;
380:   pc->diagonalscale        = PETSC_FALSE;
381:   pc->diagonalscaleleft    = NULL;
382:   pc->diagonalscaleright   = NULL;

384:   pc->modifysubmatrices  = NULL;
385:   pc->modifysubmatricesP = NULL;

387:   *newpc = pc;
388:   return 0;
389: }

391: /*@
392:    PCApply - Applies the preconditioner to a vector.

394:    Collective on pc

396:    Input Parameters:
397: +  pc - the preconditioner context
398: -  x - input vector

400:    Output Parameter:
401: .  y - output vector

403:    Level: developer

405: .seealso: `PC`, `PCApplyTranspose()`, `PCApplyBAorAB()`
406: @*/
407: PetscErrorCode PCApply(PC pc, Vec x, Vec y)
408: {
409:   PetscInt m, n, mv, nv;

415:   if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
416:   /* use pmat to check vector sizes since for KSPLSQR the pmat may be of a different size than mat */
417:   MatGetLocalSize(pc->pmat, &m, &n);
418:   VecGetLocalSize(x, &mv);
419:   VecGetLocalSize(y, &nv);
420:   /* check pmat * y = x is feasible */
423:   VecSetErrorIfLocked(y, 3);

425:   PCSetUp(pc);
426:   VecLockReadPush(x);
427:   PetscLogEventBegin(PC_Apply, pc, x, y, 0);
428:   PetscUseTypeMethod(pc, apply, x, y);
429:   PetscLogEventEnd(PC_Apply, pc, x, y, 0);
430:   if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
431:   VecLockReadPop(x);
432:   return 0;
433: }

435: /*@
436:    PCMatApply - Applies the preconditioner to multiple vectors stored as a `MATDENSE`. Like `PCApply()`, Y and X must be different matrices.

438:    Collective on pc

440:    Input Parameters:
441: +  pc - the preconditioner context
442: -  X - block of input vectors

444:    Output Parameter:
445: .  Y - block of output vectors

447:    Level: developer

449: .seealso: `PC`, `PCApply()`, `KSPMatSolve()`
450: @*/
451: PetscErrorCode PCMatApply(PC pc, Mat X, Mat Y)
452: {
453:   Mat       A;
454:   Vec       cy, cx;
455:   PetscInt  m1, M1, m2, M2, n1, N1, n2, N2, m3, M3, n3, N3;
456:   PetscBool match;

464:   PCGetOperators(pc, NULL, &A);
465:   MatGetLocalSize(A, &m3, &n3);
466:   MatGetLocalSize(X, &m2, &n2);
467:   MatGetLocalSize(Y, &m1, &n1);
468:   MatGetSize(A, &M3, &N3);
469:   MatGetSize(X, &M2, &N2);
470:   MatGetSize(Y, &M1, &N1);
474:   PetscObjectBaseTypeCompareAny((PetscObject)Y, &match, MATSEQDENSE, MATMPIDENSE, "");
476:   PetscObjectBaseTypeCompareAny((PetscObject)X, &match, MATSEQDENSE, MATMPIDENSE, "");
478:   PCSetUp(pc);
479:   if (pc->ops->matapply) {
480:     PetscLogEventBegin(PC_MatApply, pc, X, Y, 0);
481:     PetscUseTypeMethod(pc, matapply, X, Y);
482:     PetscLogEventEnd(PC_MatApply, pc, X, Y, 0);
483:   } else {
484:     PetscInfo(pc, "PC type %s applying column by column\n", ((PetscObject)pc)->type_name);
485:     for (n1 = 0; n1 < N1; ++n1) {
486:       MatDenseGetColumnVecRead(X, n1, &cx);
487:       MatDenseGetColumnVecWrite(Y, n1, &cy);
488:       PCApply(pc, cx, cy);
489:       MatDenseRestoreColumnVecWrite(Y, n1, &cy);
490:       MatDenseRestoreColumnVecRead(X, n1, &cx);
491:     }
492:   }
493:   return 0;
494: }

496: /*@
497:    PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.

499:    Collective on pc

501:    Input Parameters:
502: +  pc - the preconditioner context
503: -  x - input vector

505:    Output Parameter:
506: .  y - output vector

508:    Note:
509:    Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.

511:    Level: developer

513: .seealso: `PC`, `PCApply()`, `PCApplySymmetricRight()`
514: @*/
515: PetscErrorCode PCApplySymmetricLeft(PC pc, Vec x, Vec y)
516: {
521:   if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
522:   PCSetUp(pc);
523:   VecLockReadPush(x);
524:   PetscLogEventBegin(PC_ApplySymmetricLeft, pc, x, y, 0);
525:   PetscUseTypeMethod(pc, applysymmetricleft, x, y);
526:   PetscLogEventEnd(PC_ApplySymmetricLeft, pc, x, y, 0);
527:   VecLockReadPop(x);
528:   if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
529:   return 0;
530: }

532: /*@
533:    PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.

535:    Collective on pc

537:    Input Parameters:
538: +  pc - the preconditioner context
539: -  x - input vector

541:    Output Parameter:
542: .  y - output vector

544:    Level: developer

546:    Note:
547:    Currently, this routine is implemented only for `PCICC` and `PCJACOBI` preconditioners.

549: .seealso: `PC`, `PCApply()`, `PCApplySymmetricLeft()`
550: @*/
551: PetscErrorCode PCApplySymmetricRight(PC pc, Vec x, Vec y)
552: {
557:   if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
558:   PCSetUp(pc);
559:   VecLockReadPush(x);
560:   PetscLogEventBegin(PC_ApplySymmetricRight, pc, x, y, 0);
561:   PetscUseTypeMethod(pc, applysymmetricright, x, y);
562:   PetscLogEventEnd(PC_ApplySymmetricRight, pc, x, y, 0);
563:   VecLockReadPop(x);
564:   if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
565:   return 0;
566: }

568: /*@
569:    PCApplyTranspose - Applies the transpose of preconditioner to a vector.

571:    Collective on pc

573:    Input Parameters:
574: +  pc - the preconditioner context
575: -  x - input vector

577:    Output Parameter:
578: .  y - output vector

580:    Note:
581:     For complex numbers this applies the non-Hermitian transpose.

583:    Developer Note:
584:     We need to implement a `PCApplyHermitianTranspose()`

586:    Level: developer

588: .seealso: `PC`, `PCApply()`, `PCApplyBAorAB()`, `PCApplyBAorABTranspose()`, `PCApplyTransposeExists()`
589: @*/
590: PetscErrorCode PCApplyTranspose(PC pc, Vec x, Vec y)
591: {
596:   if (pc->erroriffailure) VecValidValues_Internal(x, 2, PETSC_TRUE);
597:   PCSetUp(pc);
598:   VecLockReadPush(x);
599:   PetscLogEventBegin(PC_Apply, pc, x, y, 0);
600:   PetscUseTypeMethod(pc, applytranspose, x, y);
601:   PetscLogEventEnd(PC_Apply, pc, x, y, 0);
602:   VecLockReadPop(x);
603:   if (pc->erroriffailure) VecValidValues_Internal(y, 3, PETSC_FALSE);
604:   return 0;
605: }

607: /*@
608:    PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation

610:    Collective on pc

612:    Input Parameter:
613: .  pc - the preconditioner context

615:    Output Parameter:
616: .  flg - `PETSC_TRUE` if a transpose operation is defined

618:    Level: developer

620: .seealso: `PC`, `PCApplyTranspose()`
621: @*/
622: PetscErrorCode PCApplyTransposeExists(PC pc, PetscBool *flg)
623: {
626:   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
627:   else *flg = PETSC_FALSE;
628:   return 0;
629: }

631: /*@
632:    PCApplyBAorAB - Applies the preconditioner and operator to a vector. y = B*A*x or y = A*B*x.

634:    Collective on pc

636:    Input Parameters:
637: +  pc - the preconditioner context
638: .  side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
639: .  x - input vector
640: -  work - work vector

642:    Output Parameter:
643: .  y - output vector

645:    Level: developer

647:    Note:
648:     If the `PC` has had `PCSetDiagonalScale()` set then D M A D^{-1} for left preconditioning or  D A M D^{-1} is actually applied. Note that the
649:    specific `KSPSolve()` method must also be written to handle the post-solve "correction" for the diagonal scaling.

651: .seealso: `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorABTranspose()`
652: @*/
653: PetscErrorCode PCApplyBAorAB(PC pc, PCSide side, Vec x, Vec y, Vec work)
654: {
666:   if (pc->erroriffailure) VecValidValues_Internal(x, 3, PETSC_TRUE);

668:   PCSetUp(pc);
669:   if (pc->diagonalscale) {
670:     if (pc->ops->applyBA) {
671:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
672:       VecDuplicate(x, &work2);
673:       PCDiagonalScaleRight(pc, x, work2);
674:       PetscUseTypeMethod(pc, applyBA, side, work2, y, work);
675:       PCDiagonalScaleLeft(pc, y, y);
676:       VecDestroy(&work2);
677:     } else if (side == PC_RIGHT) {
678:       PCDiagonalScaleRight(pc, x, y);
679:       PCApply(pc, y, work);
680:       MatMult(pc->mat, work, y);
681:       PCDiagonalScaleLeft(pc, y, y);
682:     } else if (side == PC_LEFT) {
683:       PCDiagonalScaleRight(pc, x, y);
684:       MatMult(pc->mat, y, work);
685:       PCApply(pc, work, y);
686:       PCDiagonalScaleLeft(pc, y, y);
688:   } else {
689:     if (pc->ops->applyBA) {
690:       PetscUseTypeMethod(pc, applyBA, side, x, y, work);
691:     } else if (side == PC_RIGHT) {
692:       PCApply(pc, x, work);
693:       MatMult(pc->mat, work, y);
694:     } else if (side == PC_LEFT) {
695:       MatMult(pc->mat, x, work);
696:       PCApply(pc, work, y);
697:     } else if (side == PC_SYMMETRIC) {
698:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
699:       PCApplySymmetricRight(pc, x, work);
700:       MatMult(pc->mat, work, y);
701:       VecCopy(y, work);
702:       PCApplySymmetricLeft(pc, work, y);
703:     }
704:   }
705:   if (pc->erroriffailure) VecValidValues_Internal(y, 4, PETSC_FALSE);
706:   return 0;
707: }

709: /*@
710:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
711:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
712:    NOT tr(B*A) = tr(A)*tr(B).

714:    Collective on pc

716:    Input Parameters:
717: +  pc - the preconditioner context
718: .  side - indicates the preconditioner side, one of `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
719: .  x - input vector
720: -  work - work vector

722:    Output Parameter:
723: .  y - output vector

725:    Note:
726:     This routine is used internally so that the same Krylov code can be used to solve A x = b and A' x = b, with a preconditioner
727:       defined by B'. This is why this has the funny form that it computes tr(B) * tr(A)

729:     Level: developer

731: .seealso: `PC`, `PCApply()`, `PCApplyTranspose()`, `PCApplyBAorAB()`
732: @*/
733: PetscErrorCode PCApplyBAorABTranspose(PC pc, PCSide side, Vec x, Vec y, Vec work)
734: {
740:   if (pc->erroriffailure) VecValidValues_Internal(x, 3, PETSC_TRUE);
741:   if (pc->ops->applyBAtranspose) {
742:     PetscUseTypeMethod(pc, applyBAtranspose, side, x, y, work);
743:     if (pc->erroriffailure) VecValidValues_Internal(y, 4, PETSC_FALSE);
744:     return 0;
745:   }

748:   PCSetUp(pc);
749:   if (side == PC_RIGHT) {
750:     PCApplyTranspose(pc, x, work);
751:     MatMultTranspose(pc->mat, work, y);
752:   } else if (side == PC_LEFT) {
753:     MatMultTranspose(pc->mat, x, work);
754:     PCApplyTranspose(pc, work, y);
755:   }
756:   /* add support for PC_SYMMETRIC */
757:   if (pc->erroriffailure) VecValidValues_Internal(y, 4, PETSC_FALSE);
758:   return 0;
759: }

761: /*@
762:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a
763:    built-in fast application of Richardson's method.

765:    Not Collective

767:    Input Parameter:
768: .  pc - the preconditioner

770:    Output Parameter:
771: .  exists - `PETSC_TRUE` or `PETSC_FALSE`

773:    Level: developer

775: .seealso: `PC`, `PCRICHARDSON`, `PCApplyRichardson()`
776: @*/
777: PetscErrorCode PCApplyRichardsonExists(PC pc, PetscBool *exists)
778: {
781:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
782:   else *exists = PETSC_FALSE;
783:   return 0;
784: }

786: /*@
787:    PCApplyRichardson - Applies several steps of Richardson iteration with
788:    the particular preconditioner. This routine is usually used by the
789:    Krylov solvers and not the application code directly.

791:    Collective on pc

793:    Input Parameters:
794: +  pc  - the preconditioner context
795: .  b   - the right hand side
796: .  w   - one work vector
797: .  rtol - relative decrease in residual norm convergence criteria
798: .  abstol - absolute residual norm convergence criteria
799: .  dtol - divergence residual norm increase criteria
800: .  its - the number of iterations to apply.
801: -  guesszero - if the input x contains nonzero initial guess

803:    Output Parameters:
804: +  outits - number of iterations actually used (for SOR this always equals its)
805: .  reason - the reason the apply terminated
806: -  y - the solution (also contains initial guess if guesszero is `PETSC_FALSE`

808:    Notes:
809:    Most preconditioners do not support this function. Use the command
810:    `PCApplyRichardsonExists()` to determine if one does.

812:    Except for the `PCMG` this routine ignores the convergence tolerances
813:    and always runs for the number of iterations

815:    Level: developer

817: .seealso: `PC`, `PCApplyRichardsonExists()`
818: @*/
819: PetscErrorCode PCApplyRichardson(PC pc, Vec b, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
820: {
826:   PCSetUp(pc);
827:   PetscUseTypeMethod(pc, applyrichardson, b, y, w, rtol, abstol, dtol, its, guesszero, outits, reason);
828:   return 0;
829: }

831: /*@
832:    PCSetFailedReason - Sets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail

834:    Logically Collective on pc

836:    Input Parameters:
837: +  pc - the preconditioner context
838: -  reason - the reason it failedx

840:    Level: advanced

842: .seealso: `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCFailedReason`
843: @*/
844: PetscErrorCode PCSetFailedReason(PC pc, PCFailedReason reason)
845: {
846:   pc->failedreason = reason;
847:   return 0;
848: }

850: /*@
851:    PCGetFailedReason - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail

853:    Logically Collective on pc

855:    Input Parameter:
856: .  pc - the preconditioner context

858:    Output Parameter:
859: .  reason - the reason it failed

861:    Level: advanced

863:    Note:
864:    This is the maximum over reason over all ranks in the PC communicator. It is only valid after
865:    a call `KSPCheckDot()` or  `KSPCheckNorm()` inside a `KSPSolve()`. It is not valid immediately after a `PCSetUp()`
866:    or `PCApply()`, then use `PCGetFailedReasonRank()`

868: .seealso: PC`, ``PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReasonRank()`, `PCSetFailedReason()`
869: @*/
870: PetscErrorCode PCGetFailedReason(PC pc, PCFailedReason *reason)
871: {
872:   if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
873:   else *reason = pc->failedreason;
874:   return 0;
875: }

877: /*@
878:    PCGetFailedReasonRank - Gets the reason a `PCSetUp()` failed or `PC_NOERROR` if it did not fail on this MPI rank

880:    Not Collective

882:    Input Parameter:
883: .  pc - the preconditioner context

885:    Output Parameter:
886: .  reason - the reason it failed

888:    Note:
889:      Different ranks may have different reasons or no reason, see `PCGetFailedReason()`

891:    Level: advanced

893: .seealso: `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCGetFailedReason()`, `PCSetFailedReason()`
894: @*/
895: PetscErrorCode PCGetFailedReasonRank(PC pc, PCFailedReason *reason)
896: {
897:   if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
898:   else *reason = pc->failedreason;
899:   return 0;
900: }

902: /*  Next line needed to deactivate KSP_Solve logging */
903: #include <petsc/private/kspimpl.h>

905: /*
906:       a setupcall of 0 indicates never setup,
907:                      1 indicates has been previously setup
908:                     -1 indicates a PCSetUp() was attempted and failed
909: */
910: /*@
911:    PCSetUp - Prepares for the use of a preconditioner.

913:    Collective on pc

915:    Input Parameter:
916: .  pc - the preconditioner context

918:    Level: developer

920: .seealso: `PC`, `PCCreate()`, `PCApply()`, `PCDestroy()`
921: @*/
922: PetscErrorCode PCSetUp(PC pc)
923: {
924:   const char      *def;
925:   PetscObjectState matstate, matnonzerostate;


930:   if (pc->setupcalled && pc->reusepreconditioner) {
931:     PetscInfo(pc, "Leaving PC with identical preconditioner since reuse preconditioner is set\n");
932:     return 0;
933:   }

935:   PetscObjectStateGet((PetscObject)pc->pmat, &matstate);
936:   MatGetNonzeroState(pc->pmat, &matnonzerostate);
937:   if (!pc->setupcalled) {
938:     PetscInfo(pc, "Setting up PC for first time\n");
939:     pc->flag = DIFFERENT_NONZERO_PATTERN;
940:   } else if (matstate == pc->matstate) {
941:     PetscInfo(pc, "Leaving PC with identical preconditioner since operator is unchanged\n");
942:     return 0;
943:   } else {
944:     if (matnonzerostate > pc->matnonzerostate) {
945:       PetscInfo(pc, "Setting up PC with different nonzero pattern\n");
946:       pc->flag = DIFFERENT_NONZERO_PATTERN;
947:     } else {
948:       PetscInfo(pc, "Setting up PC with same nonzero pattern\n");
949:       pc->flag = SAME_NONZERO_PATTERN;
950:     }
951:   }
952:   pc->matstate        = matstate;
953:   pc->matnonzerostate = matnonzerostate;

955:   if (!((PetscObject)pc)->type_name) {
956:     PCGetDefaultType_Private(pc, &def);
957:     PCSetType(pc, def);
958:   }

960:   MatSetErrorIfFailure(pc->pmat, pc->erroriffailure);
961:   MatSetErrorIfFailure(pc->mat, pc->erroriffailure);
962:   PetscLogEventBegin(PC_SetUp, pc, 0, 0, 0);
963:   if (pc->ops->setup) {
964:     /* do not log solves and applications of preconditioners while constructing preconditioners; perhaps they should be logged separately from the regular solves */
965:     KSPInitializePackage();
966:     PetscLogEventDeactivatePush(KSP_Solve);
967:     PetscLogEventDeactivatePush(PC_Apply);
968:     PetscUseTypeMethod(pc, setup);
969:     PetscLogEventDeactivatePop(KSP_Solve);
970:     PetscLogEventDeactivatePop(PC_Apply);
971:   }
972:   PetscLogEventEnd(PC_SetUp, pc, 0, 0, 0);
973:   if (!pc->setupcalled) pc->setupcalled = 1;
974:   return 0;
975: }

977: /*@
978:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
979:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
980:    methods.

982:    Collective on pc

984:    Input Parameter:
985: .  pc - the preconditioner context

987:    Level: developer

989:    Note:
990:    For nested preconditioners such as `PCBJACOBI` `PCSetUp()` is not called on each sub-`KSP` when `PCSetUp()` is
991:    called on the outer `PC`, this routine ensures it is called.

993: .seealso: `PC`, `PCSetUp()`, `PCCreate()`, `PCApply()`, `PCDestroy()`, `PCSetUp()`
994: @*/
995: PetscErrorCode PCSetUpOnBlocks(PC pc)
996: {
998:   if (!pc->ops->setuponblocks) return 0;
999:   PetscLogEventBegin(PC_SetUpOnBlocks, pc, 0, 0, 0);
1000:   PetscUseTypeMethod(pc, setuponblocks);
1001:   PetscLogEventEnd(PC_SetUpOnBlocks, pc, 0, 0, 0);
1002:   return 0;
1003: }

1005: /*@C
1006:    PCSetModifySubMatrices - Sets a user-defined routine for modifying the
1007:    submatrices that arise within certain subdomain-based preconditioners.
1008:    The basic submatrices are extracted from the preconditioner matrix as
1009:    usual; the user can then alter these (for example, to set different boundary
1010:    conditions for each submatrix) before they are used for the local solves.

1012:    Logically Collective on pc

1014:    Input Parameters:
1015: +  pc - the preconditioner context
1016: .  func - routine for modifying the submatrices
1017: -  ctx - optional user-defined context (may be null)

1019:    Calling sequence of func:
1020: $     func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx);

1022: +  row - an array of index sets that contain the global row numbers
1023:          that comprise each local submatrix
1024: .  col - an array of index sets that contain the global column numbers
1025:          that comprise each local submatrix
1026: .  submat - array of local submatrices
1027: -  ctx - optional user-defined context for private data for the
1028:          user-defined func routine (may be null)

1030:    Notes:
1031:    `PCSetModifySubMatrices()` MUST be called before `KSPSetUp()` and
1032:    `KSPSolve()`.

1034:    A routine set by `PCSetModifySubMatrices()` is currently called within
1035:    the block Jacobi (`PCBJACOBI`) and additive Schwarz (`PCASM`)
1036:    preconditioners.  All other preconditioners ignore this routine.

1038:    Level: advanced

1040: .seealso: `PC`, `PCBJACOBI`, `PCASM`, `PCModifySubMatrices()`
1041: @*/
1042: PetscErrorCode PCSetModifySubMatrices(PC pc, PetscErrorCode (*func)(PC, PetscInt, const IS[], const IS[], Mat[], void *), void *ctx)
1043: {
1045:   pc->modifysubmatrices  = func;
1046:   pc->modifysubmatricesP = ctx;
1047:   return 0;
1048: }

1050: /*@C
1051:    PCModifySubMatrices - Calls an optional user-defined routine within
1052:    certain preconditioners if one has been set with `PCSetModifySubMatrices()`.

1054:    Collective on pc

1056:    Input Parameters:
1057: +  pc - the preconditioner context
1058: .  nsub - the number of local submatrices
1059: .  row - an array of index sets that contain the global row numbers
1060:          that comprise each local submatrix
1061: .  col - an array of index sets that contain the global column numbers
1062:          that comprise each local submatrix
1063: .  submat - array of local submatrices
1064: -  ctx - optional user-defined context for private data for the
1065:          user-defined routine (may be null)

1067:    Output Parameter:
1068: .  submat - array of local submatrices (the entries of which may
1069:             have been modified)

1071:    Notes:
1072:    The user should NOT generally call this routine, as it will
1073:    automatically be called within certain preconditioners (currently
1074:    block Jacobi, additive Schwarz) if set.

1076:    The basic submatrices are extracted from the preconditioner matrix
1077:    as usual; the user can then alter these (for example, to set different
1078:    boundary conditions for each submatrix) before they are used for the
1079:    local solves.

1081:    Level: developer

1083: .seealso: `PC`, `PCSetModifySubMatrices()`
1084: @*/
1085: PetscErrorCode PCModifySubMatrices(PC pc, PetscInt nsub, const IS row[], const IS col[], Mat submat[], void *ctx)
1086: {
1088:   if (!pc->modifysubmatrices) return 0;
1089:   PetscLogEventBegin(PC_ModifySubMatrices, pc, 0, 0, 0);
1090:   (*pc->modifysubmatrices)(pc, nsub, row, col, submat, ctx);
1091:   PetscLogEventEnd(PC_ModifySubMatrices, pc, 0, 0, 0);
1092:   return 0;
1093: }

1095: /*@
1096:    PCSetOperators - Sets the matrix associated with the linear system and
1097:    a (possibly) different one associated with the preconditioner.

1099:    Logically Collective on pc

1101:    Input Parameters:
1102: +  pc - the preconditioner context
1103: .  Amat - the matrix that defines the linear system
1104: -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.

1106:    Notes:
1107:     Passing a NULL for Amat or Pmat removes the matrix that is currently used.

1109:     If you wish to replace either Amat or Pmat but leave the other one untouched then
1110:     first call `KSPGetOperators()` to get the one you wish to keep, call `PetscObjectReference()`
1111:     on it and then pass it back in in your call to `KSPSetOperators()`.

1113:    More Notes about Repeated Solution of Linear Systems:
1114:    PETSc does NOT reset the matrix entries of either Amat or Pmat
1115:    to zero after a linear solve; the user is completely responsible for
1116:    matrix assembly.  See the routine `MatZeroEntries()` if desiring to
1117:    zero all elements of a matrix.

1119:    Level: intermediate

1121: .seealso: `PC`, `PCGetOperators()`, `MatZeroEntries()`
1122:  @*/
1123: PetscErrorCode PCSetOperators(PC pc, Mat Amat, Mat Pmat)
1124: {
1125:   PetscInt m1, n1, m2, n2;

1132:   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
1133:     MatGetLocalSize(Amat, &m1, &n1);
1134:     MatGetLocalSize(pc->mat, &m2, &n2);
1136:     MatGetLocalSize(Pmat, &m1, &n1);
1137:     MatGetLocalSize(pc->pmat, &m2, &n2);
1139:   }

1141:   if (Pmat != pc->pmat) {
1142:     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
1143:     pc->matnonzerostate = -1;
1144:     pc->matstate        = -1;
1145:   }

1147:   /* reference first in case the matrices are the same */
1148:   if (Amat) PetscObjectReference((PetscObject)Amat);
1149:   MatDestroy(&pc->mat);
1150:   if (Pmat) PetscObjectReference((PetscObject)Pmat);
1151:   MatDestroy(&pc->pmat);
1152:   pc->mat  = Amat;
1153:   pc->pmat = Pmat;
1154:   return 0;
1155: }

1157: /*@
1158:    PCSetReusePreconditioner - reuse the current preconditioner even if the operator in the preconditioner has changed.

1160:    Logically Collective on pc

1162:    Input Parameters:
1163: +  pc - the preconditioner context
1164: -  flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner

1166:     Level: intermediate

1168:    Note:
1169:    Normally if a matrix inside a `PC` changes the `PC` automatically updates itself using information from the changed matrix. This option
1170:    prevents this.

1172: .seealso: `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCGetReusePreconditioner()`, `KSPSetReusePreconditioner()`
1173:  @*/
1174: PetscErrorCode PCSetReusePreconditioner(PC pc, PetscBool flag)
1175: {
1178:   pc->reusepreconditioner = flag;
1179:   return 0;
1180: }

1182: /*@
1183:    PCGetReusePreconditioner - Determines if the `PC` reuses the current preconditioner even if the operator in the preconditioner has changed.

1185:    Not Collective

1187:    Input Parameter:
1188: .  pc - the preconditioner context

1190:    Output Parameter:
1191: .  flag - `PETSC_TRUE` do not compute a new preconditioner, `PETSC_FALSE` do compute a new preconditioner

1193:    Level: intermediate

1195: .seealso: `PC`, `PCGetOperators()`, `MatZeroEntries()`, `PCSetReusePreconditioner()`
1196:  @*/
1197: PetscErrorCode PCGetReusePreconditioner(PC pc, PetscBool *flag)
1198: {
1201:   *flag = pc->reusepreconditioner;
1202:   return 0;
1203: }

1205: /*@
1206:    PCGetOperators - Gets the matrix associated with the linear system and
1207:    possibly a different one associated with the preconditioner.

1209:    Not collective, though parallel mats are returned if pc is parallel

1211:    Input Parameter:
1212: .  pc - the preconditioner context

1214:    Output Parameters:
1215: +  Amat - the matrix defining the linear system
1216: -  Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.

1218:    Level: intermediate

1220:    Note:
1221:     Does not increase the reference count of the matrices, so you should not destroy them

1223:    Alternative usage: If the operators have NOT been set with `KSPSetOperators()`/`PCSetOperators()` then the operators
1224:       are created in `PC` and returned to the user. In this case, if both operators
1225:       mat and pmat are requested, two DIFFERENT operators will be returned. If
1226:       only one is requested both operators in the PC will be the same (i.e. as
1227:       if one had called `KSPSetOperators()`/`PCSetOperators()` with the same argument for both Mats).
1228:       The user must set the sizes of the returned matrices and their type etc just
1229:       as if the user created them with `MatCreate()`. For example,

1231: .vb
1232:          KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
1233:            set size, type, etc of Amat

1235:          MatCreate(comm,&mat);
1236:          KSP/PCSetOperators(ksp/pc,Amat,Amat);
1237:          PetscObjectDereference((PetscObject)mat);
1238:            set size, type, etc of Amat
1239: .ve

1241:      and

1243: .vb
1244:          KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to
1245:            set size, type, etc of Amat and Pmat

1247:          MatCreate(comm,&Amat);
1248:          MatCreate(comm,&Pmat);
1249:          KSP/PCSetOperators(ksp/pc,Amat,Pmat);
1250:          PetscObjectDereference((PetscObject)Amat);
1251:          PetscObjectDereference((PetscObject)Pmat);
1252:            set size, type, etc of Amat and Pmat
1253: .ve

1255:     The rationale for this support is so that when creating a `TS`, `SNES`, or `KSP` the hierarchy
1256:     of underlying objects (i.e. `SNES`, `KSP`, `PC`, `Mat`) and their livespans can be completely
1257:     managed by the top most level object (i.e. the `TS`, `SNES`, or `KSP`). Another way to look
1258:     at this is when you create a `SNES` you do not NEED to create a `KSP` and attach it to
1259:     the `SNES` object (the `SNES` object manages it for you). Similarly when you create a KSP
1260:     you do not need to attach a `PC` to it (the `KSP` object manages the `PC` object for you).
1261:     Thus, why should YOU have to create the `Mat` and attach it to the `SNES`/`KSP`/`PC`, when
1262:     it can be created for you?

1264: .seealso: `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperatorsSet()`
1265: @*/
1266: PetscErrorCode PCGetOperators(PC pc, Mat *Amat, Mat *Pmat)
1267: {
1269:   if (Amat) {
1270:     if (!pc->mat) {
1271:       if (pc->pmat && !Pmat) { /* Apmat has been set, but user did not request it, so use for Amat */
1272:         pc->mat = pc->pmat;
1273:         PetscObjectReference((PetscObject)pc->mat);
1274:       } else { /* both Amat and Pmat are empty */
1275:         MatCreate(PetscObjectComm((PetscObject)pc), &pc->mat);
1276:         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
1277:           pc->pmat = pc->mat;
1278:           PetscObjectReference((PetscObject)pc->pmat);
1279:         }
1280:       }
1281:     }
1282:     *Amat = pc->mat;
1283:   }
1284:   if (Pmat) {
1285:     if (!pc->pmat) {
1286:       if (pc->mat && !Amat) { /* Amat has been set but was not requested, so use for pmat */
1287:         pc->pmat = pc->mat;
1288:         PetscObjectReference((PetscObject)pc->pmat);
1289:       } else {
1290:         MatCreate(PetscObjectComm((PetscObject)pc), &pc->pmat);
1291:         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
1292:           pc->mat = pc->pmat;
1293:           PetscObjectReference((PetscObject)pc->mat);
1294:         }
1295:       }
1296:     }
1297:     *Pmat = pc->pmat;
1298:   }
1299:   return 0;
1300: }

1302: /*@C
1303:    PCGetOperatorsSet - Determines if the matrix associated with the linear system and
1304:    possibly a different one associated with the preconditioner have been set in the `PC`.

1306:    Not collective, though the results on all processes should be the same

1308:    Input Parameter:
1309: .  pc - the preconditioner context

1311:    Output Parameters:
1312: +  mat - the matrix associated with the linear system was set
1313: -  pmat - matrix associated with the preconditioner was set, usually the same

1315:    Level: intermediate

1317: .seealso: `PC`, `PCSetOperators()`, `KSPGetOperators()`, `KSPSetOperators()`, `PCGetOperators()`
1318: @*/
1319: PetscErrorCode PCGetOperatorsSet(PC pc, PetscBool *mat, PetscBool *pmat)
1320: {
1322:   if (mat) *mat = (pc->mat) ? PETSC_TRUE : PETSC_FALSE;
1323:   if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
1324:   return 0;
1325: }

1327: /*@
1328:    PCFactorGetMatrix - Gets the factored matrix from the
1329:    preconditioner context.  This routine is valid only for the `PCLU`,
1330:    `PCILU`, `PCCHOLESKY`, and `PCICC` methods.

1332:    Not Collective on pc though mat is parallel if pc is parallel

1334:    Input Parameter:
1335: .  pc - the preconditioner context

1337:    Output parameters:
1338: .  mat - the factored matrix

1340:    Level: advanced

1342:    Note:
1343:     Does not increase the reference count for the matrix so DO NOT destroy it

1345: .seealso: `PC`, `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
1346: @*/
1347: PetscErrorCode PCFactorGetMatrix(PC pc, Mat *mat)
1348: {
1351:   PetscUseTypeMethod(pc, getfactoredmatrix, mat);
1352:   return 0;
1353: }

1355: /*@C
1356:    PCSetOptionsPrefix - Sets the prefix used for searching for all
1357:    `PC` options in the database.

1359:    Logically Collective on pc

1361:    Input Parameters:
1362: +  pc - the preconditioner context
1363: -  prefix - the prefix string to prepend to all `PC` option requests

1365:    Note:
1366:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1367:    The first character of all runtime options is AUTOMATICALLY the
1368:    hyphen.

1370:    Level: advanced

1372: .seealso: `PC`, `PCSetFromOptions`, `PCAppendOptionsPrefix()`, `PCGetOptionsPrefix()`
1373: @*/
1374: PetscErrorCode PCSetOptionsPrefix(PC pc, const char prefix[])
1375: {
1377:   PetscObjectSetOptionsPrefix((PetscObject)pc, prefix);
1378:   return 0;
1379: }

1381: /*@C
1382:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1383:    `PC` options in the database.

1385:    Logically Collective on pc

1387:    Input Parameters:
1388: +  pc - the preconditioner context
1389: -  prefix - the prefix string to prepend to all `PC` option requests

1391:    Note:
1392:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1393:    The first character of all runtime options is AUTOMATICALLY the
1394:    hyphen.

1396:    Level: advanced

1398: .seealso: `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCGetOptionsPrefix()`
1399: @*/
1400: PetscErrorCode PCAppendOptionsPrefix(PC pc, const char prefix[])
1401: {
1403:   PetscObjectAppendOptionsPrefix((PetscObject)pc, prefix);
1404:   return 0;
1405: }

1407: /*@C
1408:    PCGetOptionsPrefix - Gets the prefix used for searching for all
1409:    PC options in the database.

1411:    Not Collective

1413:    Input Parameter:
1414: .  pc - the preconditioner context

1416:    Output Parameter:
1417: .  prefix - pointer to the prefix string used, is returned

1419:    Fortran Note:
1420:    The user should pass in a string 'prefix' of
1421:    sufficient length to hold the prefix.

1423:    Level: advanced

1425: .seealso: `PC`, `PCSetFromOptions`, `PCSetOptionsPrefix()`, `PCAppendOptionsPrefix()`
1426: @*/
1427: PetscErrorCode PCGetOptionsPrefix(PC pc, const char *prefix[])
1428: {
1431:   PetscObjectGetOptionsPrefix((PetscObject)pc, prefix);
1432:   return 0;
1433: }

1435: /*
1436:    Indicates the right hand side will be changed by KSPSolve(), this occurs for a few
1437:   preconditioners including BDDC and Eisentat that transform the equations before applying
1438:   the Krylov methods
1439: */
1440: PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC pc, PetscBool *change)
1441: {
1444:   *change = PETSC_FALSE;
1445:   PetscTryMethod(pc, "PCPreSolveChangeRHS_C", (PC, PetscBool *), (pc, change));
1446:   return 0;
1447: }

1449: /*@
1450:    PCPreSolve - Optional pre-solve phase, intended for any
1451:    preconditioner-specific actions that must be performed before
1452:    the iterative solve itself.

1454:    Collective on pc

1456:    Input Parameters:
1457: +  pc - the preconditioner context
1458: -  ksp - the Krylov subspace context

1460:    Level: developer

1462:    Sample of Usage:
1463: .vb
1464:     PCPreSolve(pc,ksp);
1465:     KSPSolve(ksp,b,x);
1466:     PCPostSolve(pc,ksp);
1467: .ve

1469:    Notes:
1470:    The pre-solve phase is distinct from the `PCSetUp()` phase.

1472:    `KSPSolve()` calls this directly, so is rarely called by the user.

1474: .seealso: `PC`, `PCPostSolve()`
1475: @*/
1476: PetscErrorCode PCPreSolve(PC pc, KSP ksp)
1477: {
1478:   Vec x, rhs;

1482:   pc->presolvedone++;
1484:   KSPGetSolution(ksp, &x);
1485:   KSPGetRhs(ksp, &rhs);

1487:   if (pc->ops->presolve) PetscUseTypeMethod(pc, presolve, ksp, rhs, x);
1488:   else if (pc->presolve) (pc->presolve)(pc, ksp);
1489:   return 0;
1490: }

1492: /*@C
1493:    PCSetPreSolve - Sets function used by `PCPreSolve()` which is intended for any
1494:    preconditioner-specific actions that must be performed before
1495:    the iterative solve itself.

1497:    Logically Collective on pc

1499:    Input Parameters:
1500: +   pc - the preconditioner object
1501: -   presolve - the function to call before the solve

1503:    Calling sequence of presolve:
1504: $  func(PC pc,KSP ksp)

1506: +  pc - the PC context
1507: -  ksp - the KSP context

1509:    Level: developer

1511: .seealso: `PC`, `PCSetUp()`, `PCPreSolve()`
1512: @*/
1513: PetscErrorCode PCSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC, KSP))
1514: {
1516:   pc->presolve = presolve;
1517:   return 0;
1518: }

1520: /*@
1521:    PCPostSolve - Optional post-solve phase, intended for any
1522:    preconditioner-specific actions that must be performed after
1523:    the iterative solve itself.

1525:    Collective on pc

1527:    Input Parameters:
1528: +  pc - the preconditioner context
1529: -  ksp - the Krylov subspace context

1531:    Sample of Usage:
1532: .vb
1533:     PCPreSolve(pc,ksp);
1534:     KSPSolve(ksp,b,x);
1535:     PCPostSolve(pc,ksp);
1536: .ve

1538:    Note:
1539:    `KSPSolve()` calls this routine directly, so it is rarely called by the user.

1541:    Level: developer

1543: .seealso: `PC`, `PCSetPostSolve()`, `PCSetPresolve()`, `PCPreSolve()`, `KSPSolve()`
1544: @*/
1545: PetscErrorCode PCPostSolve(PC pc, KSP ksp)
1546: {
1547:   Vec x, rhs;

1551:   pc->presolvedone--;
1552:   KSPGetSolution(ksp, &x);
1553:   KSPGetRhs(ksp, &rhs);
1554:   PetscTryTypeMethod(pc, postsolve, ksp, rhs, x);
1555:   return 0;
1556: }

1558: /*@C
1559:   PCLoad - Loads a `PC` that has been stored in binary  with `PCView()`.

1561:   Collective on newdm

1563:   Input Parameters:
1564: + newdm - the newly loaded `PC`, this needs to have been created with `PCCreate()` or
1565:            some related function before a call to `PCLoad()`.
1566: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`

1568:    Level: intermediate

1570:   Note:
1571:    The type is determined by the data in the file, any type set into the PC before this call is ignored.

1573: .seealso: `PC`, `PetscViewerBinaryOpen()`, `PCView()`, `MatLoad()`, `VecLoad()`
1574: @*/
1575: PetscErrorCode PCLoad(PC newdm, PetscViewer viewer)
1576: {
1577:   PetscBool isbinary;
1578:   PetscInt  classid;
1579:   char      type[256];

1583:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary);

1586:   PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT);
1588:   PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR);
1589:   PCSetType(newdm, type);
1590:   PetscTryTypeMethod(newdm, load, viewer);
1591:   return 0;
1592: }

1594: #include <petscdraw.h>
1595: #if defined(PETSC_HAVE_SAWS)
1596: #include <petscviewersaws.h>
1597: #endif

1599: /*@C
1600:    PCViewFromOptions - View from the `PC` based on options in the database

1602:    Collective on pc

1604:    Input Parameters:
1605: +  A - the PC context
1606: .  obj - Optional object that provides the options prefix
1607: -  name - command line option

1609:    Level: intermediate

1611: .seealso: `PC`, `PCView`, `PetscObjectViewFromOptions()`, `PCCreate()`
1612: @*/
1613: PetscErrorCode PCViewFromOptions(PC A, PetscObject obj, const char name[])
1614: {
1616:   PetscObjectViewFromOptions((PetscObject)A, obj, name);
1617:   return 0;
1618: }

1620: /*@C
1621:    PCView - Prints information about the `PC`

1623:    Collective on pc

1625:    Input Parameters:
1626: +  PC - the `PC` context
1627: -  viewer - optional visualization context

1629:    Notes:
1630:    The available visualization contexts include
1631: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
1632: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
1633:          output where only the first processor opens
1634:          the file.  All other processors send their
1635:          data to the first processor to print.

1637:    The user can open an alternative visualization contexts with
1638:    `PetscViewerASCIIOpen()` (output to a specified file).

1640:    Level: developer

1642: .seealso: `PC`, `PetscViewer`, `KSPView()`, `PetscViewerASCIIOpen()`
1643: @*/
1644: PetscErrorCode PCView(PC pc, PetscViewer viewer)
1645: {
1646:   PCType    cstr;
1647:   PetscBool iascii, isstring, isbinary, isdraw;
1648: #if defined(PETSC_HAVE_SAWS)
1649:   PetscBool issaws;
1650: #endif

1653:   if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer);

1657:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
1658:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
1659:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary);
1660:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw);
1661: #if defined(PETSC_HAVE_SAWS)
1662:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws);
1663: #endif

1665:   if (iascii) {
1666:     PetscObjectPrintClassNamePrefixType((PetscObject)pc, viewer);
1667:     if (!pc->setupcalled) PetscViewerASCIIPrintf(viewer, "  PC has not been set up so information may be incomplete\n");
1668:     PetscViewerASCIIPushTab(viewer);
1669:     PetscTryTypeMethod(pc, view, viewer);
1670:     PetscViewerASCIIPopTab(viewer);
1671:     if (pc->mat) {
1672:       PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO);
1673:       if (pc->pmat == pc->mat) {
1674:         PetscViewerASCIIPrintf(viewer, "  linear system matrix = precond matrix:\n");
1675:         PetscViewerASCIIPushTab(viewer);
1676:         MatView(pc->mat, viewer);
1677:         PetscViewerASCIIPopTab(viewer);
1678:       } else {
1679:         if (pc->pmat) {
1680:           PetscViewerASCIIPrintf(viewer, "  linear system matrix followed by preconditioner matrix:\n");
1681:         } else {
1682:           PetscViewerASCIIPrintf(viewer, "  linear system matrix:\n");
1683:         }
1684:         PetscViewerASCIIPushTab(viewer);
1685:         MatView(pc->mat, viewer);
1686:         if (pc->pmat) MatView(pc->pmat, viewer);
1687:         PetscViewerASCIIPopTab(viewer);
1688:       }
1689:       PetscViewerPopFormat(viewer);
1690:     }
1691:   } else if (isstring) {
1692:     PCGetType(pc, &cstr);
1693:     PetscViewerStringSPrintf(viewer, " PCType: %-7.7s", cstr);
1694:     PetscTryTypeMethod(pc, view, viewer);
1695:     if (pc->mat) MatView(pc->mat, viewer);
1696:     if (pc->pmat && pc->pmat != pc->mat) MatView(pc->pmat, viewer);
1697:   } else if (isbinary) {
1698:     PetscInt    classid = PC_FILE_CLASSID;
1699:     MPI_Comm    comm;
1700:     PetscMPIInt rank;
1701:     char        type[256];

1703:     PetscObjectGetComm((PetscObject)pc, &comm);
1704:     MPI_Comm_rank(comm, &rank);
1705:     if (rank == 0) {
1706:       PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT);
1707:       PetscStrncpy(type, ((PetscObject)pc)->type_name, 256);
1708:       PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR);
1709:     }
1710:     PetscTryTypeMethod(pc, view, viewer);
1711:   } else if (isdraw) {
1712:     PetscDraw draw;
1713:     char      str[25];
1714:     PetscReal x, y, bottom, h;
1715:     PetscInt  n;

1717:     PetscViewerDrawGetDraw(viewer, 0, &draw);
1718:     PetscDrawGetCurrentPoint(draw, &x, &y);
1719:     if (pc->mat) {
1720:       MatGetSize(pc->mat, &n, NULL);
1721:       PetscSNPrintf(str, 25, "PC: %s (%" PetscInt_FMT ")", ((PetscObject)pc)->type_name, n);
1722:     } else {
1723:       PetscSNPrintf(str, 25, "PC: %s", ((PetscObject)pc)->type_name);
1724:     }
1725:     PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_RED, PETSC_DRAW_BLACK, str, NULL, &h);
1726:     bottom = y - h;
1727:     PetscDrawPushCurrentPoint(draw, x, bottom);
1728:     PetscTryTypeMethod(pc, view, viewer);
1729:     PetscDrawPopCurrentPoint(draw);
1730: #if defined(PETSC_HAVE_SAWS)
1731:   } else if (issaws) {
1732:     PetscMPIInt rank;

1734:     PetscObjectName((PetscObject)pc);
1735:     MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1736:     if (!((PetscObject)pc)->amsmem && rank == 0) PetscObjectViewSAWs((PetscObject)pc, viewer);
1737:     if (pc->mat) MatView(pc->mat, viewer);
1738:     if (pc->pmat && pc->pmat != pc->mat) MatView(pc->pmat, viewer);
1739: #endif
1740:   }
1741:   return 0;
1742: }

1744: /*@C
1745:   PCRegister -  Adds a method to the preconditioner package.

1747:    Not collective

1749:    Input Parameters:
1750: +  name_solver - name of a new user-defined solver
1751: -  routine_create - routine to create method context

1753:    Note:
1754:    `PCRegister()` may be called multiple times to add several user-defined preconditioners.

1756:    Sample usage:
1757: .vb
1758:    PCRegister("my_solver", MySolverCreate);
1759: .ve

1761:    Then, your solver can be chosen with the procedural interface via
1762: $     PCSetType(pc,"my_solver")
1763:    or at runtime via the option
1764: $     -pc_type my_solver

1766:    Level: advanced

1768: .seealso: `PC`, `PCType`, `PCRegisterAll()`
1769: @*/
1770: PetscErrorCode PCRegister(const char sname[], PetscErrorCode (*function)(PC))
1771: {
1772:   PCInitializePackage();
1773:   PetscFunctionListAdd(&PCList, sname, function);
1774:   return 0;
1775: }

1777: static PetscErrorCode MatMult_PC(Mat A, Vec X, Vec Y)
1778: {
1779:   PC pc;

1781:   MatShellGetContext(A, &pc);
1782:   PCApply(pc, X, Y);
1783:   return 0;
1784: }

1786: /*@
1787:     PCComputeOperator - Computes the explicit preconditioned operator.

1789:     Collective on pc

1791:     Input Parameters:
1792: +   pc - the preconditioner object
1793: -   mattype - the matrix type to be used for the operator

1795:     Output Parameter:
1796: .   mat - the explicit preconditioned operator

1798:     Note:
1799:     This computation is done by applying the operators to columns of the identity matrix.
1800:     This routine is costly in general, and is recommended for use only with relatively small systems.
1801:     Currently, this routine uses a dense matrix format when mattype == NULL

1803:     Level: advanced

1805: .seealso: `PC`, `KSPComputeOperator()`, `MatType`

1807: @*/
1808: PetscErrorCode PCComputeOperator(PC pc, MatType mattype, Mat *mat)
1809: {
1810:   PetscInt N, M, m, n;
1811:   Mat      A, Apc;

1815:   PCGetOperators(pc, &A, NULL);
1816:   MatGetLocalSize(A, &m, &n);
1817:   MatGetSize(A, &M, &N);
1818:   MatCreateShell(PetscObjectComm((PetscObject)pc), m, n, M, N, pc, &Apc);
1819:   MatShellSetOperation(Apc, MATOP_MULT, (void (*)(void))MatMult_PC);
1820:   MatComputeOperator(Apc, mattype, mat);
1821:   MatDestroy(&Apc);
1822:   return 0;
1823: }

1825: /*@
1826:    PCSetCoordinates - sets the coordinates of all the nodes on the local process

1828:    Collective on pc

1830:    Input Parameters:
1831: +  pc - the solver context
1832: .  dim - the dimension of the coordinates 1, 2, or 3
1833: .  nloc - the blocked size of the coordinates array
1834: -  coords - the coordinates array

1836:    Level: intermediate

1838:    Note:
1839:    coords is an array of the dim coordinates for the nodes on
1840:    the local processor, of size dim*nloc.
1841:    If there are 108 equation on a processor
1842:    for a displacement finite element discretization of elasticity (so
1843:    that there are nloc = 36 = 108/3 nodes) then the array must have 108
1844:    double precision values (ie, 3 * 36).  These x y z coordinates
1845:    should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
1846:    ... , N-1.z ].

1848: .seealso: `PC`, `MatSetNearNullSpace()`
1849: @*/
1850: PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[])
1851: {
1854:   PetscTryMethod(pc, "PCSetCoordinates_C", (PC, PetscInt, PetscInt, PetscReal *), (pc, dim, nloc, coords));
1855:   return 0;
1856: }

1858: /*@
1859:    PCGetInterpolations - Gets interpolation matrices for all levels (except level 0)

1861:    Logically Collective on pc

1863:    Input Parameter:
1864: .  pc - the precondition context

1866:    Output Parameters:
1867: +  num_levels - the number of levels
1868: -  interpolations - the interpolation matrices (size of num_levels-1)

1870:    Level: advanced

1872:    Developer Note:
1873:    Why is this here instead of in `PCMG` etc?

1875: .seealso: `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetInterpolation()`, `PCGetCoarseOperators()`
1876: @*/
1877: PetscErrorCode PCGetInterpolations(PC pc, PetscInt *num_levels, Mat *interpolations[])
1878: {
1882:   PetscUseMethod(pc, "PCGetInterpolations_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, interpolations));
1883:   return 0;
1884: }

1886: /*@
1887:    PCGetCoarseOperators - Gets coarse operator matrices for all levels (except the finest level)

1889:    Logically Collective on pc

1891:    Input Parameter:
1892: .  pc - the precondition context

1894:    Output Parameters:
1895: +  num_levels - the number of levels
1896: -  coarseOperators - the coarse operator matrices (size of num_levels-1)

1898:    Level: advanced

1900:    Developer Note:
1901:    Why is this here instead of in `PCMG` etc?

1903: .seealso: `PC`, `PCMG`, `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`, `PCMGGetInterpolation()`, `PCGetInterpolations()`
1904: @*/
1905: PetscErrorCode PCGetCoarseOperators(PC pc, PetscInt *num_levels, Mat *coarseOperators[])
1906: {
1910:   PetscUseMethod(pc, "PCGetCoarseOperators_C", (PC, PetscInt *, Mat *[]), (pc, num_levels, coarseOperators));
1911:   return 0;
1912: }