Actual source code: shellpc.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      2: /*
      3:    This provides a simple shell for Fortran (and C programmers) to
      4:   create their own preconditioner without writing much interface code.
      5: */

      7: #include <petsc/private/pcimpl.h>        /*I "petscpc.h" I*/
      8: #include <petsc/private/vecimpl.h>

     10: typedef struct {
     11:   void *ctx;                     /* user provided contexts for preconditioner */

     13:   PetscErrorCode (*destroy)(PC);
     14:   PetscErrorCode (*setup)(PC);
     15:   PetscErrorCode (*apply)(PC,Vec,Vec);
     16:   PetscErrorCode (*applysymmetricleft)(PC,Vec,Vec);
     17:   PetscErrorCode (*applysymmetricright)(PC,Vec,Vec);
     18:   PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec);
     19:   PetscErrorCode (*presolve)(PC,KSP,Vec,Vec);
     20:   PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec);
     21:   PetscErrorCode (*view)(PC,PetscViewer);
     22:   PetscErrorCode (*applytranspose)(PC,Vec,Vec);
     23:   PetscErrorCode (*applyrich)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*);

     25:   char *name;
     26: } PC_Shell;

     30: /*@C
     31:     PCShellGetContext - Returns the user-provided context associated with a shell PC

     33:     Not Collective

     35:     Input Parameter:
     36: .   pc - should have been created with PCSetType(pc,shell)

     38:     Output Parameter:
     39: .   ctx - the user provided context

     41:     Level: advanced

     43:     Notes:
     44:     This routine is intended for use within various shell routines

     46:    Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
     47:     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.

     49: .keywords: PC, shell, get, context

     51: .seealso: PCShellSetContext()
     52: @*/
     53: PetscErrorCode  PCShellGetContext(PC pc,void **ctx)
     54: {
     56:   PetscBool      flg;

     61:   PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&flg);
     62:   if (!flg) *ctx = 0;
     63:   else      *ctx = ((PC_Shell*)(pc->data))->ctx;
     64:   return(0);
     65: }

     69: /*@
     70:     PCShellSetContext - sets the context for a shell PC

     72:    Logically Collective on PC

     74:     Input Parameters:
     75: +   pc - the shell PC
     76: -   ctx - the context

     78:    Level: advanced

     80:    Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
     81:     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.

     85: .seealso: PCShellGetContext(), PCSHELL
     86: @*/
     87: PetscErrorCode  PCShellSetContext(PC pc,void *ctx)
     88: {
     89:   PC_Shell       *shell = (PC_Shell*)pc->data;
     91:   PetscBool      flg;

     95:   PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&flg);
     96:   if (flg) shell->ctx = ctx;
     97:   return(0);
     98: }

    102: static PetscErrorCode PCSetUp_Shell(PC pc)
    103: {
    104:   PC_Shell       *shell = (PC_Shell*)pc->data;

    108:   if (!shell->setup) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No setup() routine provided to Shell PC");
    109:   PetscStackCall("PCSHELL user function setup()",(*shell->setup)(pc);CHKERRQ(ierr));
    110:   return(0);
    111: }

    115: static PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y)
    116: {
    117:   PC_Shell         *shell = (PC_Shell*)pc->data;
    118:   PetscErrorCode   ierr;
    119:   PetscObjectState instate,outstate;

    122:   if (!shell->apply) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No apply() routine provided to Shell PC");
    123:   PetscObjectStateGet((PetscObject)y, &instate);
    124:   PetscStackCall("PCSHELL user function apply()",(*shell->apply)(pc,x,y);CHKERRQ(ierr));
    125:   PetscObjectStateGet((PetscObject)y, &outstate);
    126:   if (instate == outstate) {
    127:     /* increase the state of the output vector since the user did not update its state themselve as should have been done */
    128:     PetscObjectStateIncrease((PetscObject)y);
    129:   }
    130:   return(0);
    131: }

    135: static PetscErrorCode PCApplySymmetricLeft_Shell(PC pc,Vec x,Vec y)
    136: {
    137:   PC_Shell       *shell = (PC_Shell*)pc->data;

    141:   if (!shell->applysymmetricleft) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No apply() routine provided to Shell PC");
    142:   PetscStackCall("PCSHELL user function apply()",(*shell->applysymmetricleft)(pc,x,y);CHKERRQ(ierr));
    143:   return(0);
    144: }

    148: static PetscErrorCode PCApplySymmetricRight_Shell(PC pc,Vec x,Vec y)
    149: {
    150:   PC_Shell       *shell = (PC_Shell*)pc->data;

    154:   if (!shell->applysymmetricright) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No apply() routine provided to Shell PC");
    155:   PetscStackCall("PCSHELL user function apply()",(*shell->applysymmetricright)(pc,x,y);CHKERRQ(ierr));
    156:   return(0);
    157: }

    161: static PetscErrorCode PCApplyBA_Shell(PC pc,PCSide side,Vec x,Vec y,Vec w)
    162: {
    163:   PC_Shell         *shell = (PC_Shell*)pc->data;
    164:   PetscErrorCode   ierr;
    165:   PetscObjectState instate,outstate;

    168:   if (!shell->applyBA) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applyBA() routine provided to Shell PC");
    169:   PetscObjectStateGet((PetscObject)w, &instate);
    170:   PetscStackCall("PCSHELL user function applyBA()",(*shell->applyBA)(pc,side,x,y,w);CHKERRQ(ierr));
    171:   PetscObjectStateGet((PetscObject)w, &outstate);
    172:   if (instate == outstate) {
    173:     /* increase the state of the output vector since the user did not update its state themselve as should have been done */
    174:     PetscObjectStateIncrease((PetscObject)w);
    175:   }
    176:   return(0);
    177: }

    181: static PetscErrorCode PCPreSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
    182: {
    183:   PC_Shell       *shell = (PC_Shell*)pc->data;

    187:   if (!shell->presolve) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No presolve() routine provided to Shell PC");
    188:   PetscStackCall("PCSHELL user function presolve()",(*shell->presolve)(pc,ksp,b,x);CHKERRQ(ierr));
    189:   return(0);
    190: }

    194: static PetscErrorCode PCPostSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
    195: {
    196:   PC_Shell       *shell = (PC_Shell*)pc->data;

    200:   if (!shell->postsolve) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No postsolve() routine provided to Shell PC");
    201:   PetscStackCall("PCSHELL user function postsolve()",(*shell->postsolve)(pc,ksp,b,x);CHKERRQ(ierr));
    202:   return(0);
    203: }

    207: static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
    208: {
    209:   PC_Shell         *shell = (PC_Shell*)pc->data;
    210:   PetscErrorCode   ierr;
    211:   PetscObjectState instate,outstate;

    214:   if (!shell->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC");
    215:   PetscObjectStateGet((PetscObject)y, &instate);
    216:   PetscStackCall("PCSHELL user function applytranspose()",(*shell->applytranspose)(pc,x,y);CHKERRQ(ierr));
    217:   PetscObjectStateGet((PetscObject)y, &outstate);
    218:   if (instate == outstate) {
    219:     /* increase the state of the output vector since the user did not update its state themself as should have been done */
    220:     PetscObjectStateIncrease((PetscObject)y);
    221:   }
    222:   return(0);
    223: }

    227: static PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
    228: {
    229:   PetscErrorCode   ierr;
    230:   PC_Shell         *shell = (PC_Shell*)pc->data;
    231:   PetscObjectState instate,outstate;

    234:   if (!shell->applyrich) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applyrichardson() routine provided to Shell PC");
    235:   PetscObjectStateGet((PetscObject)y, &instate);
    236:   PetscStackCall("PCSHELL user function applyrichardson()",(*shell->applyrich)(pc,x,y,w,rtol,abstol,dtol,it,guesszero,outits,reason);CHKERRQ(ierr));
    237:   PetscObjectStateGet((PetscObject)y, &outstate);
    238:   if (instate == outstate) {
    239:     /* increase the state of the output vector since the user did not update its state themself as should have been done */
    240:     PetscObjectStateIncrease((PetscObject)y);
    241:   }
    242:   return(0);
    243: }

    247: static PetscErrorCode PCDestroy_Shell(PC pc)
    248: {
    249:   PC_Shell       *shell = (PC_Shell*)pc->data;

    253:   PetscFree(shell->name);
    254:   if (shell->destroy) PetscStackCall("PCSHELL user function destroy()",(*shell->destroy)(pc);CHKERRQ(ierr));
    255:   PetscFree(pc->data);
    256:   return(0);
    257: }

    261: static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer)
    262: {
    263:   PC_Shell       *shell = (PC_Shell*)pc->data;
    265:   PetscBool      iascii;

    268:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    269:   if (iascii) {
    270:     if (shell->name) {
    271:       PetscViewerASCIIPrintf(viewer,"  Shell: %s\n",shell->name);
    272:     } else {
    273:       PetscViewerASCIIPrintf(viewer,"  Shell: no name\n");
    274:     }
    275:   }
    276:   if (shell->view) {
    277:     PetscViewerASCIIPushTab(viewer);
    278:     (*shell->view)(pc,viewer);
    279:     PetscViewerASCIIPopTab(viewer);
    280:   }
    281:   return(0);
    282: }

    284: /* ------------------------------------------------------------------------------*/
    287: static PetscErrorCode  PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(PC))
    288: {
    289:   PC_Shell *shell= (PC_Shell*)pc->data;

    292:   shell->destroy = destroy;
    293:   return(0);
    294: }

    298: static PetscErrorCode  PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(PC))
    299: {
    300:   PC_Shell *shell = (PC_Shell*)pc->data;;

    303:   shell->setup = setup;
    304:   if (setup) pc->ops->setup = PCSetUp_Shell;
    305:   else       pc->ops->setup = 0;
    306:   return(0);
    307: }

    311: static PetscErrorCode  PCShellSetApply_Shell(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
    312: {
    313:   PC_Shell *shell = (PC_Shell*)pc->data;

    316:   shell->apply = apply;
    317:   return(0);
    318: }

    322: static PetscErrorCode  PCShellSetApplySymmetricLeft_Shell(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
    323: {
    324:   PC_Shell *shell = (PC_Shell*)pc->data;

    327:   shell->applysymmetricleft = apply;
    328:   return(0);
    329: }

    333: static PetscErrorCode  PCShellSetApplySymmetricRight_Shell(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
    334: {
    335:   PC_Shell *shell = (PC_Shell*)pc->data;

    338:   shell->applysymmetricright = apply;
    339:   return(0);
    340: }

    344: static PetscErrorCode  PCShellSetApplyBA_Shell(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec))
    345: {
    346:   PC_Shell *shell = (PC_Shell*)pc->data;

    349:   shell->applyBA = applyBA;
    350:   if (applyBA) pc->ops->applyBA  = PCApplyBA_Shell;
    351:   else         pc->ops->applyBA  = 0;
    352:   return(0);
    353: }

    357: static PetscErrorCode  PCShellSetPreSolve_Shell(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec))
    358: {
    359:   PC_Shell *shell = (PC_Shell*)pc->data;

    362:   shell->presolve = presolve;
    363:   if (presolve) pc->ops->presolve = PCPreSolve_Shell;
    364:   else          pc->ops->presolve = 0;
    365:   return(0);
    366: }

    370: static PetscErrorCode  PCShellSetPostSolve_Shell(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec))
    371: {
    372:   PC_Shell *shell = (PC_Shell*)pc->data;

    375:   shell->postsolve = postsolve;
    376:   if (postsolve) pc->ops->postsolve = PCPostSolve_Shell;
    377:   else           pc->ops->postsolve = 0;
    378:   return(0);
    379: }

    383: static PetscErrorCode  PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(PC,PetscViewer))
    384: {
    385:   PC_Shell *shell = (PC_Shell*)pc->data;

    388:   shell->view = view;
    389:   return(0);
    390: }

    394: static PetscErrorCode  PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec))
    395: {
    396:   PC_Shell *shell = (PC_Shell*)pc->data;

    399:   shell->applytranspose = applytranspose;
    400:   if (applytranspose) pc->ops->applytranspose = PCApplyTranspose_Shell;
    401:   else                pc->ops->applytranspose = 0;
    402:   return(0);
    403: }

    407: static PetscErrorCode  PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*applyrich)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool ,PetscInt*,PCRichardsonConvergedReason*))
    408: {
    409:   PC_Shell *shell = (PC_Shell*)pc->data;

    412:   shell->applyrich = applyrich;
    413:   if (applyrich) pc->ops->applyrichardson = PCApplyRichardson_Shell;
    414:   else           pc->ops->applyrichardson = 0;
    415:   return(0);
    416: }

    420: static PetscErrorCode  PCShellSetName_Shell(PC pc,const char name[])
    421: {
    422:   PC_Shell       *shell = (PC_Shell*)pc->data;

    426:   PetscFree(shell->name);
    427:   PetscStrallocpy(name,&shell->name);
    428:   return(0);
    429: }

    433: static PetscErrorCode  PCShellGetName_Shell(PC pc,const char *name[])
    434: {
    435:   PC_Shell *shell = (PC_Shell*)pc->data;

    438:   *name = shell->name;
    439:   return(0);
    440: }

    442: /* -------------------------------------------------------------------------------*/

    446: /*@C
    447:    PCShellSetDestroy - Sets routine to use to destroy the user-provided
    448:    application context.

    450:    Logically Collective on PC

    452:    Input Parameters:
    453: +  pc - the preconditioner context
    454: .  destroy - the application-provided destroy routine

    456:    Calling sequence of destroy:
    457: .vb
    458:    PetscErrorCode destroy (PC)
    459: .ve

    461: .  ptr - the application context

    463:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    465:    Level: developer

    467: .keywords: PC, shell, set, destroy, user-provided

    469: .seealso: PCShellSetApply(), PCShellSetContext()
    470: @*/
    471: PetscErrorCode  PCShellSetDestroy(PC pc,PetscErrorCode (*destroy)(PC))
    472: {

    477:   PetscTryMethod(pc,"PCShellSetDestroy_C",(PC,PetscErrorCode (*)(PC)),(pc,destroy));
    478:   return(0);
    479: }

    484: /*@C
    485:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
    486:    matrix operator is changed.

    488:    Logically Collective on PC

    490:    Input Parameters:
    491: +  pc - the preconditioner context
    492: .  setup - the application-provided setup routine

    494:    Calling sequence of setup:
    495: .vb
    496:    PetscErrorCode setup (PC pc)
    497: .ve

    499: .  pc - the preconditioner, get the application context with PCShellGetContext()

    501:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    503:    Level: developer

    505: .keywords: PC, shell, set, setup, user-provided

    507: .seealso: PCShellSetApplyRichardson(), PCShellSetApply(), PCShellSetContext()
    508: @*/
    509: PetscErrorCode  PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(PC))
    510: {

    515:   PetscTryMethod(pc,"PCShellSetSetUp_C",(PC,PetscErrorCode (*)(PC)),(pc,setup));
    516:   return(0);
    517: }

    522: /*@C
    523:    PCShellSetView - Sets routine to use as viewer of shell preconditioner

    525:    Logically Collective on PC

    527:    Input Parameters:
    528: +  pc - the preconditioner context
    529: -  view - the application-provided view routine

    531:    Calling sequence of apply:
    532: .vb
    533:    PetscErrorCode view(PC pc,PetscViewer v)
    534: .ve

    536: +  pc - the preconditioner, get the application context with PCShellGetContext()
    537: -  v   - viewer

    539:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    541:    Level: developer

    543: .keywords: PC, shell, set, apply, user-provided

    545: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
    546: @*/
    547: PetscErrorCode  PCShellSetView(PC pc,PetscErrorCode (*view)(PC,PetscViewer))
    548: {

    553:   PetscTryMethod(pc,"PCShellSetView_C",(PC,PetscErrorCode (*)(PC,PetscViewer)),(pc,view));
    554:   return(0);
    555: }

    559: /*@C
    560:    PCShellSetApply - Sets routine to use as preconditioner.

    562:    Logically Collective on PC

    564:    Input Parameters:
    565: +  pc - the preconditioner context
    566: -  apply - the application-provided preconditioning routine

    568:    Calling sequence of apply:
    569: .vb
    570:    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
    571: .ve

    573: +  pc - the preconditioner, get the application context with PCShellGetContext()
    574: .  xin - input vector
    575: -  xout - output vector

    577:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    579:    Developer Notes: There should also be a PCShellSetApplySymmetricRight() and PCShellSetApplySymmetricLeft().

    581:    Level: developer

    583: .keywords: PC, shell, set, apply, user-provided

    585: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApplyBA()
    586: @*/
    587: PetscErrorCode  PCShellSetApply(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
    588: {

    593:   PetscTryMethod(pc,"PCShellSetApply_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));
    594:   return(0);
    595: }

    599: /*@C
    600:    PCShellSetApplySymmetricLeft - Sets routine to use as left preconditioner (when the PC_SYMMETRIC is used).

    602:    Logically Collective on PC

    604:    Input Parameters:
    605: +  pc - the preconditioner context
    606: -  apply - the application-provided left preconditioning routine

    608:    Calling sequence of apply:
    609: .vb
    610:    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
    611: .ve

    613: +  pc - the preconditioner, get the application context with PCShellGetContext()
    614: .  xin - input vector
    615: -  xout - output vector

    617:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    619:    Level: developer

    621: .keywords: PC, shell, set, apply, user-provided

    623: .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
    624: @*/
    625: PetscErrorCode  PCShellSetApplySymmetricLeft(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
    626: {

    631:   PetscTryMethod(pc,"PCShellSetApplySymmetricLeft_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));
    632:   return(0);
    633: }

    637: /*@C
    638:    PCShellSetApply - Sets routine to use as right preconditioner (when the PC_SYMMETRIC is used).

    640:    Logically Collective on PC

    642:    Input Parameters:
    643: +  pc - the preconditioner context
    644: -  apply - the application-provided right preconditioning routine

    646:    Calling sequence of apply:
    647: .vb
    648:    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
    649: .ve

    651: +  pc - the preconditioner, get the application context with PCShellGetContext()
    652: .  xin - input vector
    653: -  xout - output vector

    655:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    657:    Level: developer

    659: .keywords: PC, shell, set, apply, user-provided

    661: .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
    662: @*/
    663: PetscErrorCode  PCShellSetApplySymmetricRight(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
    664: {

    669:   PetscTryMethod(pc,"PCShellSetApplySymmetricRight_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));
    670:   return(0);
    671: }

    675: /*@C
    676:    PCShellSetApplyBA - Sets routine to use as preconditioner times operator.

    678:    Logically Collective on PC

    680:    Input Parameters:
    681: +  pc - the preconditioner context
    682: -  applyBA - the application-provided BA routine

    684:    Calling sequence of apply:
    685: .vb
    686:    PetscErrorCode applyBA (PC pc,Vec xin,Vec xout)
    687: .ve

    689: +  pc - the preconditioner, get the application context with PCShellGetContext()
    690: .  xin - input vector
    691: -  xout - output vector

    693:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    695:    Level: developer

    697: .keywords: PC, shell, set, apply, user-provided

    699: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApply()
    700: @*/
    701: PetscErrorCode  PCShellSetApplyBA(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec))
    702: {

    707:   PetscTryMethod(pc,"PCShellSetApplyBA_C",(PC,PetscErrorCode (*)(PC,PCSide,Vec,Vec,Vec)),(pc,applyBA));
    708:   return(0);
    709: }

    713: /*@C
    714:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

    716:    Logically Collective on PC

    718:    Input Parameters:
    719: +  pc - the preconditioner context
    720: -  apply - the application-provided preconditioning transpose routine

    722:    Calling sequence of apply:
    723: .vb
    724:    PetscErrorCode applytranspose (PC pc,Vec xin,Vec xout)
    725: .ve

    727: +  pc - the preconditioner, get the application context with PCShellGetContext()
    728: .  xin - input vector
    729: -  xout - output vector

    731:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    733:    Level: developer

    735:    Notes:
    736:    Uses the same context variable as PCShellSetApply().

    738: .keywords: PC, shell, set, apply, user-provided

    740: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext(), PCShellSetApplyBA()
    741: @*/
    742: PetscErrorCode  PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec))
    743: {

    748:   PetscTryMethod(pc,"PCShellSetApplyTranspose_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,applytranspose));
    749:   return(0);
    750: }

    754: /*@C
    755:    PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is
    756:       applied. This usually does something like scale the linear system in some application
    757:       specific way.

    759:    Logically Collective on PC

    761:    Input Parameters:
    762: +  pc - the preconditioner context
    763: -  presolve - the application-provided presolve routine

    765:    Calling sequence of presolve:
    766: .vb
    767:    PetscErrorCode presolve (PC,KSP ksp,Vec b,Vec x)
    768: .ve

    770: +  pc - the preconditioner, get the application context with PCShellGetContext()
    771: .  xin - input vector
    772: -  xout - output vector

    774:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    776:    Level: developer

    778: .keywords: PC, shell, set, apply, user-provided

    780: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext()
    781: @*/
    782: PetscErrorCode  PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec))
    783: {

    788:   PetscTryMethod(pc,"PCShellSetPreSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,presolve));
    789:   return(0);
    790: }

    794: /*@C
    795:    PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is
    796:       applied. This usually does something like scale the linear system in some application
    797:       specific way.

    799:    Logically Collective on PC

    801:    Input Parameters:
    802: +  pc - the preconditioner context
    803: -  postsolve - the application-provided presolve routine

    805:    Calling sequence of postsolve:
    806: .vb
    807:    PetscErrorCode postsolve(PC,KSP ksp,Vec b,Vec x)
    808: .ve

    810: +  pc - the preconditioner, get the application context with PCShellGetContext()
    811: .  xin - input vector
    812: -  xout - output vector

    814:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    816:    Level: developer

    818: .keywords: PC, shell, set, apply, user-provided

    820: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext()
    821: @*/
    822: PetscErrorCode  PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec))
    823: {

    828:   PetscTryMethod(pc,"PCShellSetPostSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,postsolve));
    829:   return(0);
    830: }

    834: /*@C
    835:    PCShellSetName - Sets an optional name to associate with a shell
    836:    preconditioner.

    838:    Not Collective

    840:    Input Parameters:
    841: +  pc - the preconditioner context
    842: -  name - character string describing shell preconditioner

    844:    Level: developer

    846: .keywords: PC, shell, set, name, user-provided

    848: .seealso: PCShellGetName()
    849: @*/
    850: PetscErrorCode  PCShellSetName(PC pc,const char name[])
    851: {

    856:   PetscTryMethod(pc,"PCShellSetName_C",(PC,const char []),(pc,name));
    857:   return(0);
    858: }

    862: /*@C
    863:    PCShellGetName - Gets an optional name that the user has set for a shell
    864:    preconditioner.

    866:    Not Collective

    868:    Input Parameter:
    869: .  pc - the preconditioner context

    871:    Output Parameter:
    872: .  name - character string describing shell preconditioner (you should not free this)

    874:    Level: developer

    876: .keywords: PC, shell, get, name, user-provided

    878: .seealso: PCShellSetName()
    879: @*/
    880: PetscErrorCode  PCShellGetName(PC pc,const char *name[])
    881: {

    887:   PetscUseMethod(pc,"PCShellGetName_C",(PC,const char*[]),(pc,name));
    888:   return(0);
    889: }

    893: /*@C
    894:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
    895:    in Richardson iteration.

    897:    Logically Collective on PC

    899:    Input Parameters:
    900: +  pc - the preconditioner context
    901: -  apply - the application-provided preconditioning routine

    903:    Calling sequence of apply:
    904: .vb
    905:    PetscErrorCode apply (PC pc,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits)
    906: .ve

    908: +  pc - the preconditioner, get the application context with PCShellGetContext()
    909: .  b - right-hand-side
    910: .  x - current iterate
    911: .  r - work space
    912: .  rtol - relative tolerance of residual norm to stop at
    913: .  abstol - absolute tolerance of residual norm to stop at
    914: .  dtol - if residual norm increases by this factor than return
    915: -  maxits - number of iterations to run

    917:    Notes: the function MUST return an error code of 0 on success and nonzero on failure.

    919:    Level: developer

    921: .keywords: PC, shell, set, apply, Richardson, user-provided

    923: .seealso: PCShellSetApply(), PCShellSetContext()
    924: @*/
    925: PetscErrorCode  PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*))
    926: {

    931:   PetscTryMethod(pc,"PCShellSetApplyRichardson_C",(PC,PetscErrorCode (*)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)),(pc,apply));
    932:   return(0);
    933: }

    935: /*MC
    936:    PCSHELL - Creates a new preconditioner class for use with your
    937:               own private data storage format.

    939:    Level: advanced
    940: >
    941:    Concepts: providing your own preconditioner

    943:   Usage:
    944: $             extern PetscErrorCode apply(PC,Vec,Vec);
    945: $             extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec);
    946: $             extern PetscErrorCode applytranspose(PC,Vec,Vec);
    947: $             extern PetscErrorCode setup(PC);
    948: $             extern PetscErrorCode destroy(PC);
    949: $
    950: $             PCCreate(comm,&pc);
    951: $             PCSetType(pc,PCSHELL);
    952: $             PCShellSetContext(pc,ctx)
    953: $             PCShellSetApply(pc,apply);
    954: $             PCShellSetApplyBA(pc,applyba);               (optional)
    955: $             PCShellSetApplyTranspose(pc,applytranspose); (optional)
    956: $             PCShellSetSetUp(pc,setup);                   (optional)
    957: $             PCShellSetDestroy(pc,destroy);               (optional)

    959: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
    960:            MATSHELL, PCShellSetSetUp(), PCShellSetApply(), PCShellSetView(),
    961:            PCShellSetApplyTranspose(), PCShellSetName(), PCShellSetApplyRichardson(),
    962:            PCShellGetName(), PCShellSetContext(), PCShellGetContext(), PCShellSetApplyBA()
    963: M*/

    967: PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc)
    968: {
    970:   PC_Shell       *shell;

    973:   PetscNewLog(pc,&shell);
    974:   pc->data = (void*)shell;

    976:   pc->ops->destroy         = PCDestroy_Shell;
    977:   pc->ops->view            = PCView_Shell;
    978:   pc->ops->apply           = PCApply_Shell;
    979:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_Shell;
    980:   pc->ops->applysymmetricright = PCApplySymmetricRight_Shell;
    981:   pc->ops->applytranspose  = 0;
    982:   pc->ops->applyrichardson = 0;
    983:   pc->ops->setup           = 0;
    984:   pc->ops->presolve        = 0;
    985:   pc->ops->postsolve       = 0;

    987:   shell->apply          = 0;
    988:   shell->applytranspose = 0;
    989:   shell->name           = 0;
    990:   shell->applyrich      = 0;
    991:   shell->presolve       = 0;
    992:   shell->postsolve      = 0;
    993:   shell->ctx            = 0;
    994:   shell->setup          = 0;
    995:   shell->view           = 0;
    996:   shell->destroy        = 0;
    997:   shell->applysymmetricleft  = 0;
    998:   shell->applysymmetricright = 0;

    1000:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetDestroy_C",PCShellSetDestroy_Shell);
    1001:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetSetUp_C",PCShellSetSetUp_Shell);
    1002:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApply_C",PCShellSetApply_Shell);
    1003:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricLeft_C",PCShellSetApplySymmetricLeft_Shell);
    1004:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricRight_C",PCShellSetApplySymmetricRight_Shell);
    1005:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyBA_C",PCShellSetApplyBA_Shell);
    1006:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPreSolve_C",PCShellSetPreSolve_Shell);
    1007:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPostSolve_C",PCShellSetPostSolve_Shell);
    1008:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetView_C",PCShellSetView_Shell);
    1009:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",PCShellSetApplyTranspose_Shell);
    1010:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetName_C",PCShellSetName_Shell);
    1011:   PetscObjectComposeFunction((PetscObject)pc,"PCShellGetName_C",PCShellGetName_Shell);
    1012:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",PCShellSetApplyRichardson_Shell);
    1013:   return(0);
    1014: }