Actual source code: precon.c

petsc-3.10.5 2019-03-28
Report Typos and Errors

  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_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: {
 17:   PetscMPIInt    size;
 18:   PetscBool      hasop,flg1,flg2,set,flg3;

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

 54: /*@
 55:    PCReset - Resets a PC context to the pcsetupcalled = 0 state and removes any allocated Vecs and Mats

 57:    Collective on PC

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

 62:    Level: developer

 64:    Notes:
 65:     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

 67: .keywords: PC, destroy

 69: .seealso: PCCreate(), PCSetUp()
 70: @*/
 71: PetscErrorCode  PCReset(PC pc)
 72: {

 77:   if (pc->ops->reset) {
 78:     (*pc->ops->reset)(pc);
 79:   }
 80:   VecDestroy(&pc->diagonalscaleright);
 81:   VecDestroy(&pc->diagonalscaleleft);
 82:   MatDestroy(&pc->pmat);
 83:   MatDestroy(&pc->mat);

 85:   pc->setupcalled = 0;
 86:   return(0);
 87: }

 89: /*@
 90:    PCDestroy - Destroys PC context that was created with PCCreate().

 92:    Collective on PC

 94:    Input Parameter:
 95: .  pc - the preconditioner context

 97:    Level: developer

 99: .keywords: PC, destroy

101: .seealso: PCCreate(), PCSetUp()
102: @*/
103: PetscErrorCode  PCDestroy(PC *pc)
104: {

108:   if (!*pc) return(0);
110:   if (--((PetscObject)(*pc))->refct > 0) {*pc = 0; return(0);}

112:   PCReset(*pc);

114:   /* if memory was published with SAWs then destroy it */
115:   PetscObjectSAWsViewOff((PetscObject)*pc);
116:   if ((*pc)->ops->destroy) {(*(*pc)->ops->destroy)((*pc));}
117:   DMDestroy(&(*pc)->dm);
118:   PetscHeaderDestroy(pc);
119:   return(0);
120: }

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

126:    Logically Collective on PC

128:    Input Parameter:
129: .  pc - the preconditioner context

131:    Output Parameter:
132: .  flag - PETSC_TRUE if it applies the scaling

134:    Level: developer

136:    Notes:
137:     If this returns PETSC_TRUE then the system solved via the Krylov method is
138: $           D M A D^{-1} y = D M b  for left preconditioning or
139: $           D A M D^{-1} z = D b for right preconditioning

141: .keywords: PC

143: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCSetDiagonalScale()
144: @*/
145: PetscErrorCode  PCGetDiagonalScale(PC pc,PetscBool  *flag)
146: {
150:   *flag = pc->diagonalscale;
151:   return(0);
152: }

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

158:    Logically Collective on PC

160:    Input Parameters:
161: +  pc - the preconditioner context
162: -  s - scaling vector

164:    Level: intermediate

166:    Notes:
167:     The system solved via the Krylov method is
168: $           D M A D^{-1} y = D M b  for left preconditioning or
169: $           D A M D^{-1} z = D b for right preconditioning

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

173: .keywords: PC

175: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCGetDiagonalScale()
176: @*/
177: PetscErrorCode  PCSetDiagonalScale(PC pc,Vec s)
178: {

184:   pc->diagonalscale     = PETSC_TRUE;

186:   PetscObjectReference((PetscObject)s);
187:   VecDestroy(&pc->diagonalscaleleft);

189:   pc->diagonalscaleleft = s;

191:   VecDuplicate(s,&pc->diagonalscaleright);
192:   VecCopy(s,pc->diagonalscaleright);
193:   VecReciprocal(pc->diagonalscaleright);
194:   return(0);
195: }

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

200:    Logically Collective on PC

202:    Input Parameters:
203: +  pc - the preconditioner context
204: .  in - input vector
205: +  out - scaled vector (maybe the same as in)

207:    Level: intermediate

209:    Notes:
210:     The system solved via the Krylov method is
211: $           D M A D^{-1} y = D M b  for left preconditioning or
212: $           D A M D^{-1} z = D b for right preconditioning

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

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

218: .keywords: PC

220: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
221: @*/
222: PetscErrorCode  PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
223: {

230:   if (pc->diagonalscale) {
231:     VecPointwiseMult(out,pc->diagonalscaleleft,in);
232:   } else if (in != out) {
233:     VecCopy(in,out);
234:   }
235:   return(0);
236: }

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

241:    Logically Collective on PC

243:    Input Parameters:
244: +  pc - the preconditioner context
245: .  in - input vector
246: +  out - scaled vector (maybe the same as in)

248:    Level: intermediate

250:    Notes:
251:     The system solved via the Krylov method is
252: $           D M A D^{-1} y = D M b  for left preconditioning or
253: $           D A M D^{-1} z = D b for right preconditioning

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

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

259: .keywords: PC

261: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
262: @*/
263: PetscErrorCode  PCDiagonalScaleRight(PC pc,Vec in,Vec out)
264: {

271:   if (pc->diagonalscale) {
272:     VecPointwiseMult(out,pc->diagonalscaleright,in);
273:   } else if (in != out) {
274:     VecCopy(in,out);
275:   }
276:   return(0);
277: }

279: /*@
280:    PCSetUseAmat - Sets a flag to indicate that when the preconditioner needs to apply (part of) the
281:    operator during the preconditioning process it applies the Amat provided to TSSetRHSJacobian(),
282:    TSSetIJacobian(), SNESSetJacobian(), KSPSetOperator() or PCSetOperator() not the Pmat.

284:    Logically Collective on PC

286:    Input Parameters:
287: +  pc - the preconditioner context
288: -  flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false)

290:    Options Database Key:
291: .  -pc_use_amat <true,false>

293:    Notes:
294:    For the common case in which the linear system matrix and the matrix used to construct the
295:    preconditioner are identical, this routine is does nothing.

297:    Level: intermediate

299: .seealso: PCGetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE
300: @*/
301: PetscErrorCode  PCSetUseAmat(PC pc,PetscBool flg)
302: {
305:   pc->useAmat = flg;
306:   return(0);
307: }

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

312:    Logically Collective on PC

314:    Input Parameters:
315: +  pc - iterative context obtained from PCCreate()
316: -  flg - PETSC_TRUE indicates you want the error generated

318:    Level: advanced

320:    Notes:
321:     Normally PETSc continues if a linear solver fails due to a failed setup of a preconditioner, you can call KSPGetConvergedReason() after a KSPSolve()
322:     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
323:     detected.

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

327: .keywords: PC, set, initial guess, nonzero

329: .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll()
330: @*/
331: PetscErrorCode  PCSetErrorIfFailure(PC pc,PetscBool flg)
332: {
336:   pc->erroriffailure = flg;
337:   return(0);
338: }

340: /*@
341:    PCGetUseAmat - Gets a flag to indicate that when the preconditioner needs to apply (part of) the
342:    operator during the preconditioning process it applies the Amat provided to TSSetRHSJacobian(),
343:    TSSetIJacobian(), SNESSetJacobian(), KSPSetOperator() or PCSetOperator() not the Pmat.

345:    Logically Collective on PC

347:    Input Parameter:
348: .  pc - the preconditioner context

350:    Output Parameter:
351: .  flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false)

353:    Notes:
354:    For the common case in which the linear system matrix and the matrix used to construct the
355:    preconditioner are identical, this routine is does nothing.

357:    Level: intermediate

359: .seealso: PCSetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE
360: @*/
361: PetscErrorCode  PCGetUseAmat(PC pc,PetscBool *flg)
362: {
365:   *flg = pc->useAmat;
366:   return(0);
367: }

369: /*@
370:    PCCreate - Creates a preconditioner context.

372:    Collective on MPI_Comm

374:    Input Parameter:
375: .  comm - MPI communicator

377:    Output Parameter:
378: .  pc - location to put the preconditioner context

380:    Notes:
381:    The default preconditioner for sparse matrices is PCILU or PCICC with 0 fill on one process and block Jacobi with PCILU or ICC
382:    in parallel. For dense matrices it is always PCNONE.

384:    Level: developer

386: .keywords: PC, create, context

388: .seealso: PCSetUp(), PCApply(), PCDestroy()
389: @*/
390: PetscErrorCode  PCCreate(MPI_Comm comm,PC *newpc)
391: {
392:   PC             pc;

397:   *newpc = 0;
398:   PCInitializePackage();

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

402:   pc->mat                  = 0;
403:   pc->pmat                 = 0;
404:   pc->setupcalled          = 0;
405:   pc->setfromoptionscalled = 0;
406:   pc->data                 = 0;
407:   pc->diagonalscale        = PETSC_FALSE;
408:   pc->diagonalscaleleft    = 0;
409:   pc->diagonalscaleright   = 0;

411:   pc->modifysubmatrices  = 0;
412:   pc->modifysubmatricesP = 0;

414:   *newpc = pc;
415:   return(0);

417: }

419: /* -------------------------------------------------------------------------------*/

421: /*@
422:    PCApply - Applies the preconditioner to a vector.

424:    Collective on PC and Vec

426:    Input Parameters:
427: +  pc - the preconditioner context
428: -  x - input vector

430:    Output Parameter:
431: .  y - output vector

433:    Level: developer

435: .keywords: PC, apply

437: .seealso: PCApplyTranspose(), PCApplyBAorAB()
438: @*/
439: PetscErrorCode  PCApply(PC pc,Vec x,Vec y)
440: {
442:   PetscInt       m,n,mv,nv;

448:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
449:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
450:   /* use pmat to check vector sizes since for KSPLQR the pmat may be of a different size than mat */
451:   MatGetLocalSize(pc->pmat,&m,&n);
452:   VecGetLocalSize(x,&nv);
453:   VecGetLocalSize(y,&mv);
454:   if (mv != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Preconditioner number of local rows %D does not equal resulting vector number of rows %D",m,mv);
455:   if (nv != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Preconditioner number of local columns %D does not equal resulting vector number of rows %D",n,nv);
456:   VecLocked(y,3);

458:   PCSetUp(pc);
459:   if (!pc->ops->apply) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply");
460:   VecLockPush(x);
461:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
462:   (*pc->ops->apply)(pc,x,y);
463:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
464:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
465:   VecLockPop(x);
466:   return(0);
467: }

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

472:    Collective on PC and Vec

474:    Input Parameters:
475: +  pc - the preconditioner context
476: -  x - input vector

478:    Output Parameter:
479: .  y - output vector

481:    Notes:
482:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

484:    Level: developer

486: .keywords: PC, apply, symmetric, left

488: .seealso: PCApply(), PCApplySymmetricRight()
489: @*/
490: PetscErrorCode  PCApplySymmetricLeft(PC pc,Vec x,Vec y)
491: {

498:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
499:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
500:   PCSetUp(pc);
501:   if (!pc->ops->applysymmetricleft) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply");
502:   VecLockPush(x);
503:   PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
504:   (*pc->ops->applysymmetricleft)(pc,x,y);
505:   PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
506:   VecLockPop(x);
507:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
508:   return(0);
509: }

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

514:    Collective on PC and Vec

516:    Input Parameters:
517: +  pc - the preconditioner context
518: -  x - input vector

520:    Output Parameter:
521: .  y - output vector

523:    Level: developer

525:    Notes:
526:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

528: .keywords: PC, apply, symmetric, right

530: .seealso: PCApply(), PCApplySymmetricLeft()
531: @*/
532: PetscErrorCode  PCApplySymmetricRight(PC pc,Vec x,Vec y)
533: {

540:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
541:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
542:   PCSetUp(pc);
543:   if (!pc->ops->applysymmetricright) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply");
544:   VecLockPush(x);
545:   PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
546:   (*pc->ops->applysymmetricright)(pc,x,y);
547:   PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
548:   VecLockPop(x);
549:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
550:   return(0);
551: }

553: /*@
554:    PCApplyTranspose - Applies the transpose of preconditioner to a vector.

556:    Collective on PC and Vec

558:    Input Parameters:
559: +  pc - the preconditioner context
560: -  x - input vector

562:    Output Parameter:
563: .  y - output vector

565:    Notes:
566:     For complex numbers this applies the non-Hermitian transpose.

568:    Developer Notes:
569:     We need to implement a PCApplyHermitianTranspose()

571:    Level: developer

573: .keywords: PC, apply, transpose

575: .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCApplyTransposeExists()
576: @*/
577: PetscErrorCode  PCApplyTranspose(PC pc,Vec x,Vec y)
578: {

585:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
586:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
587:   PCSetUp(pc);
588:   if (!pc->ops->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply transpose");
589:   VecLockPush(x);
590:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
591:   (*pc->ops->applytranspose)(pc,x,y);
592:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
593:   VecLockPop(x);
594:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
595:   return(0);
596: }

598: /*@
599:    PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation

601:    Collective on PC and Vec

603:    Input Parameters:
604: .  pc - the preconditioner context

606:    Output Parameter:
607: .  flg - PETSC_TRUE if a transpose operation is defined

609:    Level: developer

611: .keywords: PC, apply, transpose

613: .seealso: PCApplyTranspose()
614: @*/
615: PetscErrorCode  PCApplyTransposeExists(PC pc,PetscBool  *flg)
616: {
620:   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
621:   else *flg = PETSC_FALSE;
622:   return(0);
623: }

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

628:    Collective on PC and Vec

630:    Input Parameters:
631: +  pc - the preconditioner context
632: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
633: .  x - input vector
634: -  work - work vector

636:    Output Parameter:
637: .  y - output vector

639:    Level: developer

641:    Notes:
642:     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
643:    specific KSPSolve() method must also be written to handle the post-solve "correction" for the diagonal scaling.

645: .keywords: PC, apply, operator

647: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
648: @*/
649: PetscErrorCode  PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
650: {

658:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
659:   if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
660:   if (pc->diagonalscale && side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application");
661:   if (pc->erroriffailure) {VecValidValues(x,3,PETSC_TRUE);}

663:   PCSetUp(pc);
664:   if (pc->diagonalscale) {
665:     if (pc->ops->applyBA) {
666:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
667:       VecDuplicate(x,&work2);
668:       PCDiagonalScaleRight(pc,x,work2);
669:       (*pc->ops->applyBA)(pc,side,work2,y,work);
670:       PCDiagonalScaleLeft(pc,y,y);
671:       VecDestroy(&work2);
672:     } else if (side == PC_RIGHT) {
673:       PCDiagonalScaleRight(pc,x,y);
674:       PCApply(pc,y,work);
675:       MatMult(pc->mat,work,y);
676:       PCDiagonalScaleLeft(pc,y,y);
677:     } else if (side == PC_LEFT) {
678:       PCDiagonalScaleRight(pc,x,y);
679:       MatMult(pc->mat,y,work);
680:       PCApply(pc,work,y);
681:       PCDiagonalScaleLeft(pc,y,y);
682:     } else if (side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner");
683:   } else {
684:     if (pc->ops->applyBA) {
685:       (*pc->ops->applyBA)(pc,side,x,y,work);
686:     } else if (side == PC_RIGHT) {
687:       PCApply(pc,x,work);
688:       MatMult(pc->mat,work,y);
689:     } else if (side == PC_LEFT) {
690:       MatMult(pc->mat,x,work);
691:       PCApply(pc,work,y);
692:     } else if (side == PC_SYMMETRIC) {
693:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
694:       PCApplySymmetricRight(pc,x,work);
695:       MatMult(pc->mat,work,y);
696:       VecCopy(y,work);
697:       PCApplySymmetricLeft(pc,work,y);
698:     }
699:   }
700:   if (pc->erroriffailure) {VecValidValues(y,4,PETSC_FALSE);}
701:   return(0);
702: }

704: /*@
705:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
706:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
707:    NOT tr(B*A) = tr(A)*tr(B).

709:    Collective on PC and Vec

711:    Input Parameters:
712: +  pc - the preconditioner context
713: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
714: .  x - input vector
715: -  work - work vector

717:    Output Parameter:
718: .  y - output vector


721:    Notes:
722:     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
723:       defined by B'. This is why this has the funny form that it computes tr(B) * tr(A)

725:     Level: developer

727: .keywords: PC, apply, operator, transpose

729: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
730: @*/
731: PetscErrorCode  PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
732: {

740:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
741:   if (pc->erroriffailure) {VecValidValues(x,3,PETSC_TRUE);}
742:   if (pc->ops->applyBAtranspose) {
743:     (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
744:     if (pc->erroriffailure) {VecValidValues(y,4,PETSC_FALSE);}
745:     return(0);
746:   }
747:   if (side != PC_LEFT && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");

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

762: /* -------------------------------------------------------------------------------*/

764: /*@
765:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a
766:    built-in fast application of Richardson's method.

768:    Not Collective

770:    Input Parameter:
771: .  pc - the preconditioner

773:    Output Parameter:
774: .  exists - PETSC_TRUE or PETSC_FALSE

776:    Level: developer

778: .keywords: PC, apply, Richardson, exists

780: .seealso: PCApplyRichardson()
781: @*/
782: PetscErrorCode  PCApplyRichardsonExists(PC pc,PetscBool  *exists)
783: {
787:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
788:   else *exists = PETSC_FALSE;
789:   return(0);
790: }

792: /*@
793:    PCApplyRichardson - Applies several steps of Richardson iteration with
794:    the particular preconditioner. This routine is usually used by the
795:    Krylov solvers and not the application code directly.

797:    Collective on PC

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

809:    Output Parameter:
810: +  outits - number of iterations actually used (for SOR this always equals its)
811: .  reason - the reason the apply terminated
812: -  y - the solution (also contains initial guess if guesszero is PETSC_FALSE

814:    Notes:
815:    Most preconditioners do not support this function. Use the command
816:    PCApplyRichardsonExists() to determine if one does.

818:    Except for the multigrid PC this routine ignores the convergence tolerances
819:    and always runs for the number of iterations

821:    Level: developer

823: .keywords: PC, apply, Richardson

825: .seealso: PCApplyRichardsonExists()
826: @*/
827: PetscErrorCode  PCApplyRichardson(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
828: {

836:   if (b == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"b and y must be different vectors");
837:   PCSetUp(pc);
838:   if (!pc->ops->applyrichardson) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply richardson");
839:   (*pc->ops->applyrichardson)(pc,b,y,w,rtol,abstol,dtol,its,guesszero,outits,reason);
840:   return(0);
841: }

843: /*@
844:    PCGetSetUpFailedReason - Gets the reason a PCSetUp() failed or 0 if it did not fail

846:    Logically Collective on PC

848:    Input Parameter:
849: .  pc - the preconditioner context

851:    Output Parameter:
852: .  reason - the reason it failed, currently only -1

854:    Level: advanced

856: .keywords: PC, setup

858: .seealso: PCCreate(), PCApply(), PCDestroy()
859: @*/
860: PetscErrorCode PCGetSetUpFailedReason(PC pc,PCFailedReason *reason)
861: {
863:   if (pc->setupcalled < 0) *reason = (PCFailedReason)pc->setupcalled;
864:   else *reason = pc->failedreason;
865:   return(0);
866: }


869: /*
870:       a setupcall of 0 indicates never setup,
871:                      1 indicates has been previously setup
872:                     -1 indicates a PCSetUp() was attempted and failed
873: */
874: /*@
875:    PCSetUp - Prepares for the use of a preconditioner.

877:    Collective on PC

879:    Input Parameter:
880: .  pc - the preconditioner context

882:    Level: developer

884: .keywords: PC, setup

886: .seealso: PCCreate(), PCApply(), PCDestroy()
887: @*/
888: PetscErrorCode  PCSetUp(PC pc)
889: {
890:   PetscErrorCode   ierr;
891:   const char       *def;
892:   PetscObjectState matstate, matnonzerostate;

896:   if (!pc->mat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");

898:   if (pc->setupcalled && pc->reusepreconditioner) {
899:     PetscInfo(pc,"Leaving PC with identical preconditioner since reuse preconditioner is set\n");
900:     return(0);
901:   }

903:   PetscObjectStateGet((PetscObject)pc->pmat,&matstate);
904:   MatGetNonzeroState(pc->pmat,&matnonzerostate);
905:   if (!pc->setupcalled) {
906:     PetscInfo(pc,"Setting up PC for first time\n");
907:     pc->flag        = DIFFERENT_NONZERO_PATTERN;
908:   } else if (matstate == pc->matstate) {
909:     PetscInfo(pc,"Leaving PC with identical preconditioner since operator is unchanged\n");
910:     return(0);
911:   } else {
912:     if (matnonzerostate > pc->matnonzerostate) {
913:        PetscInfo(pc,"Setting up PC with different nonzero pattern\n");
914:        pc->flag            = DIFFERENT_NONZERO_PATTERN;
915:     } else {
916:       PetscInfo(pc,"Setting up PC with same nonzero pattern\n");
917:       pc->flag            = SAME_NONZERO_PATTERN;
918:     }
919:   }
920:   pc->matstate        = matstate;
921:   pc->matnonzerostate = matnonzerostate;

923:   if (!((PetscObject)pc)->type_name) {
924:     PCGetDefaultType_Private(pc,&def);
925:     PCSetType(pc,def);
926:   }

928:   MatSetErrorIfFailure(pc->pmat,pc->erroriffailure);
929:   MatSetErrorIfFailure(pc->mat,pc->erroriffailure);
930:   PetscLogEventBegin(PC_SetUp,pc,0,0,0);
931:   if (pc->ops->setup) {
932:     (*pc->ops->setup)(pc);
933:   }
934:   PetscLogEventEnd(PC_SetUp,pc,0,0,0);
935:   if (!pc->setupcalled) pc->setupcalled = 1;
936:   return(0);
937: }

939: /*@
940:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
941:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
942:    methods.

944:    Collective on PC

946:    Input Parameters:
947: .  pc - the preconditioner context

949:    Level: developer

951: .keywords: PC, setup, blocks

953: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
954: @*/
955: PetscErrorCode  PCSetUpOnBlocks(PC pc)
956: {

961:   if (!pc->ops->setuponblocks) return(0);
962:   PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
963:   (*pc->ops->setuponblocks)(pc);
964:   PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
965:   return(0);
966: }

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

975:    Logically Collective on PC

977:    Input Parameters:
978: +  pc - the preconditioner context
979: .  func - routine for modifying the submatrices
980: -  ctx - optional user-defined context (may be null)

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

985: .  row - an array of index sets that contain the global row numbers
986:          that comprise each local submatrix
987: .  col - an array of index sets that contain the global column numbers
988:          that comprise each local submatrix
989: .  submat - array of local submatrices
990: -  ctx - optional user-defined context for private data for the
991:          user-defined func routine (may be null)

993:    Notes:
994:    PCSetModifySubMatrices() MUST be called before KSPSetUp() and
995:    KSPSolve().

997:    A routine set by PCSetModifySubMatrices() is currently called within
998:    the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
999:    preconditioners.  All other preconditioners ignore this routine.

1001:    Level: advanced

1003: .keywords: PC, set, modify, submatrices

1005: .seealso: PCModifySubMatrices(), PCASMGetSubMatrices()
1006: @*/
1007: PetscErrorCode  PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx)
1008: {
1011:   pc->modifysubmatrices  = func;
1012:   pc->modifysubmatricesP = ctx;
1013:   return(0);
1014: }

1016: /*@C
1017:    PCModifySubMatrices - Calls an optional user-defined routine within
1018:    certain preconditioners if one has been set with PCSetModifySubMarices().

1020:    Collective on PC

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

1033:    Output Parameter:
1034: .  submat - array of local submatrices (the entries of which may
1035:             have been modified)

1037:    Notes:
1038:    The user should NOT generally call this routine, as it will
1039:    automatically be called within certain preconditioners (currently
1040:    block Jacobi, additive Schwarz) if set.

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

1047:    Level: developer

1049: .keywords: PC, modify, submatrices

1051: .seealso: PCSetModifySubMatrices()
1052: @*/
1053: PetscErrorCode  PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
1054: {

1059:   if (!pc->modifysubmatrices) return(0);
1060:   PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
1061:   (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
1062:   PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
1063:   return(0);
1064: }

1066: /*@
1067:    PCSetOperators - Sets the matrix associated with the linear system and
1068:    a (possibly) different one associated with the preconditioner.

1070:    Logically Collective on PC and Mat

1072:    Input Parameters:
1073: +  pc - the preconditioner context
1074: .  Amat - the matrix that defines the linear system
1075: -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.

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

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

1084:    More Notes about Repeated Solution of Linear Systems:
1085:    PETSc does NOT reset the matrix entries of either Amat or Pmat
1086:    to zero after a linear solve; the user is completely responsible for
1087:    matrix assembly.  See the routine MatZeroEntries() if desiring to
1088:    zero all elements of a matrix.

1090:    Level: intermediate

1092: .keywords: PC, set, operators, matrix, linear system

1094: .seealso: PCGetOperators(), MatZeroEntries()
1095:  @*/
1096: PetscErrorCode  PCSetOperators(PC pc,Mat Amat,Mat Pmat)
1097: {
1098:   PetscErrorCode   ierr;
1099:   PetscInt         m1,n1,m2,n2;

1107:   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
1108:     MatGetLocalSize(Amat,&m1,&n1);
1109:     MatGetLocalSize(pc->mat,&m2,&n2);
1110:     if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot change local size of Amat after use old sizes %D %D new sizes %D %D",m2,n2,m1,n1);
1111:     MatGetLocalSize(Pmat,&m1,&n1);
1112:     MatGetLocalSize(pc->pmat,&m2,&n2);
1113:     if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot change local size of Pmat after use old sizes %D %D new sizes %D %D",m2,n2,m1,n1);
1114:   }

1116:   if (Pmat != pc->pmat) {
1117:     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
1118:     pc->matnonzerostate = -1;
1119:     pc->matstate        = -1;
1120:   }

1122:   /* reference first in case the matrices are the same */
1123:   if (Amat) {PetscObjectReference((PetscObject)Amat);}
1124:   MatDestroy(&pc->mat);
1125:   if (Pmat) {PetscObjectReference((PetscObject)Pmat);}
1126:   MatDestroy(&pc->pmat);
1127:   pc->mat  = Amat;
1128:   pc->pmat = Pmat;
1129:   return(0);
1130: }

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

1135:    Logically Collective on PC

1137:    Input Parameters:
1138: +  pc - the preconditioner context
1139: -  flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner

1141:     Level: intermediate

1143: .seealso: PCGetOperators(), MatZeroEntries(), PCGetReusePreconditioner(), KSPSetReusePreconditioner()
1144:  @*/
1145: PetscErrorCode  PCSetReusePreconditioner(PC pc,PetscBool flag)
1146: {
1149:   pc->reusepreconditioner = flag;
1150:   return(0);
1151: }

1153: /*@
1154:    PCGetReusePreconditioner - Determines if the PC reuses the current preconditioner even if the operator in the preconditioner has changed.

1156:    Not Collective

1158:    Input Parameter:
1159: .  pc - the preconditioner context

1161:    Output Parameter:
1162: .  flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner

1164:    Level: intermediate

1166: .seealso: PCGetOperators(), MatZeroEntries(), PCSetReusePreconditioner()
1167:  @*/
1168: PetscErrorCode  PCGetReusePreconditioner(PC pc,PetscBool *flag)
1169: {
1172:   *flag = pc->reusepreconditioner;
1173:   return(0);
1174: }

1176: /*@
1177:    PCGetOperators - Gets the matrix associated with the linear system and
1178:    possibly a different one associated with the preconditioner.

1180:    Not collective, though parallel Mats are returned if the PC is parallel

1182:    Input Parameter:
1183: .  pc - the preconditioner context

1185:    Output Parameters:
1186: +  Amat - the matrix defining the linear system
1187: -  Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.

1189:    Level: intermediate

1191:    Notes:
1192:     Does not increase the reference count of the matrices, so you should not destroy them

1194:    Alternative usage: If the operators have NOT been set with KSP/PCSetOperators() then the operators
1195:       are created in PC and returned to the user. In this case, if both operators
1196:       mat and pmat are requested, two DIFFERENT operators will be returned. If
1197:       only one is requested both operators in the PC will be the same (i.e. as
1198:       if one had called KSP/PCSetOperators() with the same argument for both Mats).
1199:       The user must set the sizes of the returned matrices and their type etc just
1200:       as if the user created them with MatCreate(). For example,

1202: $         KSP/PCGetOperators(ksp/pc,&Amat,NULL); is equivalent to
1203: $           set size, type, etc of Amat

1205: $         MatCreate(comm,&mat);
1206: $         KSP/PCSetOperators(ksp/pc,Amat,Amat);
1207: $         PetscObjectDereference((PetscObject)mat);
1208: $           set size, type, etc of Amat

1210:      and

1212: $         KSP/PCGetOperators(ksp/pc,&Amat,&Pmat); is equivalent to
1213: $           set size, type, etc of Amat and Pmat

1215: $         MatCreate(comm,&Amat);
1216: $         MatCreate(comm,&Pmat);
1217: $         KSP/PCSetOperators(ksp/pc,Amat,Pmat);
1218: $         PetscObjectDereference((PetscObject)Amat);
1219: $         PetscObjectDereference((PetscObject)Pmat);
1220: $           set size, type, etc of Amat and Pmat

1222:     The rational for this support is so that when creating a TS, SNES, or KSP the hierarchy
1223:     of underlying objects (i.e. SNES, KSP, PC, Mat) and their livespans can be completely
1224:     managed by the top most level object (i.e. the TS, SNES, or KSP). Another way to look
1225:     at this is when you create a SNES you do not NEED to create a KSP and attach it to
1226:     the SNES object (the SNES object manages it for you). Similarly when you create a KSP
1227:     you do not need to attach a PC to it (the KSP object manages the PC object for you).
1228:     Thus, why should YOU have to create the Mat and attach it to the SNES/KSP/PC, when
1229:     it can be created for you?


1232: .keywords: PC, get, operators, matrix, linear system

1234: .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperatorsSet()
1235: @*/
1236: PetscErrorCode  PCGetOperators(PC pc,Mat *Amat,Mat *Pmat)
1237: {

1242:   if (Amat) {
1243:     if (!pc->mat) {
1244:       if (pc->pmat && !Pmat) {  /* Apmat has been set, but user did not request it, so use for Amat */
1245:         pc->mat = pc->pmat;
1246:         PetscObjectReference((PetscObject)pc->mat);
1247:       } else {                  /* both Amat and Pmat are empty */
1248:         MatCreate(PetscObjectComm((PetscObject)pc),&pc->mat);
1249:         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
1250:           pc->pmat = pc->mat;
1251:           PetscObjectReference((PetscObject)pc->pmat);
1252:         }
1253:       }
1254:     }
1255:     *Amat = pc->mat;
1256:   }
1257:   if (Pmat) {
1258:     if (!pc->pmat) {
1259:       if (pc->mat && !Amat) {    /* Amat has been set but was not requested, so use for pmat */
1260:         pc->pmat = pc->mat;
1261:         PetscObjectReference((PetscObject)pc->pmat);
1262:       } else {
1263:         MatCreate(PetscObjectComm((PetscObject)pc),&pc->pmat);
1264:         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
1265:           pc->mat = pc->pmat;
1266:           PetscObjectReference((PetscObject)pc->mat);
1267:         }
1268:       }
1269:     }
1270:     *Pmat = pc->pmat;
1271:   }
1272:   return(0);
1273: }

1275: /*@C
1276:    PCGetOperatorsSet - Determines if the matrix associated with the linear system and
1277:    possibly a different one associated with the preconditioner have been set in the PC.

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

1281:    Input Parameter:
1282: .  pc - the preconditioner context

1284:    Output Parameters:
1285: +  mat - the matrix associated with the linear system was set
1286: -  pmat - matrix associated with the preconditioner was set, usually the same

1288:    Level: intermediate

1290: .keywords: PC, get, operators, matrix, linear system

1292: .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperators()
1293: @*/
1294: PetscErrorCode  PCGetOperatorsSet(PC pc,PetscBool  *mat,PetscBool  *pmat)
1295: {
1298:   if (mat) *mat = (pc->mat)  ? PETSC_TRUE : PETSC_FALSE;
1299:   if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
1300:   return(0);
1301: }

1303: /*@
1304:    PCFactorGetMatrix - Gets the factored matrix from the
1305:    preconditioner context.  This routine is valid only for the LU,
1306:    incomplete LU, Cholesky, and incomplete Cholesky methods.

1308:    Not Collective on PC though Mat is parallel if PC is parallel

1310:    Input Parameters:
1311: .  pc - the preconditioner context

1313:    Output parameters:
1314: .  mat - the factored matrix

1316:    Level: advanced

1318:    Notes:
1319:     Does not increase the reference count for the matrix so DO NOT destroy it

1321: .keywords: PC, get, factored, matrix
1322: @*/
1323: PetscErrorCode  PCFactorGetMatrix(PC pc,Mat *mat)
1324: {

1330:   if (pc->ops->getfactoredmatrix) {
1331:     (*pc->ops->getfactoredmatrix)(pc,mat);
1332:   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC type does not support getting factor matrix");
1333:   return(0);
1334: }

1336: /*@C
1337:    PCSetOptionsPrefix - Sets the prefix used for searching for all
1338:    PC options in the database.

1340:    Logically Collective on PC

1342:    Input Parameters:
1343: +  pc - the preconditioner context
1344: -  prefix - the prefix string to prepend to all PC option requests

1346:    Notes:
1347:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1348:    The first character of all runtime options is AUTOMATICALLY the
1349:    hyphen.

1351:    Level: advanced

1353: .keywords: PC, set, options, prefix, database

1355: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1356: @*/
1357: PetscErrorCode  PCSetOptionsPrefix(PC pc,const char prefix[])
1358: {

1363:   PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1364:   return(0);
1365: }

1367: /*@C
1368:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all
1369:    PC options in the database.

1371:    Logically Collective on PC

1373:    Input Parameters:
1374: +  pc - the preconditioner context
1375: -  prefix - the prefix string to prepend to all PC option requests

1377:    Notes:
1378:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1379:    The first character of all runtime options is AUTOMATICALLY the
1380:    hyphen.

1382:    Level: advanced

1384: .keywords: PC, append, options, prefix, database

1386: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1387: @*/
1388: PetscErrorCode  PCAppendOptionsPrefix(PC pc,const char prefix[])
1389: {

1394:   PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1395:   return(0);
1396: }

1398: /*@C
1399:    PCGetOptionsPrefix - Gets the prefix used for searching for all
1400:    PC options in the database.

1402:    Not Collective

1404:    Input Parameters:
1405: .  pc - the preconditioner context

1407:    Output Parameters:
1408: .  prefix - pointer to the prefix string used, is returned

1410:    Notes:
1411:     On the fortran side, the user should pass in a string 'prifix' of
1412:    sufficient length to hold the prefix.

1414:    Level: advanced

1416: .keywords: PC, get, options, prefix, database

1418: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1419: @*/
1420: PetscErrorCode  PCGetOptionsPrefix(PC pc,const char *prefix[])
1421: {

1427:   PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1428:   return(0);
1429: }

1431: /*
1432:    Indicates the right hand side will be changed by KSPSolve(), this occurs for a few
1433:   preconditioners including BDDC and Eisentat that transform the equations before applying
1434:   the Krylov methods
1435: */
1436: PETSC_INTERN PetscErrorCode  PCPreSolveChangeRHS(PC pc,PetscBool *change)
1437: {

1443:   *change = PETSC_FALSE;
1444:   PetscTryMethod(pc,"PCPreSolveChangeRHS_C",(PC,PetscBool*),(pc,change));
1445:   return(0);
1446: }

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

1453:    Collective on PC

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

1459:    Level: developer

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

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

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

1473: .keywords: PC, pre-solve

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

1485:   pc->presolvedone++;
1486:   if (pc->presolvedone > 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot embed PCPreSolve() more than twice");
1487:   KSPGetSolution(ksp,&x);
1488:   KSPGetRhs(ksp,&rhs);

1490:   if (pc->ops->presolve) {
1491:     (*pc->ops->presolve)(pc,ksp,rhs,x);
1492:   }
1493:   return(0);
1494: }

1496: /*@
1497:    PCPostSolve - Optional post-solve phase, intended for any
1498:    preconditioner-specific actions that must be performed after
1499:    the iterative solve itself.

1501:    Collective on PC

1503:    Input Parameters:
1504: +  pc - the preconditioner context
1505: -  ksp - the Krylov subspace context

1507:    Sample of Usage:
1508: .vb
1509:     PCPreSolve(pc,ksp);
1510:     KSPSolve(ksp,b,x);
1511:     PCPostSolve(pc,ksp);
1512: .ve

1514:    Note:
1515:    KSPSolve() calls this routine directly, so it is rarely called by the user.

1517:    Level: developer

1519: .keywords: PC, post-solve

1521: .seealso: PCPreSolve(), KSPSolve()
1522: @*/
1523: PetscErrorCode  PCPostSolve(PC pc,KSP ksp)
1524: {
1526:   Vec            x,rhs;

1531:   pc->presolvedone--;
1532:   KSPGetSolution(ksp,&x);
1533:   KSPGetRhs(ksp,&rhs);
1534:   if (pc->ops->postsolve) {
1535:      (*pc->ops->postsolve)(pc,ksp,rhs,x);
1536:   }
1537:   return(0);
1538: }

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

1543:   Collective on PetscViewer

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

1550:    Level: intermediate

1552:   Notes:
1553:    The type is determined by the data in the file, any type set into the PC before this call is ignored.

1555:   Notes for advanced users:
1556:   Most users should not need to know the details of the binary storage
1557:   format, since PCLoad() and PCView() completely hide these details.
1558:   But for anyone who's interested, the standard binary matrix storage
1559:   format is
1560: .vb
1561:      has not yet been determined
1562: .ve

1564: .seealso: PetscViewerBinaryOpen(), PCView(), MatLoad(), VecLoad()
1565: @*/
1566: PetscErrorCode  PCLoad(PC newdm, PetscViewer viewer)
1567: {
1569:   PetscBool      isbinary;
1570:   PetscInt       classid;
1571:   char           type[256];

1576:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1577:   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");

1579:   PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
1580:   if (classid != PC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not PC next in file");
1581:   PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
1582:   PCSetType(newdm, type);
1583:   if (newdm->ops->load) {
1584:     (*newdm->ops->load)(newdm,viewer);
1585:   }
1586:   return(0);
1587: }

1589:  #include <petscdraw.h>
1590: #if defined(PETSC_HAVE_SAWS)
1591:  #include <petscviewersaws.h>
1592: #endif
1593: /*@C
1594:    PCView - Prints the PC data structure.

1596:    Collective on PC

1598:    Input Parameters:
1599: +  PC - the PC context
1600: -  viewer - optional visualization context

1602:    Note:
1603:    The available visualization contexts include
1604: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1605: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1606:          output where only the first processor opens
1607:          the file.  All other processors send their
1608:          data to the first processor to print.

1610:    The user can open an alternative visualization contexts with
1611:    PetscViewerASCIIOpen() (output to a specified file).

1613:    Level: developer

1615: .keywords: PC, view

1617: .seealso: KSPView(), PetscViewerASCIIOpen()
1618: @*/
1619: PetscErrorCode  PCView(PC pc,PetscViewer viewer)
1620: {
1621:   PCType         cstr;
1623:   PetscBool      iascii,isstring,isbinary,isdraw;
1624: #if defined(PETSC_HAVE_SAWS)
1625:   PetscBool      issaws;
1626: #endif

1630:   if (!viewer) {
1631:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&viewer);
1632:   }

1636:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
1637:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
1638:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1639:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
1640: #if defined(PETSC_HAVE_SAWS)
1641:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);
1642: #endif

1644:   if (iascii) {
1645:     PetscObjectPrintClassNamePrefixType((PetscObject)pc,viewer);
1646:     if (!pc->setupcalled) {
1647:       PetscViewerASCIIPrintf(viewer,"  PC has not been set up so information may be incomplete\n");
1648:     }
1649:     if (pc->ops->view) {
1650:       PetscViewerASCIIPushTab(viewer);
1651:       (*pc->ops->view)(pc,viewer);
1652:       PetscViewerASCIIPopTab(viewer);
1653:     }
1654:     if (pc->mat) {
1655:       PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
1656:       if (pc->pmat == pc->mat) {
1657:         PetscViewerASCIIPrintf(viewer,"  linear system matrix = precond matrix:\n");
1658:         PetscViewerASCIIPushTab(viewer);
1659:         MatView(pc->mat,viewer);
1660:         PetscViewerASCIIPopTab(viewer);
1661:       } else {
1662:         if (pc->pmat) {
1663:           PetscViewerASCIIPrintf(viewer,"  linear system matrix followed by preconditioner matrix:\n");
1664:         } else {
1665:           PetscViewerASCIIPrintf(viewer,"  linear system matrix:\n");
1666:         }
1667:         PetscViewerASCIIPushTab(viewer);
1668:         MatView(pc->mat,viewer);
1669:         if (pc->pmat) {MatView(pc->pmat,viewer);}
1670:         PetscViewerASCIIPopTab(viewer);
1671:       }
1672:       PetscViewerPopFormat(viewer);
1673:     }
1674:   } else if (isstring) {
1675:     PCGetType(pc,&cstr);
1676:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
1677:     if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
1678:   } else if (isbinary) {
1679:     PetscInt    classid = PC_FILE_CLASSID;
1680:     MPI_Comm    comm;
1681:     PetscMPIInt rank;
1682:     char        type[256];

1684:     PetscObjectGetComm((PetscObject)pc,&comm);
1685:     MPI_Comm_rank(comm,&rank);
1686:     if (!rank) {
1687:       PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);
1688:       PetscStrncpy(type,((PetscObject)pc)->type_name,256);
1689:       PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);
1690:     }
1691:     if (pc->ops->view) {
1692:       (*pc->ops->view)(pc,viewer);
1693:     }
1694:   } else if (isdraw) {
1695:     PetscDraw draw;
1696:     char      str[25];
1697:     PetscReal x,y,bottom,h;
1698:     PetscInt  n;

1700:     PetscViewerDrawGetDraw(viewer,0,&draw);
1701:     PetscDrawGetCurrentPoint(draw,&x,&y);
1702:     if (pc->mat) {
1703:       MatGetSize(pc->mat,&n,NULL);
1704:       PetscSNPrintf(str,25,"PC: %s (%D)",((PetscObject)pc)->type_name,n);
1705:     } else {
1706:       PetscSNPrintf(str,25,"PC: %s",((PetscObject)pc)->type_name);
1707:     }
1708:     PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);
1709:     bottom = y - h;
1710:     PetscDrawPushCurrentPoint(draw,x,bottom);
1711:     if (pc->ops->view) {
1712:       (*pc->ops->view)(pc,viewer);
1713:     }
1714:     PetscDrawPopCurrentPoint(draw);
1715: #if defined(PETSC_HAVE_SAWS)
1716:   } else if (issaws) {
1717:     PetscMPIInt rank;

1719:     PetscObjectName((PetscObject)pc);
1720:     MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
1721:     if (!((PetscObject)pc)->amsmem && !rank) {
1722:       PetscObjectViewSAWs((PetscObject)pc,viewer);
1723:     }
1724:     if (pc->mat) {MatView(pc->mat,viewer);}
1725:     if (pc->pmat && pc->pmat != pc->mat) {MatView(pc->pmat,viewer);}
1726: #endif
1727:   }
1728:   return(0);
1729: }

1731: /*@C
1732:   PCRegister -  Adds a method to the preconditioner package.

1734:    Not collective

1736:    Input Parameters:
1737: +  name_solver - name of a new user-defined solver
1738: -  routine_create - routine to create method context

1740:    Notes:
1741:    PCRegister() may be called multiple times to add several user-defined preconditioners.

1743:    Sample usage:
1744: .vb
1745:    PCRegister("my_solver", MySolverCreate);
1746: .ve

1748:    Then, your solver can be chosen with the procedural interface via
1749: $     PCSetType(pc,"my_solver")
1750:    or at runtime via the option
1751: $     -pc_type my_solver

1753:    Level: advanced

1755: .keywords: PC, register

1757: .seealso: PCRegisterAll(), PCRegisterDestroy()
1758: @*/
1759: PetscErrorCode  PCRegister(const char sname[],PetscErrorCode (*function)(PC))
1760: {

1764:   PCInitializePackage();
1765:   PetscFunctionListAdd(&PCList,sname,function);
1766:   return(0);
1767: }

1769: /*@
1770:     PCComputeExplicitOperator - Computes the explicit preconditioned operator.

1772:     Collective on PC

1774:     Input Parameter:
1775: .   pc - the preconditioner object

1777:     Output Parameter:
1778: .   mat - the explict preconditioned operator

1780:     Notes:
1781:     This computation is done by applying the operators to columns of the
1782:     identity matrix.

1784:     Currently, this routine uses a dense matrix format when 1 processor
1785:     is used and a sparse format otherwise.  This routine is costly in general,
1786:     and is recommended for use only with relatively small systems.

1788:     Level: advanced

1790: .keywords: PC, compute, explicit, operator

1792: .seealso: KSPComputeExplicitOperator()

1794: @*/
1795: PetscErrorCode  PCComputeExplicitOperator(PC pc,Mat *mat)
1796: {
1797:   Vec            in,out;
1799:   PetscInt       i,M,m,*rows,start,end;
1800:   PetscMPIInt    size;
1801:   MPI_Comm       comm;
1802:   PetscScalar    *array,one = 1.0;


1808:   PetscObjectGetComm((PetscObject)pc,&comm);
1809:   MPI_Comm_size(comm,&size);

1811:   if (!pc->pmat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call");
1812:   MatCreateVecs(pc->pmat,&in,0);
1813:   VecDuplicate(in,&out);
1814:   VecGetOwnershipRange(in,&start,&end);
1815:   VecGetSize(in,&M);
1816:   VecGetLocalSize(in,&m);
1817:   PetscMalloc1(m+1,&rows);
1818:   for (i=0; i<m; i++) rows[i] = start + i;

1820:   MatCreate(comm,mat);
1821:   MatSetSizes(*mat,m,m,M,M);
1822:   if (size == 1) {
1823:     MatSetType(*mat,MATSEQDENSE);
1824:     MatSeqDenseSetPreallocation(*mat,NULL);
1825:   } else {
1826:     MatSetType(*mat,MATMPIAIJ);
1827:     MatMPIAIJSetPreallocation(*mat,0,NULL,0,NULL);
1828:   }
1829:   MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);

1831:   for (i=0; i<M; i++) {

1833:     VecSet(in,0.0);
1834:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
1835:     VecAssemblyBegin(in);
1836:     VecAssemblyEnd(in);

1838:     /* should fix, allowing user to choose side */
1839:     PCApply(pc,in,out);

1841:     VecGetArray(out,&array);
1842:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1843:     VecRestoreArray(out,&array);

1845:   }
1846:   PetscFree(rows);
1847:   VecDestroy(&out);
1848:   VecDestroy(&in);
1849:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1850:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1851:   return(0);
1852: }

1854: /*@
1855:    PCSetCoordinates - sets the coordinates of all the nodes on the local process

1857:    Collective on PC

1859:    Input Parameters:
1860: +  pc - the solver context
1861: .  dim - the dimension of the coordinates 1, 2, or 3
1862: -  coords - the coordinates

1864:    Level: intermediate

1866:    Notes:
1867:     coords is an array of the 3D coordinates for the nodes on
1868:    the local processor.  So if there are 108 equation on a processor
1869:    for a displacement finite element discretization of elasticity (so
1870:    that there are 36 = 108/3 nodes) then the array must have 108
1871:    double precision values (ie, 3 * 36).  These x y z coordinates
1872:    should be ordered for nodes 0 to N-1 like so: [ 0.x, 0.y, 0.z, 1.x,
1873:    ... , N-1.z ].

1875: .seealso: MatSetNearNullSpace()
1876: @*/
1877: PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
1878: {

1884:   PetscTryMethod(pc,"PCSetCoordinates_C",(PC,PetscInt,PetscInt,PetscReal*),(pc,dim,nloc,coords));
1885:   return(0);
1886: }