Actual source code: shellpc.c

petsc-3.7.7 2017-09-25
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 PCPreSolveChangeRHS_Shell(PC pc,PetscBool* change)
182: {
184:   *change = PETSC_TRUE;
185:   return(0);
186: }

190: static PetscErrorCode PCPreSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
191: {
192:   PC_Shell       *shell = (PC_Shell*)pc->data;

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

203: static PetscErrorCode PCPostSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
204: {
205:   PC_Shell       *shell = (PC_Shell*)pc->data;

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

216: static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
217: {
218:   PC_Shell         *shell = (PC_Shell*)pc->data;
219:   PetscErrorCode   ierr;
220:   PetscObjectState instate,outstate;

223:   if (!shell->applytranspose) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC");
224:   PetscObjectStateGet((PetscObject)y, &instate);
225:   PetscStackCall("PCSHELL user function applytranspose()",(*shell->applytranspose)(pc,x,y);CHKERRQ(ierr));
226:   PetscObjectStateGet((PetscObject)y, &outstate);
227:   if (instate == outstate) {
228:     /* increase the state of the output vector since the user did not update its state themself as should have been done */
229:     PetscObjectStateIncrease((PetscObject)y);
230:   }
231:   return(0);
232: }

236: 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)
237: {
238:   PetscErrorCode   ierr;
239:   PC_Shell         *shell = (PC_Shell*)pc->data;
240:   PetscObjectState instate,outstate;

243:   if (!shell->applyrich) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"No applyrichardson() routine provided to Shell PC");
244:   PetscObjectStateGet((PetscObject)y, &instate);
245:   PetscStackCall("PCSHELL user function applyrichardson()",(*shell->applyrich)(pc,x,y,w,rtol,abstol,dtol,it,guesszero,outits,reason);CHKERRQ(ierr));
246:   PetscObjectStateGet((PetscObject)y, &outstate);
247:   if (instate == outstate) {
248:     /* increase the state of the output vector since the user did not update its state themself as should have been done */
249:     PetscObjectStateIncrease((PetscObject)y);
250:   }
251:   return(0);
252: }

256: static PetscErrorCode PCDestroy_Shell(PC pc)
257: {
258:   PC_Shell       *shell = (PC_Shell*)pc->data;

262:   PetscFree(shell->name);
263:   if (shell->destroy) PetscStackCall("PCSHELL user function destroy()",(*shell->destroy)(pc);CHKERRQ(ierr));
264:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetDestroy_C",NULL);
265:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetSetUp_C",NULL);
266:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApply_C",NULL);
267:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricLeft_C",NULL);
268:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricRight_C",NULL);
269:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyBA_C",NULL);
270:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPreSolve_C",NULL);
271:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPostSolve_C",NULL);
272:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetView_C",NULL);
273:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",NULL);
274:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetName_C",NULL);
275:   PetscObjectComposeFunction((PetscObject)pc,"PCShellGetName_C",NULL);
276:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",NULL);
277:   PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);
278:   PetscFree(pc->data);
279:   return(0);
280: }

284: static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer)
285: {
286:   PC_Shell       *shell = (PC_Shell*)pc->data;
288:   PetscBool      iascii;

291:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
292:   if (iascii) {
293:     if (shell->name) {
294:       PetscViewerASCIIPrintf(viewer,"  Shell: %s\n",shell->name);
295:     } else {
296:       PetscViewerASCIIPrintf(viewer,"  Shell: no name\n");
297:     }
298:   }
299:   if (shell->view) {
300:     PetscViewerASCIIPushTab(viewer);
301:     (*shell->view)(pc,viewer);
302:     PetscViewerASCIIPopTab(viewer);
303:   }
304:   return(0);
305: }

307: /* ------------------------------------------------------------------------------*/
310: static PetscErrorCode  PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(PC))
311: {
312:   PC_Shell *shell= (PC_Shell*)pc->data;

315:   shell->destroy = destroy;
316:   return(0);
317: }

