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: #undef __FUNCT__  
 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:     ierr  = (*shell->setup)(shell->ctx);
 32:   }
 33:   return(0);
 34: }

 36: #undef __FUNCT__  
 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:   ierr  = (*shell->apply)(shell->ctx,x,y);
 47:   return(0);
 48: }

 50: #undef __FUNCT__  
 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:   ierr  = (*shell->applytranspose)(shell->ctx,x,y);
 61:   return(0);
 62: }

 64: #undef __FUNCT__  
 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:   ierr  = (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,atol,dtol,it);
 74:   return(0);
 75: }

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

 85:   PetscFree(shell);
 86:   return(0);
 87: }

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

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

111: /* ------------------------------------------------------------------------------*/
112: EXTERN_C_BEGIN
113: #undef __FUNCT__  
115: int PCShellSetSetUp_Shell(PC pc, int (*setup)(void*))
116: {
117:   PC_Shell *shell;

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

126: EXTERN_C_BEGIN
127: #undef __FUNCT__  
129: int PCShellSetApply_Shell(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
130: {
131:   PC_Shell *shell;

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

141: EXTERN_C_BEGIN
142: #undef __FUNCT__  
144: int PCShellSetView_Shell(PC pc,int (*view)(void*,PetscViewer))
145: {
146:   PC_Shell *shell;

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

155: EXTERN_C_BEGIN
156: #undef __FUNCT__  
158: int PCShellSetApplyTranspose_Shell(PC pc,int (*applytranspose)(void*,Vec,Vec))
159: {
160:   PC_Shell *shell;

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

169: EXTERN_C_BEGIN
170: #undef __FUNCT__  
172: int PCShellSetName_Shell(PC pc,char *name)
173: {
174:   PC_Shell *shell;

177:   shell       = (PC_Shell*)pc->data;
178:   shell->name = name;
179:   return(0);
180: }
181: EXTERN_C_END

183: EXTERN_C_BEGIN
184: #undef __FUNCT__  
186: int PCShellGetName_Shell(PC pc,char **name)
187: {
188:   PC_Shell *shell;

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

197: EXTERN_C_BEGIN
198: #undef __FUNCT__  
200: int PCShellSetApplyRichardson_Shell(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
201: {
202:   PC_Shell *shell;

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

213: /* -------------------------------------------------------------------------------*/

215: #undef __FUNCT__  
217: /*@C
218:    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the 
219:    matrix operator is changed.

221:    Collective on PC

223:    Input Parameters:
224: +  pc - the preconditioner context
225: .  setup - the application-provided setup routine

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

232: .  ptr - the application context

234:    Level: developer

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

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

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


254: #undef __FUNCT__  
256: /*@C
257:    PCShellSetView - Sets routine to use as viewer of shell preconditioner

259:    Collective on PC

261:    Input Parameters:
262: +  pc - the preconditioner context
263: -  view - the application-provided view routine

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

270: +  ptr - the application context
271: -  v   - viewer

273:    Level: developer

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

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

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

292: #undef __FUNCT__  
294: /*@C
295:    PCShellSetApply - Sets routine to use as preconditioner.

297:    Collective on PC

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

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

309: +  ptr - the application context
310: .  xin - input vector
311: -  xout - output vector

313:    Level: developer

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

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

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

332: #undef __FUNCT__  
334: /*@C
335:    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

337:    Collective on PC

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

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

348: +  ptr - the application context
349: .  xin - input vector
350: -  xout - output vector

352:    Level: developer

354:    Notes: 
355:    Uses the same context variable as PCShellSetApply().

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

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

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

374: #undef __FUNCT__  
376: /*@C
377:    PCShellSetName - Sets an optional name to associate with a shell
378:    preconditioner.

380:    Not Collective

382:    Input Parameters:
383: +  pc - the preconditioner context
384: -  name - character string describing shell preconditioner

386:    Level: developer

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

390: .seealso: PCShellGetName()
391: @*/
392: int PCShellSetName(PC pc,char *name)
393: {
394:   int ierr,(*f)(PC,char *);

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

405: #undef __FUNCT__  
407: /*@C
408:    PCShellGetName - Gets an optional name that the user has set for a shell
409:    preconditioner.

411:    Not Collective

413:    Input Parameter:
414: .  pc - the preconditioner context

416:    Output Parameter:
417: .  name - character string describing shell preconditioner

419:    Level: developer

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

423: .seealso: PCShellSetName()
424: @*/
425: int PCShellGetName(PC pc,char **name)
426: {
427:   int ierr,(*f)(PC,char **);

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

440: #undef __FUNCT__  
442: /*@C
443:    PCShellSetApplyRichardson - Sets routine to use as preconditioner
444:    in Richardson iteration.

446:    Collective on PC

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

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

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

467:    Level: developer

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

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

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

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

490:    Level: advanced

492:    Concepts: providing your own preconditioner

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

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

508: EXTERN_C_BEGIN
509: #undef __FUNCT__  
511: int PCCreate_Shell(PC pc)
512: {
513:   int      ierr;
514:   PC_Shell *shell;

517:   pc->ops->destroy    = PCDestroy_Shell;
518:   ierr                = PetscNew(PC_Shell,&shell);
519:   PetscLogObjectMemory(pc,sizeof(PC_Shell));

521:   pc->data         = (void*)shell;
522:   pc->name         = 0;

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

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

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

557:   return(0);
558: }
559: EXTERN_C_END