Actual source code: shellpc.c

  1: /*$Id: shellpc.c,v 1.75 2001/04/10 19:36:09 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"        /*I "petscpc.h" I*/
  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  (*applytranspose)(void *,Vec,Vec);
 16:   int  (*applyrich)(void *,Vec,Vec,Vec,int);
 17:   char *name;
 18: } PC_Shell;

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

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

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

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

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

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

 57: static int PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,int it)
 58: {
 59:   int      ierr;
 60:   PC_Shell *shell;

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

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

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

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

 85:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
 86:   if (isascii) {
 87:     if (jac->name) {PetscViewerASCIIPrintf(viewer,"  Shell: %sn",jac->name);}
 88:     else           {PetscViewerASCIIPrintf(viewer,"  Shell: no namen");}
 89:   } else {
 90:     SETERRQ1(1,"Viewer type %s not supported for PCShell",((PetscObject)viewer)->type_name);
 91:   }
 92:   return(0);
 93: }

 95: /* ------------------------------------------------------------------------------*/
 96: EXTERN_C_BEGIN
 97: int PCShellSetSetUp_Shell(PC pc, int (*setup)(void*))
 98: {
 99:   PC_Shell *shell;

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

108: EXTERN_C_BEGIN
109: int PCShellSetApply_Shell(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
110: {
111:   PC_Shell *shell;

114:   shell        = (PC_Shell*)pc->data;
115:   shell->apply = apply;
116:   shell->ctx   = ptr;
117:   return(0);
118: }
119: EXTERN_C_END

121: EXTERN_C_BEGIN
122: int PCShellSetApplyTranspose_Shell(PC pc,int (*applytranspose)(void*,Vec,Vec))
123: {
124:   PC_Shell *shell;

127:   shell                 = (PC_Shell*)pc->data;
128:   shell->applytranspose = applytranspose;
129:   return(0);
130: }
131: EXTERN_C_END

133: EXTERN_C_BEGIN
134: int PCShellSetName_Shell(PC pc,char *name)
135: {
136:   PC_Shell *shell;

139:   shell       = (PC_Shell*)pc->data;
140:   shell->name = name;
141:   return(0);
142: }
143: EXTERN_C_END

145: EXTERN_C_BEGIN
146: int PCShellGetName_Shell(PC pc,char **name)
147: {
148:   PC_Shell *shell;

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

157: EXTERN_C_BEGIN
158: int PCShellSetApplyRichardson_Shell(PC pc,int (*apply)(void*,Vec,Vec,Vec,int),void *ptr)
159: {
160:   PC_Shell *shell;

163:   shell                     = (PC_Shell*)pc->data;
164:   pc->ops->applyrichardson  = PCApplyRichardson_Shell;
165:   shell->applyrich          = apply;
166:   shell->ctxrich            = ptr;
167:   return(0);
168: }
169: EXTERN_C_END

171: /* -------------------------------------------------------------------------------*/

173: /*@C
174:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 
175:    matrix operator is changed.

177:    Collective on PC

179:    Input Parameters:
180: +  pc - the preconditioner context
181: .  setup - the application-provided setup routine

183:    Calling sequence of setup:
184: .vb
185:    int setup (void *ptr)
186: .ve

188: .  ptr - the application context

190:    Level: developer

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

194: .seealso: PCShellSetApplyRichardson(), PCShellSetApply()
195: @*/
196: int PCShellSetSetUp(PC pc,int (*setup)(void*))
197: {
198:   int ierr,(*f)(PC,int (*)(void*));

202:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)())&f);
203:   if (f) {
204:     (*f)(pc,setup);
205:   }
206:   return(0);
207: }

209: /*@C
210:    PCShellSetApply - Sets routine to use as preconditioner.

212:    Collective on PC

214:    Input Parameters:
215: +  pc - the preconditioner context
216: .  apply - the application-provided preconditioning routine
217: -  ptr - pointer to data needed by this routine

219:    Calling sequence of apply:
220: .vb
221:    int apply (void *ptr,Vec xin,Vec xout)
222: .ve

224: +  ptr - the application context
225: .  xin - input vector
226: -  xout - output vector

228:    Level: developer

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

232: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
233: @*/
234: int PCShellSetApply(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
235: {
236:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec),void *);

240:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)())&f);
241:   if (f) {
242:     (*f)(pc,apply,ptr);
243:   }
244:   return(0);
245: }

247: /*@C
248:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

250:    Collective on PC

252:    Input Parameters:
253: +  pc - the preconditioner context
254: -  apply - the application-provided preconditioning transpose routine

256:    Calling sequence of apply:
257: .vb
258:    int applytranspose (void *ptr,Vec xin,Vec xout)
259: .ve

261: +  ptr - the application context
262: .  xin - input vector
263: -  xout - output vector

265:    Level: developer

267:    Notes: 
268:    Uses the same context variable as PCShellSetApply().

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

272: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply()
273: @*/
274: int PCShellSetApplyTranspose(PC pc,int (*applytranspose)(void*,Vec,Vec))
275: {
276:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec));

280:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)())&f);
281:   if (f) {
282:     (*f)(pc,applytranspose);
283:   }
284:   return(0);
285: }

287: /*@C
288:    PCShellSetName - Sets an optional name to associate with a shell
289:    preconditioner.

291:    Not Collective

293:    Input Parameters:
294: +  pc - the preconditioner context
295: -  name - character string describing shell preconditioner

297:    Level: developer

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

301: .seealso: PCShellGetName()
302: @*/
303: int PCShellSetName(PC pc,char *name)
304: {
305:   int ierr,(*f)(PC,char *);

309:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)())&f);
310:   if (f) {
311:     (*f)(pc,name);
312:   }
313:   return(0);
314: }

316: /*@C
317:    PCShellGetName - Gets an optional name that the user has set for a shell
318:    preconditioner.

320:    Not Collective

322:    Input Parameter:
323: .  pc - the preconditioner context

325:    Output Parameter:
326: .  name - character string describing shell preconditioner

328:    Level: developer

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

332: .seealso: PCShellSetName()
333: @*/
334: int PCShellGetName(PC pc,char **name)
335: {
336:   int ierr,(*f)(PC,char **);

340:   PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)())&f);
341:   if (f) {
342:     (*f)(pc,name);
343:   } else {
344:     SETERRQ(1,"Not shell preconditioner, cannot get name");
345:   }
346:   return(0);
347: }

349: /*@C
350:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
351:    in Richardson iteration.

353:    Collective on PC

355:    Input Parameters:
356: +  pc - the preconditioner context
357: .  apply - the application-provided preconditioning routine
358: -  ptr - pointer to data needed by this routine

360:    Calling sequence of apply:
361: .vb
362:    int apply (void *ptr,Vec b,Vec x,Vec r,int maxits)
363: .ve

365: +  ptr - the application context
366: .  b - right-hand-side
367: .  x - current iterate
368: .  r - work space
369: -  maxits - number of iterations to run

371:    Level: developer

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

375: .seealso: PCShellSetApply()
376: @*/
377: int PCShellSetApplyRichardson(PC pc,int (*apply)(void*,Vec,Vec,Vec,int),void *ptr)
378: {
379:   int ierr,(*f)(PC,int (*)(void*,Vec,Vec,Vec,int),void *);

383:   PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)())&f);
384:   if (f) {
385:     (*f)(pc,apply,ptr);
386:   }
387:   return(0);
388: }

390: /*
391:    PCCreate_Shell - creates a new preconditioner class for use with your 
392:           own private data storage format. This is intended to 
393:           provide a simple class to use with KSP. You should 
394:           not use this if you plan to make a complete class.


397:   Usage:
398: $             int (*mult)(void *,Vec,Vec);
399: $             int (*setup)(void *);
400: $             PCCreate(comm,&pc);
401: $             PCSetType(pc,PC_Shell);
402: $             PCShellSetApply(pc,mult,ctx);
403: $             PCShellSetSetUp(pc,setup);       (optional)

405: */
406: EXTERN_C_BEGIN
407: int PCCreate_Shell(PC pc)
408: {
409:   int      ierr;
410:   PC_Shell *shell;

413:   pc->ops->destroy    = PCDestroy_Shell;
414:   ierr                = PetscNew(PC_Shell,&shell);
415:   PetscLogObjectMemory(pc,sizeof(PC_Shell));

417:   pc->data         = (void*)shell;
418:   pc->name         = 0;

420:   pc->ops->apply           = PCApply_Shell;
421:   pc->ops->applytranspose  = PCApplyTranspose_Shell;
422:   pc->ops->applyrichardson = 0;
423:   pc->ops->setup           = PCSetUp_Shell;
424:   pc->ops->view            = PCView_Shell;

426:   shell->apply          = 0;
427:   shell->applytranspose = 0;
428:   shell->name           = 0;
429:   shell->applyrich      = 0;
430:   shell->ctxrich        = 0;
431:   shell->ctx            = 0;
432:   shell->setup          = 0;

434:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
435:                     PCShellSetSetUp_Shell);
436:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
437:                     PCShellSetApply_Shell);
438:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C",
439:                     "PCShellSetApplyTranspose_Shell",
440:                     PCShellSetApplyTranspose_Shell);
441:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
442:                     PCShellSetName_Shell);
443:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
444:                     PCShellGetName_Shell);
445:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C",
446:                     "PCShellSetApplyRichardson_Shell",
447:                     PCShellSetApplyRichardson_Shell);

449:   return(0);
450: }
451: EXTERN_C_END