Actual source code: shellpc.c

  1: #define PETSCKSP_DLL

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

 8:  #include src/ksp/pc/pcimpl.h
 9:  #include vecimpl.h

 12: typedef struct {
 13:   void           *ctx;                     /* user provided contexts for preconditioner */
 14:   PetscErrorCode (*setup)(void*);
 15:   PetscErrorCode (*apply)(void*,Vec,Vec);
 16:   PetscErrorCode (*presolve)(void*,KSP,Vec,Vec);
 17:   PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec);
 18:   PetscErrorCode (*view)(void*,PetscViewer);
 19:   PetscErrorCode (*applytranspose)(void*,Vec,Vec);
 20:   PetscErrorCode (*applyrich)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt);
 21:   char           *name;
 22: } PC_Shell;

 27: /*@
 28:     PCShellGetContext - Returns the user-provided context associated with a shell PC

 30:     Not Collective

 32:     Input Parameter:
 33: .   pc - should have been created with PCCreateShell()

 35:     Output Parameter:
 36: .   ctx - the user provided context

 38:     Level: advanced

 40:     Notes:
 41:     This routine is intended for use within various shell routines
 42:     
 43: .keywords: PC, shell, get, context

 45: .seealso: PCCreateShell(), PCShellSetContext()
 46: @*/
 47: PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetContext(PC pc,void **ctx)
 48: {
 50:   PetscTruth     flg;

 55:   PetscTypeCompare((PetscObject)pc,PCSHELL,&flg);
 56:   if (!flg) *ctx = 0;
 57:   else      *ctx = ((PC_Shell*)(pc->data))->ctx;
 58:   return(0);
 59: }

 63: /*@C
 64:     PCShellSetContext - sets the context for a shell PC

 66:    Collective on PC

 68:     Input Parameters:
 69: +   pc - the shell PC
 70: -   ctx - the context

 72:    Level: advanced

 74:    Fortran Notes: The context can only be an integer or a PetscObject
 75:       unfortunately it cannot be a Fortran array or derived type.

 77: .seealso: PCCreateShell(), PCShellGetContext()
 78: @*/
 79: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetContext(PC pc,void *ctx)
 80: {
 81:   PC_Shell      *shell = (PC_Shell*)pc->data;
 83:   PetscTruth     flg;

 87:   PetscTypeCompare((PetscObject)pc,PCSHELL,&flg);
 88:   if (flg) {
 89:     shell->ctx = ctx;
 90:   }
 91:   return(0);
 92: }

 96: static PetscErrorCode PCSetUp_Shell(PC pc)
 97: {
 98:   PC_Shell       *shell;

102:   shell = (PC_Shell*)pc->data;
103:   if (shell->setup) {
104:     (*shell->setup)(shell->ctx);
105:   }
106:   return(0);
107: }

111: static PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y)
112: {
113:   PC_Shell       *shell;

117:   shell = (PC_Shell*)pc->data;
118:   if (!shell->apply) SETERRQ(PETSC_ERR_USER,"No apply() routine provided to Shell PC");
119:   (*shell->apply)(shell->ctx,x,y);
120:   return(0);
121: }

125: static PetscErrorCode PCPreSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
126: {
127:   PC_Shell       *shell;

131:   shell = (PC_Shell*)pc->data;
132:   if (!shell->presolve) SETERRQ(PETSC_ERR_USER,"No presolve() routine provided to Shell PC");
133:   (*shell->presolve)(shell->ctx,ksp,b,x);
134:   return(0);
135: }

139: static PetscErrorCode PCPostSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
140: {
141:   PC_Shell       *shell;

145:   shell = (PC_Shell*)pc->data;
146:   if (!shell->postsolve) SETERRQ(PETSC_ERR_USER,"No postsolve() routine provided to Shell PC");
147:   (*shell->postsolve)(shell->ctx,ksp,b,x);
148:   return(0);
149: }

153: static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
154: {
155:   PC_Shell       *shell;

159:   shell = (PC_Shell*)pc->data;
160:   if (!shell->applytranspose) SETERRQ(PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC");
161:   (*shell->applytranspose)(shell->ctx,x,y);
162:   return(0);
163: }

167: static PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it)
168: {
170:   PC_Shell       *shell;

173:   shell = (PC_Shell*)pc->data;
174:   (*shell->applyrich)(shell->ctx,x,y,w,rtol,abstol,dtol,it);
175:   return(0);
176: }

