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;

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

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

 34: static int PCApply_Shell(PC pc,Vec x,Vec y)
 35: {
 36:   PC_Shell *shell;
 37:   int      ierr;

 40:   shell = (PC_Shell*)pc->data;
 41:   if (!shell->apply) SETERRQ(1,"No apply() routine provided to Shell PC");
 42:   ierr  = (*shell->apply)(shell->ctx,x,y);
 43:   return(0);
 44: }

 46: static int PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
 47: {
 48:   PC_Shell *shell;
 49:   int      ierr;

 52:   shell = (PC_Shell*)pc->data;
 53:   if (!shell->applytranspose) SETERRQ(1,"No applytranspose() routine provided to Shell PC");
 54:   ierr  = (*shell->applytranspose)(shell->ctx,x,y);
 55:   return(0);
 56: }

 58: static int PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int it)
 59: {
 60:   int      ierr;
 61:   PC_Shell *shell;

 64:   shell = (PC_Shell*)pc->data;
 65:   ierr  = (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,atol,dtol,it);
 66:   return(0);
 67: }

 69: static int PCDestroy_Shell(PC pc)
 70: {
 71:   PC_Shell *shell = (PC_Shell*)pc->data;
 72:   int      ierr;

 75:   PetscFree(shell);
 76:   return(0);
 77: }

 79: static int PCView_Shell(PC pc,PetscViewer viewer)
 80: {
 81:   PC_Shell   *shell = (PC_Shell*)pc->data;
 82:   int        ierr;
 83:   PetscTruth isascii;

 86:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
 87:   if (isascii) {
 88:     if (shell->name) {PetscViewerASCIIPrintf(viewer,"  Shell: %sn",shell->name);}
 89:     else             {PetscViewerASCIIPrintf(viewer,"  Shell: no namen");}
 90:   }
 91:   if (shell->view) {
 92:     PetscViewerASCIIPushTab(viewer);
 93:     ierr  = (*shell->view)(shell->ctx,viewer);
 94:     PetscViewerASCIIPopTab(viewer);
 95:   }
 96:   return(0);
 97: }

 99: /* ------------------------------------------------------------------------------*/
100: EXTERN_C_BEGIN
101: int PCShellSetSetUp_Shell(PC pc, int (*setup)(void*))
102: {
103:   PC_Shell *shell;

106:   shell        = (PC_Shell*)pc->data;
107:   shell->setup = setup;
108:   return(0);
109: }
110: EXTERN_C_END