321: static PetscErrorCode  PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(PC))
322: {
323:   PC_Shell *shell = (PC_Shell*)pc->data;;

326:   shell->setup = setup;
327:   if (setup) pc->ops->setup = PCSetUp_Shell;
328:   else       pc->ops->setup = 0;
329:   return(0);
330: }

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

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

345: static PetscErrorCode  PCShellSetApplySymmetricLeft_Shell(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
346: {
347:   PC_Shell *shell = (PC_Shell*)pc->data;

350:   shell->applysymmetricleft = apply;
351:   return(0);
352: }

356: static PetscErrorCode  PCShellSetApplySymmetricRight_Shell(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
357: {
358:   PC_Shell *shell = (PC_Shell*)pc->data;

361:   shell->applysymmetricright = apply;
362:   return(0);
363: }

367: static PetscErrorCode  PCShellSetApplyBA_Shell(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec))
368: {
369:   PC_Shell *shell = (PC_Shell*)pc->data;

372:   shell->applyBA = applyBA;
373:   if (applyBA) pc->ops->applyBA  = PCApplyBA_Shell;
374:   else         pc->ops->applyBA  = 0;
375:   return(0);
376: }

380: static PetscErrorCode  PCShellSetPreSolve_Shell(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec))
381: {
382:   PC_Shell       *shell = (PC_Shell*)pc->data;

386:   shell->presolve = presolve;
387:   if (presolve) {
388:     pc->ops->presolve = PCPreSolve_Shell;
389:     PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_Shell);
390:   } else {
391:     pc->ops->presolve = 0;
392:     PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);
393:   }
394:   return(0);
395: }

399: static PetscErrorCode  PCShellSetPostSolve_Shell(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec))
400: {
401:   PC_Shell *shell = (PC_Shell*)pc->data;

404:   shell->postsolve = postsolve;
405:   if (postsolve) pc->ops->postsolve = PCPostSolve_Shell;
406:   else           pc->ops->postsolve = 0;
407:   return(0);
408: }

412: static PetscErrorCode  PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(PC,PetscViewer))
413: {
414:   PC_Shell *shell = (PC_Shell*)pc->data;

417:   shell->view = view;
418:   return(0);
419: }

423: static PetscErrorCode  PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec))
424: {
425:   PC_Shell *shell = (PC_Shell*)pc->data;

428:   shell->applytranspose = applytranspose;
429:   if (applytranspose) pc->ops->applytranspose = PCApplyTranspose_Shell;
430:   else                pc->ops->applytranspose = 0;
431:   return(0);
432: }

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

441:   shell->applyrich = applyrich;
442:   if (applyrich) pc->ops->applyrichardson = PCApplyRichardson_Shell;
443:   else           pc->ops->applyrichardson = 0;
444:   return(0);
445: }

449: static PetscErrorCode  PCShellSetName_Shell(PC pc,const char name[])
450: {
451:   PC_Shell       *shell = (PC_Shell*)pc->data;

455:   PetscFree(shell->name);
456:   PetscStrallocpy(name,&shell->name);
457:   return(0);
458: }

462: static PetscErrorCode  PCShellGetName_Shell(PC pc,const char *name[])
463: {
464:   PC_Shell *shell = (PC_Shell*)pc->data;

467:   *name = shell->name;
468:   return(0);
469: }

471: /* -------------------------------------------------------------------------------*/

475: /*@C
476:    PCShellSetDestroy - Sets routine to use to destroy the user-provided
477:    application context.

479:    Logically Collective on PC

481:    Input Parameters:
482: +  pc - the preconditioner context
483: .  destroy - the application-provided destroy routine

485:    Calling sequence of destroy:
486: .vb
487:    PetscErrorCode destroy (PC)
488: .ve

490: .  ptr - the application context

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

494:    Level: developer

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

498: .seealso: PCShellSetApply(), PCShellSetContext()
499: @*/
500: PetscErrorCode  PCShellSetDestroy(PC pc,PetscErrorCode (*destroy)(PC))
501: {

506:   PetscTryMethod(pc,"PCShellSetDestroy_C",(PC,PetscErrorCode (*)(PC)),(pc,destroy));
507:   return(0);
508: }