180: static PetscErrorCode PCDestroy_Shell(PC pc)
181: {
182:   PC_Shell       *shell = (PC_Shell*)pc->data;

186:   if (shell->name) {PetscFree(shell->name);}
187:   PetscFree(shell);
188:   return(0);
189: }

193: static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer)
194: {
195:   PC_Shell       *shell = (PC_Shell*)pc->data;
197:   PetscTruth     iascii;

200:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
201:   if (iascii) {
202:     if (shell->name) {PetscViewerASCIIPrintf(viewer,"  Shell: %s\n",shell->name);}
203:     else             {PetscViewerASCIIPrintf(viewer,"  Shell: no name\n");}
204:   }
205:   if (shell->view) {
206:     PetscViewerASCIIPushTab(viewer);
207:     (*shell->view)(shell->ctx,viewer);
208:     PetscViewerASCIIPopTab(viewer);
209:   }
210:   return(0);
211: }

213: /* ------------------------------------------------------------------------------*/
217: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(void*))
218: {
219:   PC_Shell *shell;

222:   shell        = (PC_Shell*)pc->data;
223:   shell->setup = setup;
224:   return(0);
225: }

231: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec))
232: {
233:   PC_Shell *shell;

236:   shell        = (PC_Shell*)pc->data;
237:   shell->apply = apply;
238:   return(0);
239: }

245: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPreSolve_Shell(PC pc,PetscErrorCode (*presolve)(void*,KSP,Vec,Vec))
246: {
247:   PC_Shell *shell;

250:   shell             = (PC_Shell*)pc->data;
251:   shell->presolve   = presolve;
252:   if (presolve) {
253:     pc->ops->presolve = PCPreSolve_Shell;
254:   } else {
255:     pc->ops->presolve = 0;
256:   }
257:   return(0);
258: }

264: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPostSolve_Shell(PC pc,PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec))
265: {
266:   PC_Shell *shell;

269:   shell           = (PC_Shell*)pc->data;
270:   shell->postsolve = postsolve;
271:   if (postsolve) {
272:     pc->ops->postsolve = PCPostSolve_Shell;
273:   } else {
274:     pc->ops->postsolve = 0;
275:   }
276:   return(0);
277: }

283: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(void*,PetscViewer))
284: {
285:   PC_Shell *shell;

288:   shell        = (PC_Shell*)pc->data;
289:   shell->view = view;
290:   return(0);
291: }

297: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec))
298: {
299:   PC_Shell *shell;

302:   shell                 = (PC_Shell*)pc->data;
303:   shell->applytranspose = applytranspose;
304:   return(0);
305: }

311: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName_Shell(PC pc,const char name[])
312: {
313:   PC_Shell       *shell;

317:   shell = (PC_Shell*)pc->data;
318:   PetscStrallocpy(name,&shell->name);
319:   return(0);
320: }

326: PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName_Shell(PC pc,char *name[])
327: {
328:   PC_Shell *shell;

331:   shell  = (PC_Shell*)pc->data;
332:   *name  = shell->name;
333:   return(0);
334: }

340: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt))
341: {
342:   PC_Shell *shell;

345:   shell                     = (PC_Shell*)pc->data;
346:   pc->ops->applyrichardson  = PCApplyRichardson_Shell;
347:   shell->applyrich          = apply;
348:   return(0);
349: }

352: /* -------------------------------------------------------------------------------*/

356: /*@C
357:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 
358:    matrix operator is changed.

360:    Collective on PC

362:    Input Parameters:
363: +  pc - the preconditioner context
364: .  setup - the application-provided setup routine

366:    Calling sequence of setup:
367: .vb
368:    PetscErrorCode setup (void *ptr)
369: .ve

371: .  ptr - the application context

373:    Level: developer

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

377: .seealso: PCShellSetApplyRichardson(), PCShellSetApply(), PCShellSetContext()
378: @*/
379: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(void*))
380: {
381:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*));

385:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&f);
386:   if (f) {
387:     (*f)(pc,setup);
388:   }
389:   return(0);
390: }


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

398:    Collective on PC

400:    Input Parameters:
401: +  pc - the preconditioner context
402: -  view - the application-provided view routine

404:    Calling sequence of apply:
405: .vb
406:    PetscErrorCode view(void *ptr,PetscViewer v)
407: .ve

409: +  ptr - the application context
410: -  v   - viewer

412:    Level: developer

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

416: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
417: @*/
418: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView(PC pc,PetscErrorCode (*view)(void*,PetscViewer))
419: {
420:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,PetscViewer));

424:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&f);
425:   if (f) {
426:     (*f)(pc,view);
427:   }
428:   return(0);
429: }

433: /*@C
434:    PCShellSetApply - Sets routine to use as preconditioner.

436:    Collective on PC

438:    Input Parameters:
439: +  pc - the preconditioner context
440: -  apply - the application-provided preconditioning routine

442:    Calling sequence of apply:
443: .vb
444:    PetscErrorCode apply (void *ptr,Vec xin,Vec xout)
445: .ve

447: +  ptr - the application context
448: .  xin - input vector
449: -  xout - output vector

451:    Level: developer

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

455: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
456: @*/
457: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec))
458: {
459:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec));

463:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&f);
464:   if (f) {
465:     (*f)(pc,apply);
466:   }
467:   return(0);
468: }

472: /*@C
473:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

475:    Collective on PC

477:    Input Parameters:
478: +  pc - the preconditioner context
479: -  apply - the application-provided preconditioning transpose routine

481:    Calling sequence of apply:
482: .vb
483:    PetscErrorCode applytranspose (void *ptr,Vec xin,Vec xout)
484: .ve

486: +  ptr - the application context
487: .  xin - input vector
488: -  xout - output vector

490:    Level: developer

492:    Notes: 
493:    Uses the same context variable as PCShellSetApply().

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

497: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext()
498: @*/
499: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec))
500: {
501:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec));

505:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&f);
506:   if (f) {
507:     (*f)(pc,applytranspose);
508:   }
509:   return(0);
510: }

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

519:    Collective on PC

521:    Input Parameters:
522: +  pc - the preconditioner context
523: -  presolve - the application-provided presolve routine

525:    Calling sequence of presolve:
526: .vb
527:    PetscErrorCode presolve (void *ptr,KSP ksp,Vec b,Vec x)
528: .ve

530: +  ptr - the application context
531: .  xin - input vector
532: -  xout - output vector

534:    Level: developer

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

538: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext()
539: @*/
540: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(void*,KSP,Vec,Vec))
541: {
542:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,KSP,Vec,Vec));

546:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetPreSolve_C",(void (**)(void))&f);
547:   if (f) {
548:     (*f)(pc,presolve);
549:   }
550:   return(0);
551: }

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

560:    Collective on PC

562:    Input Parameters:
563: +  pc - the preconditioner context
564: -  postsolve - the application-provided presolve routine

566:    Calling sequence of postsolve:
567: .vb
568:    PetscErrorCode postsolve(void *ptr,KSP ksp,Vec b,Vec x)
569: .ve

571: +  ptr - the application context
572: .  xin - input vector
573: -  xout - output vector

575:    Level: developer

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

579: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext()
580: @*/
581: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec))
582: {
583:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,KSP,Vec,Vec));

587:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetPostSolve_C",(void (**)(void))&f);
588:   if (f) {
589:     (*f)(pc,postsolve);
590:   }
591:   return(0);
592: }

596: /*@C
597:    PCShellSetName - Sets an optional name to associate with a shell
598:    preconditioner.

600:    Not Collective

602:    Input Parameters:
603: +  pc - the preconditioner context
604: -  name - character string describing shell preconditioner

606:    Level: developer

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

610: .seealso: PCShellGetName()
611: @*/
612: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName(PC pc,const char name[])
613: {
614:   PetscErrorCode ierr,(*f)(PC,const char []);

618:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&f);
619:   if (f) {
620:     (*f)(pc,name);
621:   }
622:   return(0);
623: }