112: EXTERN_C_BEGIN
113: int PCShellSetApply_Shell(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
114: {
115:   PC_Shell *shell;

118:   shell        = (PC_Shell*)pc->data;
119:   shell->apply = apply;
120:   shell->ctx   = ptr;
121:   return(0);
122: }
123: EXTERN_C_END

125: EXTERN_C_BEGIN
126: int PCShellSetView_Shell(PC pc,int (*view)(void*,PetscViewer))
127: {
128:   PC_Shell *shell;

131:   shell        = (PC_Shell*)pc->data;
132:   shell->view = view;
133:   return(0);
134: }
135: EXTERN_C_END

137: EXTERN_C_BEGIN
138: int PCShellSetApplyTranspose_Shell(PC pc,int (*applytranspose)(void*,Vec,Vec))
139: {
140:   PC_Shell *shell;

143:   shell                 = (PC_Shell*)pc->data;
144:   shell->applytranspose = applytranspose;
145:   return(0);
146: }
147: EXTERN_C_END

149: EXTERN_C_BEGIN
150: int PCShellSetName_Shell(PC pc,char *name)
151: {
152:   PC_Shell *shell;

155:   shell       = (PC_Shell*)pc->data;
156:   shell->name = name;
157:   return(0);
158: }
159: EXTERN_C_END

161: EXTERN_C_BEGIN
162: int PCShellGetName_Shell(PC pc,char **name)
163: {
164:   PC_Shell *shell;

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

173: EXTERN_C_BEGIN
174: int PCShellSetApplyRichardson_Shell(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
175: {
176:   PC_Shell *shell;

179:   shell                     = (PC_Shell*)pc->data;
180:   pc->ops->applyrichardson  = PCApplyRichardson_Shell;
181:   shell->applyrich          = apply;
182:   shell->ctxrich            = ptr;
183:   return(0);
184: }
185: EXTERN_C_END

187: /* -------------------------------------------------------------------------------*/

189: /*@C
190:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 
191:    matrix operator is changed.

193:    Collective on PC

195:    Input Parameters:
196: +  pc - the preconditioner context
197: .  setup - the application-provided setup routine

199:    Calling sequence of setup:
200: .vb
201:    int setup (void *ptr)
202: .ve

204: .  ptr - the application context

206:    Level: developer

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

210: .seealso: PCShellSetApplyRichardson(), PCShellSetApply()
211: @*/
212: int PCShellSetSetUp(PC pc,int (*setup)(void*))
213: {
214:   int ierr,(*f)(PC,int (*)(void*));

218:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&f);
219:   if (f) {
220:     (*f)(pc,setup);
221:   }
222:   return(0);
223: }


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

229:    Collective on PC

231:    Input Parameters:
232: +  pc - the preconditioner context
233: -  view - the application-provided view routine

235:    Calling sequence of apply:
236: .vb
237:    int view(void *ptr,PetscViewer v)
238: .ve

240: +  ptr - the application context
241: -  v   - viewer

243:    Level: developer

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

247: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
248: @*/
249: int PCShellSetView(PC pc,int (*view)(void*,PetscViewer))
250: {
251:   int ierr,(*f)(PC,int (*)(void*,PetscViewer));

255:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&f);
256:   if (f) {
257:     (*f)(pc,view);
258:   }
259:   return(0);
260: }

262: /*@C
263:    PCShellSetApply - Sets routine to use as preconditioner.

265:    Collective on PC

267:    Input Parameters:
268: +  pc - the preconditioner context
269: .  apply - the application-provided preconditioning routine
270: -  ptr - pointer to data needed by this routine

272:    Calling sequence of apply:
273: .vb
274:    int apply (void *ptr,Vec xin,Vec xout)
275: .ve

277: +  ptr - the application context
278: .  xin - input vector
279: -  xout - output vector

281:    Level: developer

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

285: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
286: @*/
287: int PCShellSetApply(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
288: {
289:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec),void *);

293:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&f);
294:   if (f) {
295:     (*f)(pc,apply,ptr);
296:   }
297:   return(0);
298: }

300: /*@C
301:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

303:    Collective on PC

305:    Input Parameters:
306: +  pc - the preconditioner context
307: -  apply - the application-provided preconditioning transpose routine

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

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

318:    Level: developer

320:    Notes: 
321:    Uses the same context variable as PCShellSetApply().

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

325: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply()
326: @*/
327: int PCShellSetApplyTranspose(PC pc,int (*applytranspose)(void*,Vec,Vec))
328: {
329:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec));

333:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&f);
334:   if (f) {
335:     (*f)(pc,applytranspose);
336:   }
337:   return(0);
338: }

340: /*@C
341:    PCShellSetName - Sets an optional name to associate with a shell
342:    preconditioner.

344:    Not Collective

346:    Input Parameters:
347: +  pc - the preconditioner context
348: -  name - character string describing shell preconditioner

350:    Level: developer

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

354: .seealso: PCShellGetName()
355: @*/
356: int PCShellSetName(PC pc,char *name)
357: {
358:   int ierr,(*f)(PC,char *);

362:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&f);
363:   if (f) {
364:     (*f)(pc,name);
365:   }
366:   return(0);
367: }

