Actual source code: shellpc.c
1: #define PETSCKSP_DLL
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
12: typedef struct {
13: void *ctx; /* user provided contexts for preconditioner */
14: PetscErrorCode (*setup)(void*);
15: PetscErrorCode (*apply)(void*,Vec,Vec);
16: PetscErrorCode (*presolve)(void*,KSP,Vec,Vec);
17: PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec);
18: PetscErrorCode (*view)(void*,PetscViewer);
19: PetscErrorCode (*applytranspose)(void*,Vec,Vec);
20: PetscErrorCode (*applyrich)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt);
21: char *name;
22: } PC_Shell;
27: /*@
28: PCShellGetContext - Returns the user-provided context associated with a shell PC
30: Not Collective
32: Input Parameter:
33: . pc - should have been created with PCCreateShell()
35: Output Parameter:
36: . ctx - the user provided context
38: Level: advanced
40: Notes:
41: This routine is intended for use within various shell routines
42:
43: .keywords: PC, shell, get, context
45: .seealso: PCCreateShell(), PCShellSetContext()
46: @*/
47: PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetContext(PC pc,void **ctx)
48: {
50: PetscTruth flg;
55: PetscTypeCompare((PetscObject)pc,PCSHELL,&flg);
56: if (!flg) *ctx = 0;
57: else *ctx = ((PC_Shell*)(pc->data))->ctx;
58: return(0);
59: }
63: /*@C
64: PCShellSetContext - sets the context for a shell PC
66: Collective on PC
68: Input Parameters:
69: + pc - the shell PC
70: - ctx - the context
72: Level: advanced
74: Fortran Notes: The context can only be an integer or a PetscObject
75: unfortunately it cannot be a Fortran array or derived type.
77: .seealso: PCCreateShell(), PCShellGetContext()
78: @*/
79: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetContext(PC pc,void *ctx)
80: {
81: PC_Shell *shell = (PC_Shell*)pc->data;
83: PetscTruth flg;
87: PetscTypeCompare((PetscObject)pc,PCSHELL,&flg);
88: if (flg) {
89: shell->ctx = ctx;
90: }
91: return(0);
92: }
96: static PetscErrorCode PCSetUp_Shell(PC pc)
97: {
98: PC_Shell *shell;
102: shell = (PC_Shell*)pc->data;
103: if (shell->setup) {
104: (*shell->setup)(shell->ctx);
105: }
106: return(0);
107: }
111: static PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y)
112: {
113: PC_Shell *shell;
117: shell = (PC_Shell*)pc->data;
118: if (!shell->apply) SETERRQ(PETSC_ERR_USER,"No apply() routine provided to Shell PC");
119: (*shell->apply)(shell->ctx,x,y);
120: return(0);
121: }
125: static PetscErrorCode PCPreSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
126: {
127: PC_Shell *shell;
131: shell = (PC_Shell*)pc->data;
132: if (!shell->presolve) SETERRQ(PETSC_ERR_USER,"No presolve() routine provided to Shell PC");
133: (*shell->presolve)(shell->ctx,ksp,b,x);
134: return(0);
135: }
139: static PetscErrorCode PCPostSolve_Shell(PC pc,KSP ksp,Vec b,Vec x)
140: {
141: PC_Shell *shell;
145: shell = (PC_Shell*)pc->data;
146: if (!shell->postsolve) SETERRQ(PETSC_ERR_USER,"No postsolve() routine provided to Shell PC");
147: (*shell->postsolve)(shell->ctx,ksp,b,x);
148: return(0);
149: }
153: static PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
154: {
155: PC_Shell *shell;
159: shell = (PC_Shell*)pc->data;
160: if (!shell->applytranspose) SETERRQ(PETSC_ERR_USER,"No applytranspose() routine provided to Shell PC");
161: (*shell->applytranspose)(shell->ctx,x,y);
162: return(0);
163: }
167: static PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it)
168: {
170: PC_Shell *shell;
173: shell = (PC_Shell*)pc->data;
174: (*shell->applyrich)(shell->ctx,x,y,w,rtol,abstol,dtol,it);
175: return(0);
176: }
180: static PetscErrorCode PCDestroy_Shell(PC pc)
181: {
182: PC_Shell *shell = (PC_Shell*)pc->data;
186: if (shell->name) {PetscFree(shell->name);}
187: PetscFree(shell);
188: return(0);
189: }
193: static PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer)
194: {
195: PC_Shell *shell = (PC_Shell*)pc->data;
197: PetscTruth iascii;
200: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
201: if (iascii) {
202: if (shell->name) {PetscViewerASCIIPrintf(viewer," Shell: %s\n",shell->name);}
203: else {PetscViewerASCIIPrintf(viewer," Shell: no name\n");}
204: }
205: if (shell->view) {
206: PetscViewerASCIIPushTab(viewer);
207: (*shell->view)(shell->ctx,viewer);
208: PetscViewerASCIIPopTab(viewer);
209: }
210: return(0);
211: }
213: /* ------------------------------------------------------------------------------*/
217: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(void*))
218: {
219: PC_Shell *shell;
222: shell = (PC_Shell*)pc->data;
223: shell->setup = setup;
224: return(0);
225: }
231: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec))
232: {
233: PC_Shell *shell;
236: shell = (PC_Shell*)pc->data;
237: shell->apply = apply;
238: return(0);
239: }
245: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPreSolve_Shell(PC pc,PetscErrorCode (*presolve)(void*,KSP,Vec,Vec))
246: {
247: PC_Shell *shell;
250: shell = (PC_Shell*)pc->data;
251: shell->presolve = presolve;
252: if (presolve) {
253: pc->ops->presolve = PCPreSolve_Shell;
254: } else {
255: pc->ops->presolve = 0;
256: }
257: return(0);
258: }
264: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPostSolve_Shell(PC pc,PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec))
265: {
266: PC_Shell *shell;
269: shell = (PC_Shell*)pc->data;
270: shell->postsolve = postsolve;
271: if (postsolve) {
272: pc->ops->postsolve = PCPostSolve_Shell;
273: } else {
274: pc->ops->postsolve = 0;
275: }
276: return(0);
277: }
283: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView_Shell(PC pc,PetscErrorCode (*view)(void*,PetscViewer))
284: {
285: PC_Shell *shell;
288: shell = (PC_Shell*)pc->data;
289: shell->view = view;
290: return(0);
291: }
297: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec))
298: {
299: PC_Shell *shell;
302: shell = (PC_Shell*)pc->data;
303: shell->applytranspose = applytranspose;
304: return(0);
305: }
311: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName_Shell(PC pc,const char name[])
312: {
313: PC_Shell *shell;
317: shell = (PC_Shell*)pc->data;
318: PetscStrallocpy(name,&shell->name);
319: return(0);
320: }
326: PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName_Shell(PC pc,char *name[])
327: {
328: PC_Shell *shell;
331: shell = (PC_Shell*)pc->data;
332: *name = shell->name;
333: return(0);
334: }
340: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt))
341: {
342: PC_Shell *shell;
345: shell = (PC_Shell*)pc->data;
346: pc->ops->applyrichardson = PCApplyRichardson_Shell;
347: shell->applyrich = apply;
348: return(0);
349: }
352: /* -------------------------------------------------------------------------------*/
356: /*@C
357: PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
358: matrix operator is changed.
360: Collective on PC
362: Input Parameters:
363: + pc - the preconditioner context
364: . setup - the application-provided setup routine
366: Calling sequence of setup:
367: .vb
368: PetscErrorCode setup (void *ptr)
369: .ve
371: . ptr - the application context
373: Level: developer
375: .keywords: PC, shell, set, setup, user-provided
377: .seealso: PCShellSetApplyRichardson(), PCShellSetApply(), PCShellSetContext()
378: @*/
379: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(void*))
380: {
381: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*));
385: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&f);
386: if (f) {
387: (*f)(pc,setup);
388: }
389: return(0);
390: }
395: /*@C
396: PCShellSetView - Sets routine to use as viewer of shell preconditioner
398: Collective on PC
400: Input Parameters:
401: + pc - the preconditioner context
402: - view - the application-provided view routine
404: Calling sequence of apply:
405: .vb
406: PetscErrorCode view(void *ptr,PetscViewer v)
407: .ve
409: + ptr - the application context
410: - v - viewer
412: Level: developer
414: .keywords: PC, shell, set, apply, user-provided
416: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
417: @*/
418: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView(PC pc,PetscErrorCode (*view)(void*,PetscViewer))
419: {
420: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,PetscViewer));
424: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&f);
425: if (f) {
426: (*f)(pc,view);
427: }
428: return(0);
429: }
433: /*@C
434: PCShellSetApply - Sets routine to use as preconditioner.
436: Collective on PC
438: Input Parameters:
439: + pc - the preconditioner context
440: - apply - the application-provided preconditioning routine
442: Calling sequence of apply:
443: .vb
444: PetscErrorCode apply (void *ptr,Vec xin,Vec xout)
445: .ve
447: + ptr - the application context
448: . xin - input vector
449: - xout - output vector
451: Level: developer
453: .keywords: PC, shell, set, apply, user-provided
455: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
456: @*/
457: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec))
458: {
459: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec));
463: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&f);
464: if (f) {
465: (*f)(pc,apply);
466: }
467: return(0);
468: }
472: /*@C
473: PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.
475: Collective on PC
477: Input Parameters:
478: + pc - the preconditioner context
479: - apply - the application-provided preconditioning transpose routine
481: Calling sequence of apply:
482: .vb
483: PetscErrorCode applytranspose (void *ptr,Vec xin,Vec xout)
484: .ve
486: + ptr - the application context
487: . xin - input vector
488: - xout - output vector
490: Level: developer
492: Notes:
493: Uses the same context variable as PCShellSetApply().
495: .keywords: PC, shell, set, apply, user-provided
497: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext()
498: @*/
499: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec))
500: {
501: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec));
505: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&f);
506: if (f) {
507: (*f)(pc,applytranspose);
508: }
509: return(0);
510: }
514: /*@C
515: PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is
516: applied. This usually does something like scale the linear system in some application
517: specific way.
519: Collective on PC
521: Input Parameters:
522: + pc - the preconditioner context
523: - presolve - the application-provided presolve routine
525: Calling sequence of presolve:
526: .vb
527: PetscErrorCode presolve (void *ptr,KSP ksp,Vec b,Vec x)
528: .ve
530: + ptr - the application context
531: . xin - input vector
532: - xout - output vector
534: Level: developer
536: .keywords: PC, shell, set, apply, user-provided
538: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext()
539: @*/
540: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(void*,KSP,Vec,Vec))
541: {
542: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,KSP,Vec,Vec));
546: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetPreSolve_C",(void (**)(void))&f);
547: if (f) {
548: (*f)(pc,presolve);
549: }
550: return(0);
551: }
555: /*@C
556: PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is
557: applied. This usually does something like scale the linear system in some application
558: specific way.
560: Collective on PC
562: Input Parameters:
563: + pc - the preconditioner context
564: - postsolve - the application-provided presolve routine
566: Calling sequence of postsolve:
567: .vb
568: PetscErrorCode postsolve(void *ptr,KSP ksp,Vec b,Vec x)
569: .ve
571: + ptr - the application context
572: . xin - input vector
573: - xout - output vector
575: Level: developer
577: .keywords: PC, shell, set, apply, user-provided
579: .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext()
580: @*/
581: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(void*,KSP,Vec,Vec))
582: {
583: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,KSP,Vec,Vec));
587: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetPostSolve_C",(void (**)(void))&f);
588: if (f) {
589: (*f)(pc,postsolve);
590: }
591: return(0);
592: }
596: /*@C
597: PCShellSetName - Sets an optional name to associate with a shell
598: preconditioner.
600: Not Collective
602: Input Parameters:
603: + pc - the preconditioner context
604: - name - character string describing shell preconditioner
606: Level: developer
608: .keywords: PC, shell, set, name, user-provided
610: .seealso: PCShellGetName()
611: @*/
612: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName(PC pc,const char name[])
613: {
614: PetscErrorCode ierr,(*f)(PC,const char []);
618: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&f);
619: if (f) {
620: (*f)(pc,name);
621: }
622: return(0);
623: }
627: /*@C
628: PCShellGetName - Gets an optional name that the user has set for a shell
629: preconditioner.
631: Not Collective
633: Input Parameter:
634: . pc - the preconditioner context
636: Output Parameter:
637: . name - character string describing shell preconditioner (you should not free this)
639: Level: developer
641: .keywords: PC, shell, get, name, user-provided
643: .seealso: PCShellSetName()
644: @*/
645: PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName(PC pc,char *name[])
646: {
647: PetscErrorCode ierr,(*f)(PC,char *[]);
652: PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);
653: if (f) {
654: (*f)(pc,name);
655: } else {
656: SETERRQ(PETSC_ERR_ARG_WRONG,"Not shell preconditioner, cannot get name");
657: }
658: return(0);
659: }
663: /*@C
664: PCShellSetApplyRichardson - Sets routine to use as preconditioner
665: in Richardson iteration.
667: Collective on PC
669: Input Parameters:
670: + pc - the preconditioner context
671: - apply - the application-provided preconditioning routine
673: Calling sequence of apply:
674: .vb
675: PetscErrorCode apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits)
676: .ve
678: + ptr - the application context
679: . b - right-hand-side
680: . x - current iterate
681: . r - work space
682: . rtol - relative tolerance of residual norm to stop at
683: . abstol - absolute tolerance of residual norm to stop at
684: . dtol - if residual norm increases by this factor than return
685: - maxits - number of iterations to run
687: Level: developer
689: .keywords: PC, shell, set, apply, Richardson, user-provided
691: .seealso: PCShellSetApply(), PCShellSetContext()
692: @*/
693: PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt))
694: {
695: PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt));
699: PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);
700: if (f) {
701: (*f)(pc,apply);
702: }
703: return(0);
704: }
706: /*MC
707: PCSHELL - Creates a new preconditioner class for use with your
708: own private data storage format.
710: Level: advanced
712: Concepts: providing your own preconditioner
714: Usage:
715: $ PetscErrorCode (*mult)(void*,Vec,Vec);
716: $ PetscErrorCode (*setup)(void*);
717: $ PCCreate(comm,&pc);
718: $ PCSetType(pc,PCSHELL);
719: $ PCShellSetApply(pc,mult);
720: $ PCShellSetContext(pc,ctx)
721: $ PCShellSetSetUp(pc,setup); (optional)
723: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
724: MATSHELL, PCShellSetUp(), PCShellSetApply(), PCShellSetView(),
725: PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(),
726: PCShellGetName(), PCShellSetContext(), PCShellGetContext()
727: M*/
732: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Shell(PC pc)
733: {
735: PC_Shell *shell;
738: pc->ops->destroy = PCDestroy_Shell;
739: PetscNew(PC_Shell,&shell);
740: PetscLogObjectMemory(pc,sizeof(PC_Shell));
741: pc->data = (void*)shell;
742: pc->name = 0;
744: pc->ops->apply = PCApply_Shell;
745: pc->ops->view = PCView_Shell;
746: pc->ops->applytranspose = PCApplyTranspose_Shell;
747: pc->ops->applyrichardson = 0;
748: pc->ops->setup = PCSetUp_Shell;
749: pc->ops->presolve = 0;
750: pc->ops->postsolve = 0;
751: pc->ops->view = PCView_Shell;
753: shell->apply = 0;
754: shell->applytranspose = 0;
755: shell->name = 0;
756: shell->applyrich = 0;
757: shell->presolve = 0;
758: shell->postsolve = 0;
759: shell->ctx = 0;
760: shell->setup = 0;
761: shell->view = 0;
763: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
764: PCShellSetSetUp_Shell);
765: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
766: PCShellSetApply_Shell);
767: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetPreSolve_C","PCShellSetPreSolve_Shell",
768: PCShellSetPreSolve_Shell);
769: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetPostSolve_C","PCShellSetPostSolve_Shell",
770: PCShellSetPostSolve_Shell);
771: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell",
772: PCShellSetView_Shell);
773: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C","PCShellSetApplyTranspose_Shell",
774: PCShellSetApplyTranspose_Shell);
775: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
776: PCShellSetName_Shell);
777: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
778: PCShellGetName_Shell);
779: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C","PCShellSetApplyRichardson_Shell",
780: PCShellSetApplyRichardson_Shell);
781: return(0);
782: }