Date: 2015-10-02T22:17:39+00:00

Actual source code: precon.c
petsc-3.6.2 2015-10-02
Report Typos and Errors

      2: /*
      3:     The PC (preconditioner) interface routines, callable by users.
      4: */
      5: #include <petsc/private/pcimpl.h>            /*I "petscksp.h" I*/
      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, PC_ApplyOnMproc;

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

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

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

     61:    Collective on PC

     63:    Input Parameter:
     64: .  pc - the preconditioner context

     66:    Level: developer

     68:    Notes: 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

     70: .keywords: PC, destroy

     72: .seealso: PCCreate(), PCSetUp()
     73: @*/
     74: PetscErrorCode  PCReset(PC pc)
     75: {

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

     88:   pc->setupcalled = 0;
     89:   return(0);
     90: }

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

     97:    Collective on PC

     99:    Input Parameter:
    100: .  pc - the preconditioner context

    102:    Level: developer

    104: .keywords: PC, destroy

    106: .seealso: PCCreate(), PCSetUp()
    107: @*/
    108: PetscErrorCode  PCDestroy(PC *pc)
    109: {

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

    117:   PCReset(*pc);

    119:   /* if memory was published with SAWs then destroy it */
    120:   PetscObjectSAWsViewOff((PetscObject)*pc);
    121:   if ((*pc)->ops->destroy) {(*(*pc)->ops->destroy)((*pc));}
    122:   DMDestroy(&(*pc)->dm);
    123:   PetscHeaderDestroy(pc);
    124:   return(0);
    125: }

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

    133:    Logically Collective on PC

    135:    Input Parameter:
    136: .  pc - the preconditioner context

    138:    Output Parameter:
    139: .  flag - PETSC_TRUE if it applies the scaling

    141:    Level: developer

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

    147: .keywords: PC

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

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

    166:    Logically Collective on PC

    168:    Input Parameters:
    169: +  pc - the preconditioner context
    170: -  s - scaling vector

    172:    Level: intermediate

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

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

    180: .keywords: PC

    182: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCGetDiagonalScale()
    183: @*/
    184: PetscErrorCode  PCSetDiagonalScale(PC pc,Vec s)
    185: {

    191:   pc->diagonalscale     = PETSC_TRUE;

    193:   PetscObjectReference((PetscObject)s);
    194:   VecDestroy(&pc->diagonalscaleleft);

    196:   pc->diagonalscaleleft = s;

    198:   VecDuplicate(s,&pc->diagonalscaleright);
    199:   VecCopy(s,pc->diagonalscaleright);
    200:   VecReciprocal(pc->diagonalscaleright);
    201:   return(0);
    202: }

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

    209:    Logically Collective on PC

    211:    Input Parameters:
    212: +  pc - the preconditioner context
    213: .  in - input vector
    214: +  out - scaled vector (maybe the same as in)

    216:    Level: intermediate

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

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

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

    226: .keywords: PC

    228: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
    229: @*/
    230: PetscErrorCode  PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
    231: {

    238:   if (pc->diagonalscale) {
    239:     VecPointwiseMult(out,pc->diagonalscaleleft,in);
    240:   } else if (in != out) {
    241:     VecCopy(in,out);
    242:   }
    243:   return(0);
    244: }

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

    251:    Logically Collective on PC

    253:    Input Parameters:
    254: +  pc - the preconditioner context
    255: .  in - input vector
    256: +  out - scaled vector (maybe the same as in)

    258:    Level: intermediate

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

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

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

    268: .keywords: PC

    270: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
    271: @*/
    272: PetscErrorCode  PCDiagonalScaleRight(PC pc,Vec in,Vec out)
    273: {

    280:   if (pc->diagonalscale) {
    281:     VecPointwiseMult(out,pc->diagonalscaleright,in);
    282:   } else if (in != out) {
    283:     VecCopy(in,out);
    284:   }
    285:   return(0);
    286: }

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

    295:    Logically Collective on PC

    297:    Input Parameters:
    298: +  pc - the preconditioner context
    299: -  flg - PETSC_TRUE to use the Amat, PETSC_FALSE to use the Pmat (default is false)

    301:    Options Database Key:
    302: .  -pc_use_amat <true,false>

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

    308:    Level: intermediate

    310: .seealso: PCGetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE
    311: @*/
    312: PetscErrorCode  PCSetUseAmat(PC pc,PetscBool flg)
    313: {
    316:   pc->useAmat = flg;
    317:   return(0);
    318: }

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

    325:    Logically Collective on PC

    327:    Input Parameters:
    328: +  pc - iterative context obtained from PCCreate()
    329: -  flg - PETSC_TRUE indicates you want the error generated

    331:    Level: advanced

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

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

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

    342: .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll()
    343: @*/
    344: PetscErrorCode  PCSetErrorIfFailure(PC pc,PetscBool flg)
    345: {
    349:   pc->erroriffailure = flg;
    350:   return(0);
    351: }

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

    360:    Logically Collective on PC

    362:    Input Parameter:
    363: .  pc - the preconditioner context

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

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

    372:    Level: intermediate

    374: .seealso: PCSetUseAmat(), PCBJACOBI, PGMG, PCFIELDSPLIT, PCCOMPOSITE
    375: @*/
    376: PetscErrorCode  PCGetUseAmat(PC pc,PetscBool *flg)
    377: {
    380:   *flg = pc->useAmat;
    381:   return(0);
    382: }

    386: /*@
    387:    PCCreate - Creates a preconditioner context.

    389:    Collective on MPI_Comm

    391:    Input Parameter:
    392: .  comm - MPI communicator

    394:    Output Parameter:
    395: .  pc - location to put the preconditioner context

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

    401:    Level: developer

    403: .keywords: PC, create, context

    405: .seealso: PCSetUp(), PCApply(), PCDestroy()
    406: @*/
    407: PetscErrorCode  PCCreate(MPI_Comm comm,PC *newpc)
    408: {
    409:   PC             pc;

    414:   *newpc = 0;
    415:   PCInitializePackage();

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

    419:   pc->mat                  = 0;
    420:   pc->pmat                 = 0;
    421:   pc->setupcalled          = 0;
    422:   pc->setfromoptionscalled = 0;
    423:   pc->data                 = 0;
    424:   pc->diagonalscale        = PETSC_FALSE;
    425:   pc->diagonalscaleleft    = 0;
    426:   pc->diagonalscaleright   = 0;

    428:   pc->modifysubmatrices  = 0;
    429:   pc->modifysubmatricesP = 0;

    431:   *newpc = pc;
    432:   return(0);

    434: }

    436: /* -------------------------------------------------------------------------------*/

    440: /*@
    441:    PCApply - Applies the preconditioner to a vector.

    443:    Collective on PC and Vec

    445:    Input Parameters:
    446: +  pc - the preconditioner context
    447: -  x - input vector

    449:    Output Parameter:
    450: .  y - output vector

    452:    Level: developer

    454: .keywords: PC, apply

    456: .seealso: PCApplyTranspose(), PCApplyBAorAB()
    457: @*/
    458: PetscErrorCode  PCApply(PC pc,Vec x,Vec y)
    459: {
    461:   PetscInt       m,n,mv,nv;

    467:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    468:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
    469:   /* use pmat to check vector sizes since for KSPLQR the pmat may be of a different size than mat */
    470:   MatGetLocalSize(pc->pmat,&m,&n);
    471:   VecGetLocalSize(x,&nv);
    472:   VecGetLocalSize(y,&mv);
    473:   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);
    474:   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);
    475:   VecLocked(y,3);

    477:   if (pc->setupcalled < 2) {
    478:     PCSetUp(pc);
    479:   }
    480:   if (!pc->ops->apply) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply");
    481:   VecLockPush(x);
    482:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
    483:   (*pc->ops->apply)(pc,x,y);
    484:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
    485:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
    486:   VecLockPop(x);
    487:   return(0);
    488: }

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

    495:    Collective on PC and Vec

    497:    Input Parameters:
    498: +  pc - the preconditioner context
    499: -  x - input vector

    501:    Output Parameter:
    502: .  y - output vector

    504:    Notes:
    505:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

    507:    Level: developer

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

    511: .seealso: PCApply(), PCApplySymmetricRight()
    512: @*/
    513: PetscErrorCode  PCApplySymmetricLeft(PC pc,Vec x,Vec y)
    514: {

    521:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    522:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
    523:   if (pc->setupcalled < 2) {
    524:     PCSetUp(pc);
    525:   }
    526:   if (!pc->ops->applysymmetricleft) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply");
    527:   VecLockPush(x);
    528:   PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
    529:   (*pc->ops->applysymmetricleft)(pc,x,y);
    530:   PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
    531:   VecLockPop(x);
    532:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
    533:   return(0);
    534: }

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

    541:    Collective on PC and Vec

    543:    Input Parameters:
    544: +  pc - the preconditioner context
    545: -  x - input vector

    547:    Output Parameter:
    548: .  y - output vector

    550:    Level: developer

    552:    Notes:
    553:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

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

    557: .seealso: PCApply(), PCApplySymmetricLeft()
    558: @*/
    559: PetscErrorCode  PCApplySymmetricRight(PC pc,Vec x,Vec y)
    560: {

    567:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    568:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
    569:   if (pc->setupcalled < 2) {
    570:     PCSetUp(pc);
    571:   }
    572:   if (!pc->ops->applysymmetricright) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have left symmetric apply");
    573:   VecLockPush(x);
    574:   PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
    575:   (*pc->ops->applysymmetricright)(pc,x,y);
    576:   PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
    577:   VecLockPop(x);
    578:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
    579:   return(0);
    580: }

    584: /*@
    585:    PCApplyTranspose - Applies the transpose of preconditioner to a vector.

    587:    Collective on PC and Vec

    589:    Input Parameters:
    590: +  pc - the preconditioner context
    591: -  x - input vector

    593:    Output Parameter:
    594: .  y - output vector

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

    598:    Developer Notes: We need to implement a PCApplyHermitianTranspose()

    600:    Level: developer

    602: .keywords: PC, apply, transpose

    604: .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCApplyTransposeExists()
    605: @*/
    606: PetscErrorCode  PCApplyTranspose(PC pc,Vec x,Vec y)
    607: {

    614:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    615:   if (pc->erroriffailure) {VecValidValues(x,2,PETSC_TRUE);}
    616:   if (pc->setupcalled < 2) {
    617:     PCSetUp(pc);
    618:   }
    619:   if (!pc->ops->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply transpose");
    620:   VecLockPush(x);
    621:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
    622:   (*pc->ops->applytranspose)(pc,x,y);
    623:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
    624:   VecLockPop(x);
    625:   if (pc->erroriffailure) {VecValidValues(y,3,PETSC_FALSE);}
    626:   return(0);
    627: }

    631: /*@
    632:    PCApplyTransposeExists - Test whether the preconditioner has a transpose apply operation

    634:    Collective on PC and Vec

    636:    Input Parameters:
    637: .  pc - the preconditioner context

    639:    Output Parameter:
    640: .  flg - PETSC_TRUE if a transpose operation is defined

    642:    Level: developer

    644: .keywords: PC, apply, transpose

    646: .seealso: PCApplyTranspose()
    647: @*/
    648: PetscErrorCode  PCApplyTransposeExists(PC pc,PetscBool  *flg)
    649: {
    653:   if (pc->ops->applytranspose) *flg = PETSC_TRUE;
    654:   else *flg = PETSC_FALSE;
    655:   return(0);
    656: }

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

    663:    Collective on PC and Vec

    665:    Input Parameters:
    666: +  pc - the preconditioner context
    667: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
    668: .  x - input vector
    669: -  work - work vector

    671:    Output Parameter:
    672: .  y - output vector

    674:    Level: developer

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

    679: .keywords: PC, apply, operator

    681: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
    682: @*/
    683: PetscErrorCode  PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
    684: {

    692:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    693:   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");
    694:   if (pc->diagonalscale && side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application");
    695:   if (pc->erroriffailure) {VecValidValues(x,3,PETSC_TRUE);}

    697:   if (pc->setupcalled < 2) {
    698:     PCSetUp(pc);
    699:   }

    701:   if (pc->diagonalscale) {
    702:     if (pc->ops->applyBA) {
    703:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
    704:       VecDuplicate(x,&work2);
    705:       PCDiagonalScaleRight(pc,x,work2);
    706:       (*pc->ops->applyBA)(pc,side,work2,y,work);
    707:       PCDiagonalScaleLeft(pc,y,y);
    708:       VecDestroy(&work2);
    709:     } else if (side == PC_RIGHT) {
    710:       PCDiagonalScaleRight(pc,x,y);
    711:       PCApply(pc,y,work);
    712:       MatMult(pc->mat,work,y);
    713:       PCDiagonalScaleLeft(pc,y,y);
    714:     } else if (side == PC_LEFT) {
    715:       PCDiagonalScaleRight(pc,x,y);
    716:       MatMult(pc->mat,y,work);
    717:       PCApply(pc,work,y);
    718:       PCDiagonalScaleLeft(pc,y,y);
    719:     } else if (side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner");
    720:   } else {
    721:     if (pc->ops->applyBA) {
    722:       (*pc->ops->applyBA)(pc,side,x,y,work);
    723:     } else if (side == PC_RIGHT) {
    724:       PCApply(pc,x,work);
    725:       MatMult(pc->mat,work,y);
    726:     } else if (side == PC_LEFT) {
    727:       MatMult(pc->mat,x,work);
    728:       PCApply(pc,work,y);
    729:     } else if (side == PC_SYMMETRIC) {
    730:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
    731:       PCApplySymmetricRight(pc,x,work);
    732:       MatMult(pc->mat,work,y);
    733:       VecCopy(y,work);
    734:       PCApplySymmetricLeft(pc,work,y);
    735:     }
    736:   }
    737:   if (pc->erroriffailure) {VecValidValues(y,4,PETSC_FALSE);}
    738:   return(0);
    739: }

    743: /*@
    744:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
    745:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
    746:    NOT tr(B*A) = tr(A)*tr(B).

    748:    Collective on PC and Vec

    750:    Input Parameters:
    751: +  pc - the preconditioner context
    752: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
    753: .  x - input vector
    754: -  work - work vector

    756:    Output Parameter:
    757: .  y - output vector

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

    763:     Level: developer

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

    767: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
    768: @*/
    769: PetscErrorCode  PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
    770: {

    778:   if (x == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    779:   if (pc->erroriffailure) {VecValidValues(x,3,PETSC_TRUE);}
    780:   if (pc->ops->applyBAtranspose) {
    781:     (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
    782:     if (pc->erroriffailure) {VecValidValues(y,4,PETSC_FALSE);}
    783:     return(0);
    784:   }
    785:   if (side != PC_LEFT && side != PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");

    787:   if (pc->setupcalled < 2) {
    788:     PCSetUp(pc);
    789:   }

    791:   if (side == PC_RIGHT) {
    792:     PCApplyTranspose(pc,x,work);
    793:     MatMultTranspose(pc->mat,work,y);
    794:   } else if (side == PC_LEFT) {
    795:     MatMultTranspose(pc->mat,x,work);
    796:     PCApplyTranspose(pc,work,y);
    797:   }
    798:   /* add support for PC_SYMMETRIC */
    799:   if (pc->erroriffailure) {VecValidValues(y,4,PETSC_FALSE);}
    800:   return(0);
    801: }

    803: /* -------------------------------------------------------------------------------*/

    807: /*@
    808:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a
    809:    built-in fast application of Richardson's method.

    811:    Not Collective

    813:    Input Parameter:
    814: .  pc - the preconditioner

    816:    Output Parameter:
    817: .  exists - PETSC_TRUE or PETSC_FALSE

    819:    Level: developer

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

    823: .seealso: PCApplyRichardson()
    824: @*/
    825: PetscErrorCode  PCApplyRichardsonExists(PC pc,PetscBool  *exists)
    826: {
    830:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
    831:   else *exists = PETSC_FALSE;
    832:   return(0);
    833: }

    837: /*@
    838:    PCApplyRichardson - Applies several steps of Richardson iteration with
    839:    the particular preconditioner. This routine is usually used by the
    840:    Krylov solvers and not the application code directly.

    842:    Collective on PC

    844:    Input Parameters:
    845: +  pc  - the preconditioner context
    846: .  b   - the right hand side
    847: .  w   - one work vector
    848: .  rtol - relative decrease in residual norm convergence criteria
    849: .  abstol - absolute residual norm convergence criteria
    850: .  dtol - divergence residual norm increase criteria
    851: .  its - the number of iterations to apply.
    852: -  guesszero - if the input x contains nonzero initial guess

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

    859:    Notes:
    860:    Most preconditioners do not support this function. Use the command
    861:    PCApplyRichardsonExists() to determine if one does.

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

    866:    Level: developer

    868: .keywords: PC, apply, Richardson

    870: .seealso: PCApplyRichardsonExists()
    871: @*/
    872: PetscErrorCode  PCApplyRichardson(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
    873: {

    881:   if (b == y) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_IDN,"b and y must be different vectors");
    882:   if (pc->setupcalled < 2) {
    883:     PCSetUp(pc);
    884:   }
    885:   if (!pc->ops->applyrichardson) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC does not have apply richardson");
    886:   (*pc->ops->applyrichardson)(pc,b,y,w,rtol,abstol,dtol,its,guesszero,outits,reason);
    887:   return(0);
    888: }

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

    895:    Logically Collective on PC

    897:    Input Parameter:
    898: .  pc - the preconditioner context

    900:    Output Parameter:
    901: .  reason - the reason it failed, currently only -1

    903:    Level: advanced

    905: .keywords: PC, setup

    907: .seealso: PCCreate(), PCApply(), PCDestroy()
    908: @*/
    909: PetscErrorCode  PCGetSetUpFailedReason(PC pc,PetscInt *reason)
    910: {
    912:   if (pc->setupcalled < 0) *reason = pc->setupcalled;
    913:   else *reason = 0;
    914:   return(0);
    915: }

    918: /*
    919:       a setupcall of 0 indicates never setup,
    920:                      1 indicates has been previously setup
    921:                     -1 indicates a PCSetUp() was attempted and failed
    922: */
    925: /*@
    926:    PCSetUp - Prepares for the use of a preconditioner.

    928:    Collective on PC

    930:    Input Parameter:
    931: .  pc - the preconditioner context

    933:    Level: developer

    935: .keywords: PC, setup

    937: .seealso: PCCreate(), PCApply(), PCDestroy()
    938: @*/
    939: PetscErrorCode  PCSetUp(PC pc)
    940: {
    941:   PetscErrorCode   ierr;
    942:   const char       *def;
    943:   PetscObjectState matstate, matnonzerostate;

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

    949:   if (pc->setupcalled && pc->reusepreconditioner) {
    950:     PetscInfo(pc,"Leaving PC with identical preconditioner since reuse preconditioner is set\n");
    951:     return(0);
    952:   }

    954:   PetscObjectStateGet((PetscObject)pc->pmat,&matstate);
    955:   MatGetNonzeroState(pc->pmat,&matnonzerostate);
    956:   if (!pc->setupcalled) {
    957:     PetscInfo(pc,"Setting up PC for first time\n");
    958:     pc->flag        = DIFFERENT_NONZERO_PATTERN;
    959:   } else if (matstate == pc->matstate) {
    960:     PetscInfo(pc,"Leaving PC with identical preconditioner since operator is unchanged\n");
    961:     return(0);
    962:   } else {
    963:     if (matnonzerostate > pc->matnonzerostate) {
    964:        PetscInfo(pc,"Setting up PC with different nonzero pattern\n");
    965:        pc->flag            = DIFFERENT_NONZERO_PATTERN;
    966:     } else {
    967:       PetscInfo(pc,"Setting up PC with same nonzero pattern\n");
    968:       pc->flag            = SAME_NONZERO_PATTERN;
    969:     }
    970:   }
    971:   pc->matstate        = matstate;
    972:   pc->matnonzerostate = matnonzerostate;

    974:   if (!((PetscObject)pc)->type_name) {
    975:     PCGetDefaultType_Private(pc,&def);
    976:     PCSetType(pc,def);
    977:   }

    979:   MatSetErrorIfFPE(pc->pmat,pc->erroriffailure);
    980:   MatSetErrorIfFPE(pc->mat,pc->erroriffailure);
    981:   PetscLogEventBegin(PC_SetUp,pc,0,0,0);
    982:   if (pc->ops->setup) {
    983:     (*pc->ops->setup)(pc);
    984:   }
    985:   PetscLogEventEnd(PC_SetUp,pc,0,0,0);
    986:   if (!pc->setupcalled) pc->setupcalled = 1;
    987:   return(0);
    988: }

    992: /*@
    993:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
    994:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz
    995:    methods.

    997:    Collective on PC

    999:    Input Parameters:
    1000: .  pc - the preconditioner context

    1002:    Level: developer

    1004: .keywords: PC, setup, blocks

    1006: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
    1007: @*/
    1008: PetscErrorCode  PCSetUpOnBlocks(PC pc)
    1009: {

    1014:   if (!pc->ops->setuponblocks) return(0);
    1015:   PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
    1016:   (*pc->ops->setuponblocks)(pc);
    1017:   PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
    1018:   return(0);
    1019: }

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

    1030:    Logically Collective on PC

    1032:    Input Parameters:
    1033: +  pc - the preconditioner context
    1034: .  func - routine for modifying the submatrices
    1035: -  ctx - optional user-defined context (may be null)

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

    1040: .  row - an array of index sets that contain the global row numbers
    1041:          that comprise each local submatrix
    1042: .  col - an array of index sets that contain the global column numbers
    1043:          that comprise each local submatrix
    1044: .  submat - array of local submatrices
    1045: -  ctx - optional user-defined context for private data for the
    1046:          user-defined func routine (may be null)

    1048:    Notes:
    1049:    PCSetModifySubMatrices() MUST be called before KSPSetUp() and
    1050:    KSPSolve().

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

    1056:    Level: advanced

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

    1060: .seealso: PCModifySubMatrices(), PCASMGetSubMatrices()
    1061: @*/
    1062: PetscErrorCode  PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx)
    1063: {
    1066:   pc->modifysubmatrices  = func;
    1067:   pc->modifysubmatricesP = ctx;
    1068:   return(0);
    1069: }

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

    1077:    Collective on PC

    1079:    Input Parameters:
    1080: +  pc - the preconditioner context
    1081: .  nsub - the number of local submatrices
    1082: .  row - an array of index sets that contain the global row numbers
    1083:          that comprise each local submatrix
    1084: .  col - an array of index sets that contain the global column numbers
    1085:          that comprise each local submatrix
    1086: .  submat - array of local submatrices
    1087: -  ctx - optional user-defined context for private data for the
    1088:          user-defined routine (may be null)

    1090:    Output Parameter:
    1091: .  submat - array of local submatrices (the entries of which may
    1092:             have been modified)

    1094:    Notes:
    1095:    The user should NOT generally call this routine, as it will
    1096:    automatically be called within certain preconditioners (currently
    1097:    block Jacobi, additive Schwarz) if set.

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

    1104:    Level: developer

    1106: .keywords: PC, modify, submatrices

    1108: .seealso: PCSetModifySubMatrices()
    1109: @*/
    1110: PetscErrorCode  PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
    1111: {

    1116:   if (!pc->modifysubmatrices) return(0);
    1117:   PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
    1118:   (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
    1119:   PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
    1120:   return(0);
    1121: }

    1125: /*@
    1126:    PCSetOperators - Sets the matrix associated with the linear system and
    1127:    a (possibly) different one associated with the preconditioner.

    1129:    Logically Collective on PC and Mat

    1131:    Input Parameters:
    1132: +  pc - the preconditioner context
    1133: .  Amat - the matrix that defines the linear system
    1134: -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.

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

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

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

    1149:    Level: intermediate

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

    1153: .seealso: PCGetOperators(), MatZeroEntries()
    1154:  @*/
    1155: PetscErrorCode  PCSetOperators(PC pc,Mat Amat,Mat Pmat)
    1156: {
    1157:   PetscErrorCode   ierr;
    1158:   PetscInt         m1,n1,m2,n2;

    1166:   if (pc->setupcalled && pc->mat && pc->pmat && Amat && Pmat) {
    1167:     MatGetLocalSize(Amat,&m1,&n1);
    1168:     MatGetLocalSize(pc->mat,&m2,&n2);
    1169:     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);
    1170:     MatGetLocalSize(Pmat,&m1,&n1);
    1171:     MatGetLocalSize(pc->pmat,&m2,&n2);
    1172:     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);
    1173:   }

    1175:   if (Pmat != pc->pmat) {
    1176:     /* changing the operator that defines the preconditioner thus reneed to clear current states so new preconditioner is built */
    1177:     pc->matnonzerostate = -1;
    1178:     pc->matstate        = -1;
    1179:   }

    1181:   /* reference first in case the matrices are the same */
    1182:   if (Amat) {PetscObjectReference((PetscObject)Amat);}
    1183:   MatDestroy(&pc->mat);
    1184:   if (Pmat) {PetscObjectReference((PetscObject)Pmat);}
    1185:   MatDestroy(&pc->pmat);
    1186:   pc->mat  = Amat;
    1187:   pc->pmat = Pmat;
    1188:   return(0);
    1189: }

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

    1196:    Logically Collective on PC

    1198:    Input Parameters:
    1199: +  pc - the preconditioner context
    1200: -  flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner

    1202:     Level: intermediate

    1204: .seealso: PCGetOperators(), MatZeroEntries(), PCGetReusePreconditioner(), KSPSetReusePreconditioner()
    1205:  @*/
    1206: PetscErrorCode  PCSetReusePreconditioner(PC pc,PetscBool flag)
    1207: {
    1210:   pc->reusepreconditioner = flag;
    1211:   return(0);
    1212: }

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

    1219:    Not Collective

    1221:    Input Parameter:
    1222: .  pc - the preconditioner context

    1224:    Output Parameter:
    1225: .  flag - PETSC_TRUE do not compute a new preconditioner, PETSC_FALSE do compute a new preconditioner

    1227:    Level: intermediate

    1229: .seealso: PCGetOperators(), MatZeroEntries(), PCSetReusePreconditioner()
    1230:  @*/
    1231: PetscErrorCode  PCGetReusePreconditioner(PC pc,PetscBool *flag)
    1232: {
    1235:   *flag = pc->reusepreconditioner;
    1236:   return(0);
    1237: }

    1241: /*@C
    1242:    PCGetOperators - Gets the matrix associated with the linear system and
    1243:    possibly a different one associated with the preconditioner.

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

    1247:    Input Parameter:
    1248: .  pc - the preconditioner context

    1250:    Output Parameters:
    1251: +  Amat - the matrix defining the linear system
    1252: -  Pmat - the matrix from which the preconditioner is constructed, usually the same as Amat.

    1254:    Level: intermediate

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

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

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

    1269: $         MatCreate(comm,&mat);
    1270: $         KSP/PCSetOperators(ksp/pc,Amat,Amat);
    1271: $         PetscObjectDereference((PetscObject)mat);
    1272: $           set size, type, etc of Amat

    1274:      and

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

    1279: $         MatCreate(comm,&Amat);
    1280: $         MatCreate(comm,&Pmat);
    1281: $         KSP/PCSetOperators(ksp/pc,Amat,Pmat);
    1282: $         PetscObjectDereference((PetscObject)Amat);
    1283: $         PetscObjectDereference((PetscObject)Pmat);
    1284: $           set size, type, etc of Amat and Pmat

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

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

    1298: .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperatorsSet()
    1299: @*/
    1300: PetscErrorCode  PCGetOperators(PC pc,Mat *Amat,Mat *Pmat)
    1301: {

    1306:   if (Amat) {
    1307:     if (!pc->mat) {
    1308:       if (pc->pmat && !Pmat) {  /* Apmat has been set, but user did not request it, so use for Amat */
    1309:         pc->mat = pc->pmat;
    1310:         PetscObjectReference((PetscObject)pc->mat);
    1311:       } else {                  /* both Amat and Pmat are empty */
    1312:         MatCreate(PetscObjectComm((PetscObject)pc),&pc->mat);
    1313:         if (!Pmat) { /* user did NOT request Pmat, so make same as Amat */
    1314:           pc->pmat = pc->mat;
    1315:           PetscObjectReference((PetscObject)pc->pmat);
    1316:         }
    1317:       }
    1318:     }
    1319:     *Amat = pc->mat;
    1320:   }
    1321:   if (Pmat) {
    1322:     if (!pc->pmat) {
    1323:       if (pc->mat && !Amat) {    /* Amat has been set but was not requested, so use for pmat */
    1324:         pc->pmat = pc->mat;
    1325:         PetscObjectReference((PetscObject)pc->pmat);
    1326:       } else {
    1327:         MatCreate(PetscObjectComm((PetscObject)pc),&pc->pmat);
    1328:         if (!Amat) { /* user did NOT request Amat, so make same as Pmat */
    1329:           pc->mat = pc->pmat;
    1330:           PetscObjectReference((PetscObject)pc->mat);
    1331:         }
    1332:       }
    1333:     }
    1334:     *Pmat = pc->pmat;
    1335:   }
    1336:   return(0);
    1337: }

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

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

    1347:    Input Parameter:
    1348: .  pc - the preconditioner context

    1350:    Output Parameters:
    1351: +  mat - the matrix associated with the linear system was set
    1352: -  pmat - matrix associated with the preconditioner was set, usually the same

    1354:    Level: intermediate

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

    1358: .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperators()
    1359: @*/
    1360: PetscErrorCode  PCGetOperatorsSet(PC pc,PetscBool  *mat,PetscBool  *pmat)
    1361: {
    1364:   if (mat) *mat = (pc->mat)  ? PETSC_TRUE : PETSC_FALSE;
    1365:   if (pmat) *pmat = (pc->pmat) ? PETSC_TRUE : PETSC_FALSE;
    1366:   return(0);
    1367: }

    1371: /*@
    1372:    PCFactorGetMatrix - Gets the factored matrix from the
    1373:    preconditioner context.  This routine is valid only for the LU,
    1374:    incomplete LU, Cholesky, and incomplete Cholesky methods.

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

    1378:    Input Parameters:
    1379: .  pc - the preconditioner context

    1381:    Output parameters:
    1382: .  mat - the factored matrix

    1384:    Level: advanced

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

    1388: .keywords: PC, get, factored, matrix
    1389: @*/
    1390: PetscErrorCode  PCFactorGetMatrix(PC pc,Mat *mat)
    1391: {

    1397:   if (pc->ops->getfactoredmatrix) {
    1398:     (*pc->ops->getfactoredmatrix)(pc,mat);
    1399:   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PC type does not support getting factor matrix");
    1400:   return(0);
    1401: }

    1405: /*@C
    1406:    PCSetOptionsPrefix - Sets the prefix used for searching for all
    1407:    PC options in the database.

    1409:    Logically Collective on PC

    1411:    Input Parameters:
    1412: +  pc - the preconditioner context
    1413: -  prefix - the prefix string to prepend to all PC option requests

    1415:    Notes:
    1416:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    1417:    The first character of all runtime options is AUTOMATICALLY the
    1418:    hyphen.

    1420:    Level: advanced

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

    1424: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
    1425: @*/
    1426: PetscErrorCode  PCSetOptionsPrefix(PC pc,const char prefix[])
    1427: {

    1432:   PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
    1433:   return(0);
    1434: }

    1438: /*@C
    1439:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all
    1440:    PC options in the database.

    1442:    Logically Collective on PC

    1444:    Input Parameters:
    1445: +  pc - the preconditioner context
    1446: -  prefix - the prefix string to prepend to all PC option requests

    1448:    Notes:
    1449:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    1450:    The first character of all runtime options is AUTOMATICALLY the
    1451:    hyphen.

    1453:    Level: advanced

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

    1457: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
    1458: @*/
    1459: PetscErrorCode  PCAppendOptionsPrefix(PC pc,const char prefix[])
    1460: {

    1465:   PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
    1466:   return(0);
    1467: }

    1471: /*@C
    1472:    PCGetOptionsPrefix - Gets the prefix used for searching for all
    1473:    PC options in the database.

    1475:    Not Collective

    1477:    Input Parameters:
    1478: .  pc - the preconditioner context

    1480:    Output Parameters:
    1481: .  prefix - pointer to the prefix string used, is returned

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

    1486:    Level: advanced

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

    1490: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
    1491: @*/
    1492: PetscErrorCode  PCGetOptionsPrefix(PC pc,const char *prefix[])
    1493: {

    1499:   PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
    1500:   return(0);
    1501: }

    1505: /*@
    1506:    PCPreSolve - Optional pre-solve phase, intended for any
    1507:    preconditioner-specific actions that must be performed before
    1508:    the iterative solve itself.

    1510:    Collective on PC

    1512:    Input Parameters:
    1513: +  pc - the preconditioner context
    1514: -  ksp - the Krylov subspace context

    1516:    Level: developer

    1518:    Sample of Usage:
    1519: .vb
    1520:     PCPreSolve(pc,ksp);
    1521:     KSPSolve(ksp,b,x);
    1522:     PCPostSolve(pc,ksp);
    1523: .ve

    1525:    Notes:
    1526:    The pre-solve phase is distinct from the PCSetUp() phase.

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

    1530: .keywords: PC, pre-solve

    1532: .seealso: PCPostSolve()
    1533: @*/
    1534: PetscErrorCode  PCPreSolve(PC pc,KSP ksp)
    1535: {
    1537:   Vec            x,rhs;

    1542:   pc->presolvedone++;
    1543:   if (pc->presolvedone > 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot embed PCPreSolve() more than twice");
    1544:   KSPGetSolution(ksp,&x);
    1545:   KSPGetRhs(ksp,&rhs);

    1547:   if (pc->ops->presolve) {
    1548:     (*pc->ops->presolve)(pc,ksp,rhs,x);
    1549:   }
    1550:   return(0);
    1551: }

    1555: /*@
    1556:    PCPostSolve - Optional post-solve phase, intended for any
    1557:    preconditioner-specific actions that must be performed after
    1558:    the iterative solve itself.

    1560:    Collective on PC

    1562:    Input Parameters:
    1563: +  pc - the preconditioner context
    1564: -  ksp - the Krylov subspace context

    1566:    Sample of Usage:
    1567: .vb
    1568:     PCPreSolve(pc,ksp);
    1569:     KSPSolve(ksp,b,x);
    1570:     PCPostSolve(pc,ksp);
    1571: .ve

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

    1576:    Level: developer

    1578: .keywords: PC, post-solve

    1580: .seealso: PCPreSolve(), KSPSolve()
    1581: @*/
    1582: PetscErrorCode  PCPostSolve(PC pc,KSP ksp)
    1583: {
    1585:   Vec            x,rhs;

    1590:   pc->presolvedone--;
    1591:   KSPGetSolution(ksp,&x);
    1592:   KSPGetRhs(ksp,&rhs);
    1593:   if (pc->ops->postsolve) {
    1594:      (*pc->ops->postsolve)(pc,ksp,rhs,x);
    1595:   }
    1596:   return(0);
    1597: }

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

    1604:   Collective on PetscViewer

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

    1611:    Level: intermediate

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

    1616:   Notes for advanced users:
    1617:   Most users should not need to know the details of the binary storage
    1618:   format, since PCLoad() and PCView() completely hide these details.
    1619:   But for anyone who's interested, the standard binary matrix storage
    1620:   format is
    1621: .vb
    1622:      has not yet been determined
    1623: .ve

    1625: .seealso: PetscViewerBinaryOpen(), PCView(), MatLoad(), VecLoad()
    1626: @*/
    1627: PetscErrorCode  PCLoad(PC newdm, PetscViewer viewer)
    1628: {
    1630:   PetscBool      isbinary;
    1631:   PetscInt       classid;
    1632:   char           type[256];

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

    1640:   PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
    1641:   if (classid != PC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not PC next in file");
    1642:   PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
    1643:   PCSetType(newdm, type);
    1644:   if (newdm->ops->load) {
    1645:     (*newdm->ops->load)(newdm,viewer);
    1646:   }
    1647:   return(0);
    1648: }

    1650: #include <petscdraw.h>
    1651: #if defined(PETSC_HAVE_SAWS)
    1652: #include <petscviewersaws.h>
    1653: #endif
    1656: /*@C
    1657:    PCView - Prints the PC data structure.

    1659:    Collective on PC

    1661:    Input Parameters:
    1662: +  PC - the PC context
    1663: -  viewer - optional visualization context

    1665:    Note:
    1666:    The available visualization contexts include
    1667: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    1668: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    1669:          output where only the first processor opens
    1670:          the file.  All other processors send their
    1671:          data to the first processor to print.

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

    1676:    Level: developer

    1678: .keywords: PC, view

    1680: .seealso: KSPView(), PetscViewerASCIIOpen()
    1681: @*/
    1682: PetscErrorCode  PCView(PC pc,PetscViewer viewer)
    1683: {
    1684:   PCType            cstr;
    1685:   PetscErrorCode    ierr;
    1686:   PetscBool         iascii,isstring,isbinary,isdraw;
    1687:   PetscViewerFormat format;
    1688: #if defined(PETSC_HAVE_SAWS)
    1689:   PetscBool         issaws;
    1690: #endif

    1694:   if (!viewer) {
    1695:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&viewer);
    1696:   }

    1700:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    1701:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
    1702:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
    1703:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    1704: #if defined(PETSC_HAVE_SAWS)
    1705:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);
    1706: #endif

    1708:   if (iascii) {
    1709:     PetscViewerGetFormat(viewer,&format);
    1710:     PetscObjectPrintClassNamePrefixType((PetscObject)pc,viewer);
    1711:     if (!pc->setupcalled) {
    1712:       PetscViewerASCIIPrintf(viewer,"  PC has not been set up so information may be incomplete\n");
    1713:     }
    1714:     if (pc->ops->view) {
    1715:       PetscViewerASCIIPushTab(viewer);
    1716:       (*pc->ops->view)(pc,viewer);
    1717:       PetscViewerASCIIPopTab(viewer);
    1718:     }
    1719:     if (pc->mat) {
    1720:       PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
    1721:       if (pc->pmat == pc->mat) {
    1722:         PetscViewerASCIIPrintf(viewer,"  linear system matrix = precond matrix:\n");
    1723:         PetscViewerASCIIPushTab(viewer);
    1724:         MatView(pc->mat,viewer);
    1725:         PetscViewerASCIIPopTab(viewer);
    1726:       } else {
    1727:         if (pc->pmat) {
    1728:           PetscViewerASCIIPrintf(viewer,"  linear system matrix followed by preconditioner matrix:\n");
    1729:         } else {
    1730:           PetscViewerASCIIPrintf(viewer,"  linear system matrix:\n");
    1731:         }
    1732:         PetscViewerASCIIPushTab(viewer);
    1733:         MatView(pc->mat,viewer);
    1734:         if (pc->pmat) {MatView(pc->pmat,viewer);}
    1735:         PetscViewerASCIIPopTab(viewer);
    1736:       }
    1737:       PetscViewerPopFormat(viewer);
    1738:     }
    1739:   } else if (isstring) {
    1740:     PCGetType(pc,&cstr);
    1741:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
    1742:     if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
    1743:   } else if (isbinary) {
    1744:     PetscInt    classid = PC_FILE_CLASSID;
    1745:     MPI_Comm    comm;
    1746:     PetscMPIInt rank;
    1747:     char        type[256];

    1749:     PetscObjectGetComm((PetscObject)pc,&comm);
    1750:     MPI_Comm_rank(comm,&rank);
    1751:     if (!rank) {
    1752:       PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);
    1753:       PetscStrncpy(type,((PetscObject)pc)->type_name,256);
    1754:       PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);
    1755:     }
    1756:     if (pc->ops->view) {
    1757:       (*pc->ops->view)(pc,viewer);
    1758:     }
    1759:   } else if (isdraw) {
    1760:     PetscDraw draw;
    1761:     char      str[25];
    1762:     PetscReal x,y,bottom,h;
    1763:     PetscInt  n;

    1765:     PetscViewerDrawGetDraw(viewer,0,&draw);
    1766:     PetscDrawGetCurrentPoint(draw,&x,&y);
    1767:     if (pc->mat) {
    1768:       MatGetSize(pc->mat,&n,NULL);
    1769:       PetscSNPrintf(str,25,"PC: %s (%D)",((PetscObject)pc)->type_name,n);
    1770:     } else {
    1771:       PetscSNPrintf(str,25,"PC: %s",((PetscObject)pc)->type_name);
    1772:     }
    1773:     PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);
    1774:     bottom = y - h;
    1775:     PetscDrawPushCurrentPoint(draw,x,bottom);
    1776:     if (pc->ops->view) {
    1777:       (*pc->ops->view)(pc,viewer);
    1778:     }
    1779:     PetscDrawPopCurrentPoint(draw);
    1780: #if defined(PETSC_HAVE_SAWS)
    1781:   } else if (issaws) {
    1782:     PetscMPIInt rank;

    1784:     PetscObjectName((PetscObject)pc);
    1785:     MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
    1786:     if (!((PetscObject)pc)->amsmem && !rank) {
    1787:       PetscObjectViewSAWs((PetscObject)pc,viewer);
    1788:     }
    1789:     if (pc->mat) {MatView(pc->mat,viewer);}
    1790:     if (pc->pmat && pc->pmat != pc->mat) {MatView(pc->pmat,viewer);}
    1791: #endif
    1792:   }
    1793:   return(0);
    1794: }

    1799: /*@
    1800:    PCSetInitialGuessNonzero - Tells the iterative solver that the
    1801:    initial guess is nonzero; otherwise PC assumes the initial guess
    1802:    is to be zero (and thus zeros it out before solving).

    1804:    Logically Collective on PC

    1806:    Input Parameters:
    1807: +  pc - iterative context obtained from PCCreate()
    1808: -  flg - PETSC_TRUE indicates the guess is non-zero, PETSC_FALSE indicates the guess is zero

    1810:    Level: Developer

    1812:    Notes:
    1813:     This is a weird function. Since PC's are linear operators on the right hand side they
    1814:     CANNOT use an initial guess. This function is for the "pass-through" preconditioners
    1815:     PCKSP and PCREDUNDANT  and causes the inner KSP object to use the nonzero
    1816:     initial guess. Not currently working for PCREDUNDANT, that has to be rewritten to use KSP.

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

    1821: .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll()
    1822: @*/
    1823: PetscErrorCode  PCSetInitialGuessNonzero(PC pc,PetscBool flg)
    1824: {
    1827:   pc->nonzero_guess = flg;
    1828:   return(0);
    1829: }

    1833: /*@
    1834:    PCGetInitialGuessNonzero - Determines if the iterative solver assumes that the
    1835:    initial guess is nonzero; otherwise PC assumes the initial guess
    1836:    is to be zero (and thus zeros it out before solving).

    1838:    Logically Collective on PC

    1840:    Input Parameter:
    1841: .   pc - iterative context obtained from PCCreate()

    1843:    Output Parameter:
    1844: .  flg - PETSC_TRUE indicates the guess is non-zero, PETSC_FALSE indicates the guess is zero

    1846:    Level: Developer

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

    1850: .seealso: PCGetInitialGuessNonzero(), PCSetInitialGuessKnoll(), PCGetInitialGuessKnoll(), PCSetInitialGuessNonzero()
    1851: @*/
    1852: PetscErrorCode  PCGetInitialGuessNonzero(PC pc,PetscBool *flg)
    1853: {
    1855:   *flg = pc->nonzero_guess;
    1856:   return(0);
    1857: }

    1861: /*@C
    1862:   PCRegister -  Adds a method to the preconditioner package.

    1864:    Not collective

    1866:    Input Parameters:
    1867: +  name_solver - name of a new user-defined solver
    1868: -  routine_create - routine to create method context

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

    1873:    Sample usage:
    1874: .vb
    1875:    PCRegister("my_solver", MySolverCreate);
    1876: .ve

    1878:    Then, your solver can be chosen with the procedural interface via
    1879: $     PCSetType(pc,"my_solver")
    1880:    or at runtime via the option
    1881: $     -pc_type my_solver

    1883:    Level: advanced

    1885: .keywords: PC, register

    1887: .seealso: PCRegisterAll(), PCRegisterDestroy()
    1888: @*/
    1889: PetscErrorCode  PCRegister(const char sname[],PetscErrorCode (*function)(PC))
    1890: {

    1894:   PetscFunctionListAdd(&PCList,sname,function);
    1895:   return(0);
    1896: }

    1900: /*@
    1901:     PCComputeExplicitOperator - Computes the explicit preconditioned operator.

    1903:     Collective on PC

    1905:     Input Parameter:
    1906: .   pc - the preconditioner object

    1908:     Output Parameter:
    1909: .   mat - the explict preconditioned operator

    1911:     Notes:
    1912:     This computation is done by applying the operators to columns of the
    1913:     identity matrix.

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

    1919:     Level: advanced

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

    1923: .seealso: KSPComputeExplicitOperator()

    1925: @*/
    1926: PetscErrorCode  PCComputeExplicitOperator(PC pc,Mat *mat)
    1927: {
    1928:   Vec            in,out;
    1930:   PetscInt       i,M,m,*rows,start,end;
    1931:   PetscMPIInt    size;
    1932:   MPI_Comm       comm;
    1933:   PetscScalar    *array,one = 1.0;

    1939:   PetscObjectGetComm((PetscObject)pc,&comm);
    1940:   MPI_Comm_size(comm,&size);

    1942:   if (!pc->pmat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call");
    1943:   MatCreateVecs(pc->pmat,&in,0);
    1944:   VecDuplicate(in,&out);
    1945:   VecGetOwnershipRange(in,&start,&end);
    1946:   VecGetSize(in,&M);
    1947:   VecGetLocalSize(in,&m);
    1948:   PetscMalloc1(m+1,&rows);
    1949:   for (i=0; i<m; i++) rows[i] = start + i;

    1951:   MatCreate(comm,mat);
    1952:   MatSetSizes(*mat,m,m,M,M);
    1953:   if (size == 1) {
    1954:     MatSetType(*mat,MATSEQDENSE);
    1955:     MatSeqDenseSetPreallocation(*mat,NULL);
    1956:   } else {
    1957:     MatSetType(*mat,MATMPIAIJ);
    1958:     MatMPIAIJSetPreallocation(*mat,0,NULL,0,NULL);
    1959:   }
    1960:   MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);

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

    1964:     VecSet(in,0.0);
    1965:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
    1966:     VecAssemblyBegin(in);
    1967:     VecAssemblyEnd(in);

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

    1972:     VecGetArray(out,&array);
    1973:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
    1974:     VecRestoreArray(out,&array);

    1976:   }
    1977:   PetscFree(rows);
    1978:   VecDestroy(&out);
    1979:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
    1980:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
    1981:   return(0);
    1982: }

    1986: /*@
    1987:    PCSetCoordinates - sets the coordinates of all the nodes on the local process

    1989:    Collective on PC

    1991:    Input Parameters:
    1992: +  pc - the solver context
    1993: .  dim - the dimension of the coordinates 1, 2, or 3
    1994: -  coords - the coordinates

    1996:    Level: intermediate

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

    2006: .seealso: MatSetNearNullSpace
    2007: @*/
    2008: PetscErrorCode PCSetCoordinates(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
    2009: {

    2013:   PetscTryMethod(pc,"PCSetCoordinates_C",(PC,PetscInt,PetscInt,PetscReal*),(pc,dim,nloc,coords));
    2014:   return(0);
    2015: }