513: /*@C
514:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
515:    matrix operator is changed.

517:    Logically Collective on PC

519:    Input Parameters:
520: +  pc - the preconditioner context
521: .  setup - the application-provided setup routine

523:    Calling sequence of setup:
524: .vb
525:    PetscErrorCode setup (PC pc)
526: .ve

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

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

532:    Level: developer

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

536: .seealso: PCShellSetApplyRichardson(), PCShellSetApply(), PCShellSetContext()
537: @*/
538: PetscErrorCode  PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(PC))
539: {

544:   PetscTryMethod(pc,"PCShellSetSetUp_C",(PC,PetscErrorCode (*)(PC)),(pc,setup));
545:   return(0);
546: }


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

554:    Logically Collective on PC

556:    Input Parameters:
557: +  pc - the preconditioner context
558: -  view - the application-provided view routine

560:    Calling sequence of apply:
561: .vb
562:    PetscErrorCode view(PC pc,PetscViewer v)
563: .ve

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

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

570:    Level: developer

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

574: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
575: @*/
576: PetscErrorCode  PCShellSetView(PC pc,PetscErrorCode (*view)(PC,PetscViewer))
577: {

582:   PetscTryMethod(pc,"PCShellSetView_C",(PC,PetscErrorCode (*)(PC,PetscViewer)),(pc,view));
583:   return(0);
584: }