369: /*@C
370:    PCShellGetName - Gets an optional name that the user has set for a shell
371:    preconditioner.

373:    Not Collective

375:    Input Parameter:
376: .  pc - the preconditioner context

378:    Output Parameter:
379: .  name - character string describing shell preconditioner

381:    Level: developer

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

385: .seealso: PCShellSetName()
386: @*/
387: int PCShellGetName(PC pc,char **name)
388: {
389:   int ierr,(*f)(PC,char **);

393:   PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);
394:   if (f) {
395:     (*f)(pc,name);
396:   } else {
397:     SETERRQ(1,"Not shell preconditioner, cannot get name");
398:   }
399:   return(0);
400: }

402: /*@C
403:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
404:    in Richardson iteration.

406:    Collective on PC

408:    Input Parameters:
409: +  pc - the preconditioner context
410: .  apply - the application-provided preconditioning routine
411: -  ptr - pointer to data needed by this routine

413:    Calling sequence of apply:
414: .vb
415:    int apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal atol,PetscReal dtol,int maxits)
416: .ve

418: +  ptr - the application context
419: .  b - right-hand-side
420: .  x - current iterate
421: .  r - work space
422: .  rtol - relative tolerance of residual norm to stop at
423: .  atol - absolute tolerance of residual norm to stop at
424: .  dtol - if residual norm increases by this factor than return
425: -  maxits - number of iterations to run

427:    Level: developer

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

431: .seealso: PCShellSetApply()
432: @*/
433: int PCShellSetApplyRichardson(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
434: {
435:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *);

439:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);
440:   if (f) {
441:     (*f)(pc,apply,ptr);
442:   }
443:   return(0);
444: }

446: /*
447:    PCCreate_Shell - creates a new preconditioner class for use with your 
448:           own private data storage format. This is intended to 
449:           provide a simple class to use with KSP. You should 
450:           not use this if you plan to make a complete class.


453:   Usage:
454: $             int (*mult)(void *,Vec,Vec);
455: $             int (*setup)(void *);
456: $             PCCreate(comm,&pc);
457: $             PCSetType(pc,PC_Shell);
458: $             PCShellSetApply(pc,mult,ctx);
459: $             PCShellSetSetUp(pc,setup);       (optional)

461: */
462: EXTERN_C_BEGIN
463: int PCCreate_Shell(PC pc)
464: {
465:   int      ierr;
466:   PC_Shell *shell;

469:   pc->ops->destroy    = PCDestroy_Shell;
470:   ierr                = PetscNew(PC_Shell,&shell);
471:   PetscLogObjectMemory(pc,sizeof(PC_Shell));

473:   pc->data         = (void*)shell;
474:   pc->name         = 0;

476:   pc->ops->apply           = PCApply_Shell;
477:   pc->ops->view            = PCView_Shell;
478:   pc->ops->applytranspose  = PCApplyTranspose_Shell;
479:   pc->ops->applyrichardson = 0;
480:   pc->ops->setup           = PCSetUp_Shell;
481:   pc->ops->view            = PCView_Shell;

483:   shell->apply          = 0;
484:   shell->applytranspose = 0;
485:   shell->name           = 0;
486:   shell->applyrich      = 0;
487:   shell->ctxrich        = 0;
488:   shell->ctx            = 0;
489:   shell->setup          = 0;
490:   shell->view           = 0;

492:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
493:                     PCShellSetSetUp_Shell);
494:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
495:                     PCShellSetApply_Shell);
496:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell",
497:                     PCShellSetView_Shell);
498:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C",
499:                     "PCShellSetApplyTranspose_Shell",
500:                     PCShellSetApplyTranspose_Shell);
501:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
502:                     PCShellSetName_Shell);
503:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
504:                     PCShellGetName_Shell);
505:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C",
506:                     "PCShellSetApplyRichardson_Shell",
507:                     PCShellSetApplyRichardson_Shell);

509:   return(0);
510: }
511: EXTERN_C_END