Actual source code: shellpc.c

  1: /*$Id: shellpc.c,v 1.77 2001/08/21 21:03:18 bsmith Exp $*/

  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

 11: EXTERN_C_BEGIN
 12: typedef struct {
 13:   void *ctx,*ctxrich;    /* user provided contexts for preconditioner */
 14:   int  (*setup)(void *);
 15:   int  (*apply)(void *,Vec,Vec);
 16:   int  (*view)(void *,PetscViewer);
 17:   int  (*applytranspose)(void *,Vec,Vec);
 18:   int  (*applyrich)(void *,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int);
 19:   char *name;
 20: } PC_Shell;
 21: EXTERN_C_END

 25: static int PCSetUp_Shell(PC pc)
 26: {
 27:   PC_Shell *shell;
 28:   int      ierr;

 31:   shell = (PC_Shell*)pc->data;
 32:   if (shell->setup) {
 33:     (*shell->setup)(shell->ctx);
 34:   }
 35:   return(0);
 36: }

 40: static int PCApply_Shell(PC pc,Vec x,Vec y)
 41: {
 42:   PC_Shell *shell;
 43:   int      ierr;

 46:   shell = (PC_Shell*)pc->data;
 47:   if (!shell->apply) SETERRQ(1,"No apply() routine provided to Shell PC");
 48:   (*shell->apply)(shell->ctx,x,y);
 49:   return(0);
 50: }

 54: static int PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
 55: {
 56:   PC_Shell *shell;
 57:   int      ierr;

 60:   shell = (PC_Shell*)pc->data;
 61:   if (!shell->applytranspose) SETERRQ(1,"No applytranspose() routine provided to Shell PC");
 62:   (*shell->applytranspose)(shell->ctx,x,y);
 63:   return(0);
 64: }

 68: static int PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int it)
 69: {
 70:   int      ierr;
 71:   PC_Shell *shell;

 74:   shell = (PC_Shell*)pc->data;
 75:   (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,atol,dtol,it);
 76:   return(0);
 77: }

 81: static int PCDestroy_Shell(PC pc)
 82: {
 83:   PC_Shell *shell = (PC_Shell*)pc->data;
 84:   int      ierr;

 87:   if (shell->name) {PetscFree(shell->name);}
 88:   PetscFree(shell);
 89:   return(0);
 90: }

 94: static int PCView_Shell(PC pc,PetscViewer viewer)
 95: {
 96:   PC_Shell   *shell = (PC_Shell*)pc->data;
 97:   int        ierr;
 98:   PetscTruth isascii;

101:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
102:   if (isascii) {
103:     if (shell->name) {PetscViewerASCIIPrintf(viewer,"  Shell: %s\n",shell->name);}
104:     else             {PetscViewerASCIIPrintf(viewer,"  Shell: no name\n");}
105:   }
106:   if (shell->view) {
107:     PetscViewerASCIIPushTab(viewer);
108:     (*shell->view)(shell->ctx,viewer);
109:     PetscViewerASCIIPopTab(viewer);
110:   }
111:   return(0);
112: }

114: /* ------------------------------------------------------------------------------*/
115: EXTERN_C_BEGIN
118: int PCShellSetSetUp_Shell(PC pc, int (*setup)(void*))
119: {
120:   PC_Shell *shell;

123:   shell        = (PC_Shell*)pc->data;
124:   shell->setup = setup;
125:   return(0);
126: }
127: EXTERN_C_END