588: /*@C
589:    PCShellSetApply - Sets routine to use as preconditioner.

591:    Logically Collective on PC

593:    Input Parameters:
594: +  pc - the preconditioner context
595: -  apply - the application-provided preconditioning routine

597:    Calling sequence of apply:
598: .vb
599:    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
600: .ve

602: +  pc - the preconditioner, get the application context with PCShellGetContext()
603: .  xin - input vector
604: -  xout - output vector

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

608:    Level: developer

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

612: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApplyBA(), PCShellSetApplySymmetricRight(),PCShellSetApplySymmetricLeft()
613: @*/
614: PetscErrorCode  PCShellSetApply(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
615: {

620:   PetscTryMethod(pc,"PCShellSetApply_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));
621:   return(0);
622: }

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

629:    Logically Collective on PC

631:    Input Parameters:
632: +  pc - the preconditioner context
633: -  apply - the application-provided left preconditioning routine

635:    Calling sequence of apply:
636: .vb
637:    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
638: .ve

640: +  pc - the preconditioner, get the application context with PCShellGetContext()
641: .  xin - input vector
642: -  xout - output vector

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

646:    Level: developer

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

650: .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
651: @*/
652: PetscErrorCode  PCShellSetApplySymmetricLeft(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
653: {

658:   PetscTryMethod(pc,"PCShellSetApplySymmetricLeft_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));
659:   return(0);
660: }

664: /*@C
665:    PCShellSetApplySymmetricRight - Sets routine to use as right preconditioner (when the PC_SYMMETRIC is used).

667:    Logically Collective on PC

669:    Input Parameters:
670: +  pc - the preconditioner context
671: -  apply - the application-provided right preconditioning routine

673:    Calling sequence of apply:
674: .vb
675:    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
676: .ve

678: +  pc - the preconditioner, get the application context with PCShellGetContext()
679: .  xin - input vector
680: -  xout - output vector

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

684:    Level: developer

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

688: .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
689: @*/
690: PetscErrorCode  PCShellSetApplySymmetricRight(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
691: {

696:   PetscTryMethod(pc,"PCShellSetApplySymmetricRight_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));
697:   return(0);
698: }

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

705:    Logically Collective on PC

707:    Input Parameters:
708: +  pc - the preconditioner context
709: -  applyBA - the application-provided BA routine

711:    Calling sequence of apply:
712: .vb
713:    PetscErrorCode applyBA (PC pc,Vec xin,Vec xout)
714: .ve

716: +  pc - the preconditioner, get the application context with PCShellGetContext()
717: .  xin - input vector
718: -  xout - output vector

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

722:    Level: developer

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

726: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApply()
727: @*/
728: PetscErrorCode  PCShellSetApplyBA(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec))
729: {

734:   PetscTryMethod(pc,"PCShellSetApplyBA_C",(PC,PetscErrorCode (*)(PC,PCSide,Vec,Vec,Vec)),(pc,applyBA));
735:   return(0);
736: }

740: /*@C
741:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

743:    Logically Collective on PC

745:    Input Parameters:
746: +  pc - the preconditioner context
747: -  apply - the application-provided preconditioning transpose routine

749:    Calling sequence of apply:
750: .vb
751:    PetscErrorCode applytranspose (PC pc,Vec xin,Vec xout)
752: .ve

754: +  pc - the preconditioner, get the application context with PCShellGetContext()
755: .  xin - input vector
756: -  xout - output vector

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

760:    Level: developer

762:    Notes:
763:    Uses the same context variable as PCShellSetApply().

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

767: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext(), PCShellSetApplyBA()
768: @*/
769: PetscErrorCode  PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec))
770: {

775:   PetscTryMethod(pc,"PCShellSetApplyTranspose_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,applytranspose));
776:   return(0);
777: }

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

786:    Logically Collective on PC

788:    Input Parameters:
789: +  pc - the preconditioner context
790: -  presolve - the application-provided presolve routine

792:    Calling sequence of presolve:
793: .vb
794:    PetscErrorCode presolve (PC,KSP ksp,Vec b,Vec x)
795: .ve

797: +  pc - the preconditioner, get the application context with PCShellGetContext()
798: .  xin - input vector
799: -  xout - output vector

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

803:    Level: developer

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

807: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext()
808: @*/
809: PetscErrorCode  PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec))
810: {

815:   PetscTryMethod(pc,"PCShellSetPreSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,presolve));
816:   return(0);
817: }

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

826:    Logically Collective on PC

828:    Input Parameters:
829: +  pc - the preconditioner context
830: -  postsolve - the application-provided presolve routine

832:    Calling sequence of postsolve:
833: .vb
834:    PetscErrorCode postsolve(PC,KSP ksp,Vec b,Vec x)
835: .ve

837: +  pc - the preconditioner, get the application context with PCShellGetContext()
838: .  xin - input vector
839: -  xout - output vector

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

843:    Level: developer

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

847: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext()
848: @*/
849: PetscErrorCode  PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec))
850: {

855:   PetscTryMethod(pc,"PCShellSetPostSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,postsolve));
856:   return(0);
857: }

861: /*@C
862:    PCShellSetName - Sets an optional name to associate with a shell
863:    preconditioner.

865:    Not Collective

867:    Input Parameters:
868: +  pc - the preconditioner context
869: -  name - character string describing shell preconditioner

871:    Level: developer

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

875: .seealso: PCShellGetName()
876: @*/
877: PetscErrorCode  PCShellSetName(PC pc,const char name[])
878: {

883:   PetscTryMethod(pc,"PCShellSetName_C",(PC,const char []),(pc,name));
884:   return(0);
885: }

889: /*@C
890:    PCShellGetName - Gets an optional name that the user has set for a shell
891:    preconditioner.

893:    Not Collective

895:    Input Parameter:
896: .  pc - the preconditioner context

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

901:    Level: developer

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

905: .seealso: PCShellSetName()
906: @*/
907: PetscErrorCode  PCShellGetName(PC pc,const char *name[])
908: {

914:   PetscUseMethod(pc,"PCShellGetName_C",(PC,const char*[]),(pc,name));
915:   return(0);
916: }

920: /*@C
921:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
922:    in Richardson iteration.

924:    Logically Collective on PC

926:    Input Parameters:
927: +  pc - the preconditioner context
928: -  apply - the application-provided preconditioning routine

930:    Calling sequence of apply:
931: .vb
932:    PetscErrorCode apply (PC pc,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits)
933: .ve

935: +  pc - the preconditioner, get the application context with PCShellGetContext()
936: .  b - right-hand-side
937: .  x - current iterate
938: .  r - work space
939: .  rtol - relative tolerance of residual norm to stop at
940: .  abstol - absolute tolerance of residual norm to stop at
941: .  dtol - if residual norm increases by this factor than return
942: -  maxits - number of iterations to run

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

946:    Level: developer

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

950: .seealso: PCShellSetApply(), PCShellSetContext()
951: @*/
952: PetscErrorCode  PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*))
953: {

958:   PetscTryMethod(pc,"PCShellSetApplyRichardson_C",(PC,PetscErrorCode (*)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)),(pc,apply));
959:   return(0);
960: }

