Date: 2013-07-02T14:46:33+00:00

Actual source code: jacobi.c
petsc-3.4.2 2013-07-02

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

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

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

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

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

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

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

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

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

     51: #include <petsc-private/pcimpl.h>   /*I "petscpc.h" I*/

     53: /*
     54:    Private context (data structure) for the Jacobi preconditioner.
     55: */
     56: typedef struct {
     57:   Vec diag;                      /* vector containing the reciprocals of the diagonal elements of the preconditioner matrix */
     58:   Vec diagsqrt;                  /* vector containing the reciprocals of the square roots of
     59:                                     the diagonal elements of the preconditioner matrix (used
     60:                                     only for symmetric preconditioner application) */
     61:   PetscBool userowmax;
     62:   PetscBool userowsum;
     63:   PetscBool useabs;              /* use the absolute values of the diagonal entries */
     64: } PC_Jacobi;

     68: static PetscErrorCode  PCJacobiSetUseRowMax_Jacobi(PC pc)
     69: {
     70:   PC_Jacobi *j;

     73:   j            = (PC_Jacobi*)pc->data;
     74:   j->userowmax = PETSC_TRUE;
     75:   return(0);
     76: }

     80: static PetscErrorCode  PCJacobiSetUseRowSum_Jacobi(PC pc)
     81: {
     82:   PC_Jacobi *j;

     85:   j            = (PC_Jacobi*)pc->data;
     86:   j->userowsum = PETSC_TRUE;
     87:   return(0);
     88: }

     92: static PetscErrorCode  PCJacobiSetUseAbs_Jacobi(PC pc)
     93: {
     94:   PC_Jacobi *j;

     97:   j         = (PC_Jacobi*)pc->data;
     98:   j->useabs = PETSC_TRUE;
     99:   return(0);
    100: }

    102: /* -------------------------------------------------------------------------- */
    103: /*
    104:    PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner
    105:                     by setting data structures and options.

    107:    Input Parameter:
    108: .  pc - the preconditioner context

    110:    Application Interface Routine: PCSetUp()

    112:    Notes:
    113:    The interface routine PCSetUp() is not usually called directly by
    114:    the user, but instead is called by PCApply() if necessary.
    115: */
    118: static PetscErrorCode PCSetUp_Jacobi(PC pc)
    119: {
    120:   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
    121:   Vec            diag,diagsqrt;
    123:   PetscInt       n,i;
    124:   PetscScalar    *x;
    125:   PetscBool      zeroflag = PETSC_FALSE;

    128:   /*
    129:        For most preconditioners the code would begin here something like

    131:   if (pc->setupcalled == 0) { allocate space the first time this is ever called
    132:     MatGetVecs(pc->mat,&jac->diag);
    133:     PetscLogObjectParent(pc,jac->diag);
    134:   }

    136:     But for this preconditioner we want to support use of both the matrix' diagonal
    137:     elements (for left or right preconditioning) and square root of diagonal elements
    138:     (for symmetric preconditioning).  Hence we do not allocate space here, since we
    139:     don't know at this point which will be needed (diag and/or diagsqrt) until the user
    140:     applies the preconditioner, and we don't want to allocate BOTH unless we need
    141:     them both.  Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric()
    142:     and PCSetUp_Jacobi_Symmetric(), respectively.
    143:   */

    145:   /*
    146:     Here we set up the preconditioner; that is, we copy the diagonal values from
    147:     the matrix and put them into a format to make them quick to apply as a preconditioner.
    148:   */
    149:   diag     = jac->diag;
    150:   diagsqrt = jac->diagsqrt;

    152:   if (diag) {
    153:     if (jac->userowmax) {
    154:       MatGetRowMaxAbs(pc->pmat,diag,NULL);
    155:     } else if (jac->userowsum) {
    156:       MatGetRowSum(pc->pmat,diag);
    157:     } else {
    158:       MatGetDiagonal(pc->pmat,diag);
    159:     }
    160:     VecReciprocal(diag);
    161:     VecGetLocalSize(diag,&n);
    162:     VecGetArray(diag,&x);
    163:     if (jac->useabs) {
    164:       for (i=0; i<n; i++) x[i] = PetscAbsScalar(x[i]);
    165:     }
    166:     for (i=0; i<n; i++) {
    167:       if (x[i] == 0.0) {
    168:         x[i]     = 1.0;
    169:         zeroflag = PETSC_TRUE;
    170:       }
    171:     }
    172:     VecRestoreArray(diag,&x);
    173:   }
    174:   if (diagsqrt) {
    175:     if (jac->userowmax) {
    176:       MatGetRowMaxAbs(pc->pmat,diagsqrt,NULL);
    177:     } else if (jac->userowsum) {
    178:       MatGetRowSum(pc->pmat,diagsqrt);
    179:     } else {
    180:       MatGetDiagonal(pc->pmat,diagsqrt);
    181:     }
    182:     VecGetLocalSize(diagsqrt,&n);
    183:     VecGetArray(diagsqrt,&x);
    184:     for (i=0; i<n; i++) {
    185:       if (x[i] != 0.0) x[i] = 1.0/PetscSqrtReal(PetscAbsScalar(x[i]));
    186:       else {
    187:         x[i]     = 1.0;
    188:         zeroflag = PETSC_TRUE;
    189:       }
    190:     }
    191:     VecRestoreArray(diagsqrt,&x);
    192:   }
    193:   if (zeroflag) {
    194:     PetscInfo(pc,"Zero detected in diagonal of matrix, using 1 at those locations\n");
    195:   }
    196:   return(0);
    197: }
    198: /* -------------------------------------------------------------------------- */
    199: /*
    200:    PCSetUp_Jacobi_Symmetric - Allocates the vector needed to store the
    201:    inverse of the square root of the diagonal entries of the matrix.  This
    202:    is used for symmetric application of the Jacobi preconditioner.

    204:    Input Parameter:
    205: .  pc - the preconditioner context
    206: */
    209: static PetscErrorCode PCSetUp_Jacobi_Symmetric(PC pc)
    210: {
    212:   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;

    215:   MatGetVecs(pc->pmat,&jac->diagsqrt,0);
    216:   PetscLogObjectParent(pc,jac->diagsqrt);
    217:   PCSetUp_Jacobi(pc);
    218:   return(0);
    219: }
    220: /* -------------------------------------------------------------------------- */
    221: /*
    222:    PCSetUp_Jacobi_NonSymmetric - Allocates the vector needed to store the
    223:    inverse of the diagonal entries of the matrix.  This is used for left of
    224:    right application of the Jacobi preconditioner.

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

    237:   MatGetVecs(pc->pmat,&jac->diag,0);
    238:   PetscLogObjectParent(pc,jac->diag);
    239:   PCSetUp_Jacobi(pc);
    240:   return(0);
    241: }
    242: /* -------------------------------------------------------------------------- */
    243: /*
    244:    PCApply_Jacobi - Applies the Jacobi preconditioner to a vector.

    246:    Input Parameters:
    247: .  pc - the preconditioner context
    248: .  x - input vector

    250:    Output Parameter:
    251: .  y - output vector

    253:    Application Interface Routine: PCApply()
    254:  */
    257: static PetscErrorCode PCApply_Jacobi(PC pc,Vec x,Vec y)
    258: {
    259:   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;

    263:   if (!jac->diag) {
    264:     PCSetUp_Jacobi_NonSymmetric(pc);
    265:   }
    266:   VecPointwiseMult(y,x,jac->diag);
    267:   return(0);
    268: }
    269: /* -------------------------------------------------------------------------- */
    270: /*
    271:    PCApplySymmetricLeftOrRight_Jacobi - Applies the left or right part of a
    272:    symmetric preconditioner to a vector.

    274:    Input Parameters:
    275: .  pc - the preconditioner context
    276: .  x - input vector

    278:    Output Parameter:
    279: .  y - output vector

    281:    Application Interface Routines: PCApplySymmetricLeft(), PCApplySymmetricRight()
    282: */
    285: static PetscErrorCode PCApplySymmetricLeftOrRight_Jacobi(PC pc,Vec x,Vec y)
    286: {
    288:   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;

    291:   if (!jac->diagsqrt) {
    292:     PCSetUp_Jacobi_Symmetric(pc);
    293:   }
    294:   VecPointwiseMult(y,x,jac->diagsqrt);
    295:   return(0);
    296: }
    297: /* -------------------------------------------------------------------------- */
    300: static PetscErrorCode PCReset_Jacobi(PC pc)
    301: {
    302:   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;

    306:   VecDestroy(&jac->diag);
    307:   VecDestroy(&jac->diagsqrt);
    308:   return(0);
    309: }

    311: /*
    312:    PCDestroy_Jacobi - Destroys the private context for the Jacobi preconditioner
    313:    that was created with PCCreate_Jacobi().

    315:    Input Parameter:
    316: .  pc - the preconditioner context

    318:    Application Interface Routine: PCDestroy()
    319: */
    322: static PetscErrorCode PCDestroy_Jacobi(PC pc)
    323: {

    327:   PCReset_Jacobi(pc);

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

    338: static PetscErrorCode PCSetFromOptions_Jacobi(PC pc)
    339: {
    340:   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;

    344:   PetscOptionsHead("Jacobi options");
    345:   PetscOptionsBool("-pc_jacobi_rowmax","Use row maximums for diagonal","PCJacobiSetUseRowMax",jac->userowmax,
    346:                           &jac->userowmax,NULL);
    347:   PetscOptionsBool("-pc_jacobi_rowsum","Use row sums for diagonal","PCJacobiSetUseRowSum",jac->userowsum,
    348:                           &jac->userowsum,NULL);
    349:   PetscOptionsBool("-pc_jacobi_abs","Use absolute values of diagaonal entries","PCJacobiSetUseAbs",jac->useabs,
    350:                           &jac->useabs,NULL);
    351:   PetscOptionsTail();
    352:   return(0);
    353: }

    355: /* -------------------------------------------------------------------------- */
    356: /*
    357:    PCCreate_Jacobi - Creates a Jacobi preconditioner context, PC_Jacobi,
    358:    and sets this as the private data within the generic preconditioning
    359:    context, PC, that was created within PCCreate().

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

    364:    Application Interface Routine: PCCreate()
    365: */

    367: /*MC
    368:      PCJACOBI - Jacobi (i.e. diagonal scaling preconditioning)

    370:    Options Database Key:
    371: +    -pc_jacobi_rowmax - use the maximum absolute value in each row as the scaling factor,
    372:                         rather than the diagonal
    373: .    -pc_jacobi_rowsum - use the row sums as the scaling factor,
    374:                         rather than the diagonal
    375: -    -pc_jacobi_abs - use the absolute value of the diagaonl entry

    377:    Level: beginner

    379:   Concepts: Jacobi, diagonal scaling, preconditioners

    381:   Notes: By using KSPSetPCSide(ksp,PC_SYMMETRIC) or -ksp_pc_side symmetric
    382:          can scale each side of the matrix by the squareroot of the diagonal entries.

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

    386: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
    387:            PCJacobiSetUseRowMax(), PCJacobiSetUseRowSum(), PCJacobiSetUseAbs()
    388: M*/

    392: PETSC_EXTERN PetscErrorCode PCCreate_Jacobi(PC pc)
    393: {
    394:   PC_Jacobi      *jac;

    398:   /*
    399:      Creates the private data structure for this preconditioner and
    400:      attach it to the PC object.
    401:   */
    402:   PetscNewLog(pc,PC_Jacobi,&jac);
    403:   pc->data = (void*)jac;

    405:   /*
    406:      Initialize the pointers to vectors to ZERO; these will be used to store
    407:      diagonal entries of the matrix for fast preconditioner application.
    408:   */
    409:   jac->diag      = 0;
    410:   jac->diagsqrt  = 0;
    411:   jac->userowmax = PETSC_FALSE;
    412:   jac->userowsum = PETSC_FALSE;
    413:   jac->useabs    = PETSC_FALSE;

    415:   /*
    416:       Set the pointers for the functions that are provided above.
    417:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
    418:       are called, they will automatically call these functions.  Note we
    419:       choose not to provide a couple of these functions since they are
    420:       not needed.
    421:   */
    422:   pc->ops->apply               = PCApply_Jacobi;
    423:   pc->ops->applytranspose      = PCApply_Jacobi;
    424:   pc->ops->setup               = PCSetUp_Jacobi;
    425:   pc->ops->reset               = PCReset_Jacobi;
    426:   pc->ops->destroy             = PCDestroy_Jacobi;
    427:   pc->ops->setfromoptions      = PCSetFromOptions_Jacobi;
    428:   pc->ops->view                = 0;
    429:   pc->ops->applyrichardson     = 0;
    430:   pc->ops->applysymmetricleft  = PCApplySymmetricLeftOrRight_Jacobi;
    431:   pc->ops->applysymmetricright = PCApplySymmetricLeftOrRight_Jacobi;

    433:   PetscObjectComposeFunction((PetscObject)pc,"PCJacobiSetUseRowMax_C",PCJacobiSetUseRowMax_Jacobi);
    434:   PetscObjectComposeFunction((PetscObject)pc,"PCJacobiSetUseRowSum_C",PCJacobiSetUseRowSum_Jacobi);
    435:   PetscObjectComposeFunction((PetscObject)pc,"PCJacobiSetUseAbs_C",PCJacobiSetUseAbs_Jacobi);
    436:   return(0);
    437: }

    441: /*@
    442:    PCJacobiSetUseAbs - Causes the Jacobi preconditioner to use the
    443:       absolute value of the diagonal to for the preconditioner

    445:    Logically Collective on PC

    447:    Input Parameters:
    448: .  pc - the preconditioner context

    451:    Options Database Key:
    452: .  -pc_jacobi_abs

    454:    Level: intermediate

    456:    Concepts: Jacobi preconditioner

    458: .seealso: PCJacobiaUseRowMax(), PCJacobiaUseRowSum()

    460: @*/
    461: PetscErrorCode  PCJacobiSetUseAbs(PC pc)
    462: {

    467:   PetscTryMethod(pc,"PCJacobiSetUseAbs_C",(PC),(pc));
    468:   return(0);
    469: }

    473: /*@
    474:    PCJacobiSetUseRowMax - Causes the Jacobi preconditioner to use the
    475:       maximum entry in each row as the diagonal preconditioner, instead of
    476:       the diagonal entry

    478:    Logically Collective on PC

    480:    Input Parameters:
    481: .  pc - the preconditioner context

    484:    Options Database Key:
    485: .  -pc_jacobi_rowmax

    487:    Level: intermediate

    489:    Concepts: Jacobi preconditioner

    491: .seealso: PCJacobiaUseAbs()
    492: @*/
    493: PetscErrorCode  PCJacobiSetUseRowMax(PC pc)
    494: {

    499:   PetscTryMethod(pc,"PCJacobiSetUseRowMax_C",(PC),(pc));
    500:   return(0);
    501: }

    505: /*@
    506:    PCJacobiSetUseRowSum - Causes the Jacobi preconditioner to use the
    507:       sum of each row as the diagonal preconditioner, instead of
    508:       the diagonal entry

    510:    Logical Collective on PC

    512:    Input Parameters:
    513: .  pc - the preconditioner context

    516:    Options Database Key:
    517: .  -pc_jacobi_rowsum

    519:    Level: intermediate

    521:    Concepts: Jacobi preconditioner

    523: .seealso: PCJacobiaUseAbs(), PCJacobiaUseRowSum()
    524: @*/
    525: PetscErrorCode  PCJacobiSetUseRowSum(PC pc)
    526: {

    531:   PetscTryMethod(pc,"PCJacobiSetUseRowSum_C",(PC),(pc));
    532:   return(0);
    533: }