129: EXTERN_C_BEGIN
132: int PCShellSetApply_Shell(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
133: {
134:   PC_Shell *shell;

137:   shell        = (PC_Shell*)pc->data;
138:   shell->apply = apply;
139:   shell->ctx   = ptr;
140:   return(0);
141: }
142: EXTERN_C_END

144: EXTERN_C_BEGIN
147: int PCShellSetView_Shell(PC pc,int (*view)(void*,PetscViewer))
148: {
149:   PC_Shell *shell;

152:   shell        = (PC_Shell*)pc->data;
153:   shell->view = view;
154:   return(0);
155: }
156: EXTERN_C_END

158: EXTERN_C_BEGIN
161: int PCShellSetApplyTranspose_Shell(PC pc,int (*applytranspose)(void*,Vec,Vec))
162: {
163:   PC_Shell *shell;

166:   shell                 = (PC_Shell*)pc->data;
167:   shell->applytranspose = applytranspose;
168:   return(0);
169: }
170: EXTERN_C_END

172: EXTERN_C_BEGIN
175: int PCShellSetName_Shell(PC pc,const char name[])
176: {
177:   PC_Shell *shell;
178:   int      ierr;

181:   shell = (PC_Shell*)pc->data;
182:   PetscStrallocpy(name,&shell->name);
183:   return(0);
184: }
185: EXTERN_C_END

187: EXTERN_C_BEGIN
190: int PCShellGetName_Shell(PC pc,char *name[])
191: {
192:   PC_Shell *shell;

195:   shell  = (PC_Shell*)pc->data;
196:   *name  = shell->name;
197:   return(0);
198: }
199: EXTERN_C_END

201: EXTERN_C_BEGIN
204: int PCShellSetApplyRichardson_Shell(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
205: {
206:   PC_Shell *shell;

209:   shell                     = (PC_Shell*)pc->data;
210:   pc->ops->applyrichardson  = PCApplyRichardson_Shell;
211:   shell->applyrich          = apply;
212:   shell->ctxrich            = ptr;
213:   return(0);
214: }
215: EXTERN_C_END

217: /* -------------------------------------------------------------------------------*/

221: /*@C
222:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 
223:    matrix operator is changed.

225:    Collective on PC

227:    Input Parameters:
228: +  pc - the preconditioner context
229: .  setup - the application-provided setup routine

231:    Calling sequence of setup:
232: .vb
233:    int setup (void *ptr)
234: .ve

236: .  ptr - the application context

238:    Level: developer

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

242: .seealso: PCShellSetApplyRichardson(), PCShellSetApply()
243: @*/
244: int PCShellSetSetUp(PC pc,int (*setup)(void*))
245: {
246:   int ierr,(*f)(PC,int (*)(void*));

250:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&f);
251:   if (f) {
252:     (*f)(pc,setup);
253:   }
254:   return(0);
255: }


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

263:    Collective on PC

265:    Input Parameters:
266: +  pc - the preconditioner context
267: -  view - the application-provided view routine

269:    Calling sequence of apply:
270: .vb
271:    int view(void *ptr,PetscViewer v)
272: .ve

274: +  ptr - the application context
275: -  v   - viewer

277:    Level: developer

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

281: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
282: @*/
283: int PCShellSetView(PC pc,int (*view)(void*,PetscViewer))
284: {
285:   int ierr,(*f)(PC,int (*)(void*,PetscViewer));

289:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&f);
290:   if (f) {
291:     (*f)(pc,view);
292:   }
293:   return(0);
294: }

298: /*@C
299:    PCShellSetApply - Sets routine to use as preconditioner.

301:    Collective on PC

303:    Input Parameters:
304: +  pc - the preconditioner context
305: .  apply - the application-provided preconditioning routine
306: -  ptr - pointer to data needed by this routine

308:    Calling sequence of apply:
309: .vb
310:    int apply (void *ptr,Vec xin,Vec xout)
311: .ve

313: +  ptr - the application context
314: .  xin - input vector
315: -  xout - output vector

317:    Level: developer

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

321: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
322: @*/
323: int PCShellSetApply(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
324: {
325:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec),void *);

329:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&f);
330:   if (f) {
331:     (*f)(pc,apply,ptr);
332:   }
333:   return(0);
334: }

338: /*@C
339:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

341:    Collective on PC

343:    Input Parameters:
344: +  pc - the preconditioner context
345: -  apply - the application-provided preconditioning transpose routine

347:    Calling sequence of apply:
348: .vb
349:    int applytranspose (void *ptr,Vec xin,Vec xout)
350: .ve

352: +  ptr - the application context
353: .  xin - input vector
354: -  xout - output vector

356:    Level: developer

358:    Notes: 
359:    Uses the same context variable as PCShellSetApply().

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

363: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply()
364: @*/
365: int PCShellSetApplyTranspose(PC pc,int (*applytranspose)(void*,Vec,Vec))
366: {
367:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec));

371:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&f);
372:   if (f) {
373:     (*f)(pc,applytranspose);
374:   }
375:   return(0);
376: }