962: /*MC
963:    PCSHELL - Creates a new preconditioner class for use with your
964:               own private data storage format.

966:    Level: advanced
967: >
968:    Concepts: providing your own preconditioner

970:   Usage:
971: $             extern PetscErrorCode apply(PC,Vec,Vec);
972: $             extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec);
973: $             extern PetscErrorCode applytranspose(PC,Vec,Vec);
974: $             extern PetscErrorCode setup(PC);
975: $             extern PetscErrorCode destroy(PC);
976: $
977: $             PCCreate(comm,&pc);
978: $             PCSetType(pc,PCSHELL);
979: $             PCShellSetContext(pc,ctx)
980: $             PCShellSetApply(pc,apply);
981: $             PCShellSetApplyBA(pc,applyba);               (optional)
982: $             PCShellSetApplyTranspose(pc,applytranspose); (optional)
983: $             PCShellSetSetUp(pc,setup);                   (optional)
984: $             PCShellSetDestroy(pc,destroy);               (optional)

986: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
987:            MATSHELL, PCShellSetSetUp(), PCShellSetApply(), PCShellSetView(),
988:            PCShellSetApplyTranspose(), PCShellSetName(), PCShellSetApplyRichardson(),
989:            PCShellGetName(), PCShellSetContext(), PCShellGetContext(), PCShellSetApplyBA()
990: M*/

994: PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc)
995: {
997:   PC_Shell       *shell;

1000:   PetscNewLog(pc,&shell);
1001:   pc->data = (void*)shell;

1003:   pc->ops->destroy         = PCDestroy_Shell;
1004:   pc->ops->view            = PCView_Shell;
1005:   pc->ops->apply           = PCApply_Shell;
1006:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_Shell;
1007:   pc->ops->applysymmetricright = PCApplySymmetricRight_Shell;
1008:   pc->ops->applytranspose  = 0;
1009:   pc->ops->applyrichardson = 0;
1010:   pc->ops->setup           = 0;
1011:   pc->ops->presolve        = 0;
1012:   pc->ops->postsolve       = 0;

1014:   shell->apply          = 0;
1015:   shell->applytranspose = 0;
1016:   shell->name           = 0;
1017:   shell->applyrich      = 0;
1018:   shell->presolve       = 0;
1019:   shell->postsolve      = 0;
1020:   shell->ctx            = 0;
1021:   shell->setup          = 0;
1022:   shell->view           = 0;
1023:   shell->destroy        = 0;
1024:   shell->applysymmetricleft  = 0;
1025:   shell->applysymmetricright = 0;

1027:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetDestroy_C",PCShellSetDestroy_Shell);
1028:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetSetUp_C",PCShellSetSetUp_Shell);
1029:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApply_C",PCShellSetApply_Shell);
1030:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricLeft_C",PCShellSetApplySymmetricLeft_Shell);
1031:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricRight_C",PCShellSetApplySymmetricRight_Shell);
1032:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyBA_C",PCShellSetApplyBA_Shell);
1033:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPreSolve_C",PCShellSetPreSolve_Shell);
1034:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPostSolve_C",PCShellSetPostSolve_Shell);
1035:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetView_C",PCShellSetView_Shell);
1036:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",PCShellSetApplyTranspose_Shell);
1037:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetName_C",PCShellSetName_Shell);
1038:   PetscObjectComposeFunction((PetscObject)pc,"PCShellGetName_C",PCShellGetName_Shell);
1039:   PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",PCShellSetApplyRichardson_Shell);
1040:   return(0);
1041: }