627: /*@C
628:    PCShellGetName - Gets an optional name that the user has set for a shell
629:    preconditioner.

631:    Not Collective

633:    Input Parameter:
634: .  pc - the preconditioner context

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

639:    Level: developer

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

643: .seealso: PCShellSetName()
644: @*/
645: PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName(PC pc,char *name[])
646: {
647:   PetscErrorCode ierr,(*f)(PC,char *[]);

652:   PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);
653:   if (f) {
654:     (*f)(pc,name);
655:   } else {
656:     SETERRQ(PETSC_ERR_ARG_WRONG,"Not shell preconditioner, cannot get name");
657:   }
658:   return(0);
659: }

663: /*@C
664:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
665:    in Richardson iteration.

667:    Collective on PC

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

673:    Calling sequence of apply:
674: .vb
675:    PetscErrorCode apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits)
676: .ve

678: +  ptr - the application context
679: .  b - right-hand-side
680: .  x - current iterate
681: .  r - work space
682: .  rtol - relative tolerance of residual norm to stop at
683: .  abstol - absolute tolerance of residual norm to stop at
684: .  dtol - if residual norm increases by this factor than return
685: -  maxits - number of iterations to run

687:    Level: developer

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

691: .seealso: PCShellSetApply(), PCShellSetContext()
692: @*/
693: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt))
694: {
695:   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt));

699:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);
700:   if (f) {
701:     (*f)(pc,apply);
702:   }
703:   return(0);
704: }

706: /*MC
707:    PCSHELL - Creates a new preconditioner class for use with your 
708:               own private data storage format.

710:    Level: advanced

712:    Concepts: providing your own preconditioner

714:   Usage:
715: $             PetscErrorCode (*mult)(void*,Vec,Vec);
716: $             PetscErrorCode (*setup)(void*);
717: $             PCCreate(comm,&pc);
718: $             PCSetType(pc,PCSHELL);
719: $             PCShellSetApply(pc,mult);
720: $             PCShellSetContext(pc,ctx)
721: $             PCShellSetSetUp(pc,setup);       (optional)

723: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
724:            MATSHELL, PCShellSetUp(), PCShellSetApply(), PCShellSetView(), 
725:            PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(), 
726:            PCShellGetName(), PCShellSetContext(), PCShellGetContext()
727: M*/

732: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Shell(PC pc)
733: {
735:   PC_Shell       *shell;

738:   pc->ops->destroy    = PCDestroy_Shell;
739:   PetscNew(PC_Shell,&shell);
740:   PetscLogObjectMemory(pc,sizeof(PC_Shell));
741:   pc->data         = (void*)shell;
742:   pc->name         = 0;

744:   pc->ops->apply           = PCApply_Shell;
745:   pc->ops->view            = PCView_Shell;
746:   pc->ops->applytranspose  = PCApplyTranspose_Shell;
747:   pc->ops->applyrichardson = 0;
748:   pc->ops->setup           = PCSetUp_Shell;
749:   pc->ops->presolve        = 0;
750:   pc->ops->postsolve       = 0;
751:   pc->ops->view            = PCView_Shell;

753:   shell->apply          = 0;
754:   shell->applytranspose = 0;
755:   shell->name           = 0;
756:   shell->applyrich      = 0;
757:   shell->presolve       = 0;
758:   shell->postsolve      = 0;
759:   shell->ctx            = 0;
760:   shell->setup          = 0;
761:   shell->view           = 0;

763:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
764:                     PCShellSetSetUp_Shell);
765:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
766:                     PCShellSetApply_Shell);
767:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetPreSolve_C","PCShellSetPreSolve_Shell",
768:                     PCShellSetPreSolve_Shell);
769:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetPostSolve_C","PCShellSetPostSolve_Shell",
770:                     PCShellSetPostSolve_Shell);
771:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell",
772:                     PCShellSetView_Shell);
773:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C","PCShellSetApplyTranspose_Shell",
774:                     PCShellSetApplyTranspose_Shell);
775:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
776:                     PCShellSetName_Shell);
777:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
778:                     PCShellGetName_Shell);
779:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C","PCShellSetApplyRichardson_Shell",
780:                     PCShellSetApplyRichardson_Shell);
781:   return(0);
782: }