380: /*@C
381:    PCShellSetName - Sets an optional name to associate with a shell
382:    preconditioner.

384:    Not Collective

386:    Input Parameters:
387: +  pc - the preconditioner context
388: -  name - character string describing shell preconditioner

390:    Level: developer

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

394: .seealso: PCShellGetName()
395: @*/
396: int PCShellSetName(PC pc,const char name[])
397: {
398:   int ierr,(*f)(PC,const char []);

402:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&f);
403:   if (f) {
404:     (*f)(pc,name);
405:   }
406:   return(0);
407: }

411: /*@C
412:    PCShellGetName - Gets an optional name that the user has set for a shell
413:    preconditioner.

415:    Not Collective

417:    Input Parameter:
418: .  pc - the preconditioner context

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

423:    Level: developer

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

427: .seealso: PCShellSetName()
428: @*/
429: int PCShellGetName(PC pc,char *name[])
430: {
431:   int ierr,(*f)(PC,char *[]);

436:   PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);
437:   if (f) {
438:     (*f)(pc,name);
439:   } else {
440:     SETERRQ(1,"Not shell preconditioner, cannot get name");
441:   }
442:   return(0);
443: }

447: /*@C
448:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
449:    in Richardson iteration.

451:    Collective on PC

453:    Input Parameters:
454: +  pc - the preconditioner context
455: .  apply - the application-provided preconditioning routine
456: -  ptr - pointer to data needed by this routine

458:    Calling sequence of apply:
459: .vb
460:    int apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal atol,PetscReal dtol,int maxits)
461: .ve

463: +  ptr - the application context
464: .  b - right-hand-side
465: .  x - current iterate
466: .  r - work space
467: .  rtol - relative tolerance of residual norm to stop at
468: .  atol - absolute tolerance of residual norm to stop at
469: .  dtol - if residual norm increases by this factor than return
470: -  maxits - number of iterations to run

472:    Level: developer

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

476: .seealso: PCShellSetApply()
477: @*/
478: int PCShellSetApplyRichardson(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
479: {
480:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *);

484:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);
485:   if (f) {
486:     (*f)(pc,apply,ptr);
487:   }
488:   return(0);
489: }

491: /*MC
492:    PCSHELL - Creates a new preconditioner class for use with your 
493:               own private data storage format.

495:    Level: advanced

497:    Concepts: providing your own preconditioner

499:   Usage:
500: $             int (*mult)(void *,Vec,Vec);
501: $             int (*setup)(void *);
502: $             PCCreate(comm,&pc);
503: $             PCSetType(pc,PCSHELL);
504: $             PCShellSetApply(pc,mult,ctx);
505: $             PCShellSetSetUp(pc,setup);       (optional)

507: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
508:            KSPSHELL(), MATSHELL(), PCShellSetUp(), PCShellSetApply(), PCShellSetView(), 
509:            PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(), 
510:            PCShellGetName()
511: M*/

513: EXTERN_C_BEGIN
516: int PCCreate_Shell(PC pc)
517: {
518:   int      ierr;
519:   PC_Shell *shell;

522:   pc->ops->destroy    = PCDestroy_Shell;
523:   PetscNew(PC_Shell,&shell);
524:   PetscLogObjectMemory(pc,sizeof(PC_Shell));

526:   pc->data         = (void*)shell;
527:   pc->name         = 0;

529:   pc->ops->apply           = PCApply_Shell;
530:   pc->ops->view            = PCView_Shell;
531:   pc->ops->applytranspose  = PCApplyTranspose_Shell;
532:   pc->ops->applyrichardson = 0;
533:   pc->ops->setup           = PCSetUp_Shell;
534:   pc->ops->view            = PCView_Shell;

536:   shell->apply          = 0;
537:   shell->applytranspose = 0;
538:   shell->name           = 0;
539:   shell->applyrich      = 0;
540:   shell->ctxrich        = 0;
541:   shell->ctx            = 0;
542:   shell->setup          = 0;
543:   shell->view           = 0;

545:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
546:                     PCShellSetSetUp_Shell);
547:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
548:                     PCShellSetApply_Shell);
549:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell",
550:                     PCShellSetView_Shell);
551:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C",
552:                     "PCShellSetApplyTranspose_Shell",
553:                     PCShellSetApplyTranspose_Shell);
554:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
555:                     PCShellSetName_Shell);
556:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
557:                     PCShellGetName_Shell);
558:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C",
559:                     "PCShellSetApplyRichardson_Shell",
560:                     PCShellSetApplyRichardson_Shell);

562:   return(0);
563: }
564: EXTERN_C_END