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/sles/pc/pcimpl.h
 9:  #include src/vec/vecimpl.h

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

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

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

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

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

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

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

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

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

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

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

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

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

112: /* ------------------------------------------------------------------------------*/
113: EXTERN_C_BEGIN
116: int PCShellSetSetUp_Shell(PC pc, int (*setup)(void*))
117: {
118:   PC_Shell *shell;

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

127: EXTERN_C_BEGIN
130: int PCShellSetApply_Shell(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
131: {
132:   PC_Shell *shell;

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

142: EXTERN_C_BEGIN
145: int PCShellSetView_Shell(PC pc,int (*view)(void*,PetscViewer))
146: {
147:   PC_Shell *shell;

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

156: EXTERN_C_BEGIN
159: int PCShellSetApplyTranspose_Shell(PC pc,int (*applytranspose)(void*,Vec,Vec))
160: {
161:   PC_Shell *shell;

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

170: EXTERN_C_BEGIN
173: int PCShellSetName_Shell(PC pc,const char name[])
174: {
175:   PC_Shell *shell;
176:   int      ierr;

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

185: EXTERN_C_BEGIN
188: int PCShellGetName_Shell(PC pc,char *name[])
189: {
190:   PC_Shell *shell;

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

199: EXTERN_C_BEGIN
202: int PCShellSetApplyRichardson_Shell(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
203: {
204:   PC_Shell *shell;

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

215: /* -------------------------------------------------------------------------------*/

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

223:    Collective on PC

225:    Input Parameters:
226: +  pc - the preconditioner context
227: .  setup - the application-provided setup routine

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

234: .  ptr - the application context

236:    Level: developer

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

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

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


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

261:    Collective on PC

263:    Input Parameters:
264: +  pc - the preconditioner context
265: -  view - the application-provided view routine

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

272: +  ptr - the application context
273: -  v   - viewer

275:    Level: developer

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

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

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

296: /*@C
297:    PCShellSetApply - Sets routine to use as preconditioner.

299:    Collective on PC

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

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

311: +  ptr - the application context
312: .  xin - input vector
313: -  xout - output vector

315:    Level: developer

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

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

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

336: /*@C
337:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

339:    Collective on PC

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

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

350: +  ptr - the application context
351: .  xin - input vector
352: -  xout - output vector

354:    Level: developer

356:    Notes: 
357:    Uses the same context variable as PCShellSetApply().

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

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

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

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

382:    Not Collective

384:    Input Parameters:
385: +  pc - the preconditioner context
386: -  name - character string describing shell preconditioner

388:    Level: developer

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

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

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

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

413:    Not Collective

415:    Input Parameter:
416: .  pc - the preconditioner context

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

421:    Level: developer

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

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

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

444: /*@C
445:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
446:    in Richardson iteration.

448:    Collective on PC

450:    Input Parameters:
451: +  pc - the preconditioner context
452: .  apply - the application-provided preconditioning routine
453: -  ptr - pointer to data needed by this routine

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

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

469:    Level: developer

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

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

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

488: /*MC
489:    PCSHELL - Creates a new preconditioner class for use with your 
490:               own private data storage format.

492:    Level: advanced

494:    Concepts: providing your own preconditioner

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

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

510: EXTERN_C_BEGIN
513: int PCCreate_Shell(PC pc)
514: {
515:   int      ierr;
516:   PC_Shell *shell;

519:   pc->ops->destroy    = PCDestroy_Shell;
520:   PetscNew(PC_Shell,&shell);
521:   PetscLogObjectMemory(pc,sizeof(PC_Shell));

523:   pc->data         = (void*)shell;
524:   pc->name         = 0;

526:   pc->ops->apply           = PCApply_Shell;
527:   pc->ops->view            = PCView_Shell;
528:   pc->ops->applytranspose  = PCApplyTranspose_Shell;
529:   pc->ops->applyrichardson = 0;
530:   pc->ops->setup           = PCSetUp_Shell;
531:   pc->ops->view            = PCView_Shell;

533:   shell->apply          = 0;
534:   shell->applytranspose = 0;
535:   shell->name           = 0;
536:   shell->applyrich      = 0;
537:   shell->ctxrich        = 0;
538:   shell->ctx            = 0;
539:   shell->setup          = 0;
540:   shell->view           = 0;

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

559:   return(0);
560: }
561: EXTERN_C_END