Actual source code: shellpc.c
1: /*
2: This provides a simple shell for Fortran (and C programmers) to
3: create their own preconditioner without writing much interface code.
4: */
6: #include <petsc/private/pcimpl.h>
8: typedef struct {
9: void *ctx; /* user provided contexts for preconditioner */
11: PetscErrorCode (*destroy)(PC);
12: PetscErrorCode (*setup)(PC);
13: PetscErrorCode (*apply)(PC, Vec, Vec);
14: PetscErrorCode (*matapply)(PC, Mat, Mat);
15: PetscErrorCode (*applysymmetricleft)(PC, Vec, Vec);
16: PetscErrorCode (*applysymmetricright)(PC, Vec, Vec);
17: PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec);
18: PetscErrorCode (*presolve)(PC, KSP, Vec, Vec);
19: PetscErrorCode (*postsolve)(PC, KSP, Vec, Vec);
20: PetscErrorCode (*view)(PC, PetscViewer);
21: PetscErrorCode (*applytranspose)(PC, Vec, Vec);
22: PetscErrorCode (*applyrich)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *);
24: char *name;
25: } PC_Shell;
27: /*@C
28: PCShellGetContext - Returns the user-provided context associated with a shell `PC` that was provided with `PCShellSetContext()`
30: Not Collective
32: Input Parameter:
33: . pc - of type `PCSHELL`
35: Output Parameter:
36: . ctx - the user provided context
38: Level: advanced
40: Note:
41: This routine is intended for use within the various user-provided routines set with, for example, `PCShellSetApply()`
43: Fortran Note:
44: To use this from Fortran you must write a Fortran interface definition for this
45: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
47: .seealso: [](ch_ksp), `PC`, `PCSHELL`, `PCShellSetContext()`, `PCShellSetApply()`, `PCShellSetDestroy()`
48: @*/
49: PetscErrorCode PCShellGetContext(PC pc, void *ctx)
50: {
51: PetscBool flg;
53: PetscFunctionBegin;
55: PetscAssertPointer(ctx, 2);
56: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCSHELL, &flg));
57: if (!flg) *(void **)ctx = NULL;
58: else *(void **)ctx = ((PC_Shell *)pc->data)->ctx;
59: PetscFunctionReturn(PETSC_SUCCESS);
60: }
62: /*@
63: PCShellSetContext - sets the context for a shell `PC` that can be accessed with `PCShellGetContext()`
65: Logically Collective
67: Input Parameters:
68: + pc - the `PC` of type `PCSHELL`
69: - ctx - the context
71: Level: advanced
73: Notes:
74: This routine is intended for use within the various user-provided routines set with, for example, `PCShellSetApply()`
76: One should also provide a routine to destroy the context when `pc` is destroyed with `PCShellSetDestroy()`
78: Fortran Notes:
79: To use this from Fortran you must write a Fortran interface definition for this
80: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
82: .seealso: [](ch_ksp), `PC`, `PCShellGetContext()`, `PCSHELL`, `PCShellSetApply()`, `PCShellSetDestroy()`
83: @*/
84: PetscErrorCode PCShellSetContext(PC pc, void *ctx)
85: {
86: PC_Shell *shell = (PC_Shell *)pc->data;
87: PetscBool flg;
89: PetscFunctionBegin;
91: PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCSHELL, &flg));
92: if (flg) shell->ctx = ctx;
93: PetscFunctionReturn(PETSC_SUCCESS);
94: }
96: static PetscErrorCode PCSetUp_Shell(PC pc)
97: {
98: PC_Shell *shell = (PC_Shell *)pc->data;
100: PetscFunctionBegin;
101: PetscCheck(shell->setup, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No setup() routine provided to Shell PC");
102: PetscCallBack("PCSHELL callback setup", (*shell->setup)(pc));
103: PetscFunctionReturn(PETSC_SUCCESS);
104: }
106: static PetscErrorCode PCApply_Shell(PC pc, Vec x, Vec y)
107: {
108: PC_Shell *shell = (PC_Shell *)pc->data;
109: PetscObjectState instate, outstate;
111: PetscFunctionBegin;
112: PetscCheck(shell->apply, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
113: PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
114: PetscCallBack("PCSHELL callback apply", (*shell->apply)(pc, x, y));
115: PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
116: /* increase the state of the output vector if the user did not update its state themself as should have been done */
117: if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
118: PetscFunctionReturn(PETSC_SUCCESS);
119: }
121: static PetscErrorCode PCMatApply_Shell(PC pc, Mat X, Mat Y)
122: {
123: PC_Shell *shell = (PC_Shell *)pc->data;
124: PetscObjectState instate, outstate;
126: PetscFunctionBegin;
127: PetscCheck(shell->matapply, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
128: PetscCall(PetscObjectStateGet((PetscObject)Y, &instate));
129: PetscCallBack("PCSHELL callback apply", (*shell->matapply)(pc, X, Y));
130: PetscCall(PetscObjectStateGet((PetscObject)Y, &outstate));
131: /* increase the state of the output vector if the user did not update its state themself as should have been done */
132: if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)Y));
133: PetscFunctionReturn(PETSC_SUCCESS);
134: }
136: static PetscErrorCode PCApplySymmetricLeft_Shell(PC pc, Vec x, Vec y)
137: {
138: PC_Shell *shell = (PC_Shell *)pc->data;
140: PetscFunctionBegin;
141: PetscCheck(shell->applysymmetricleft, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
142: PetscCallBack("PCSHELL callback apply symmetric left", (*shell->applysymmetricleft)(pc, x, y));
143: PetscFunctionReturn(PETSC_SUCCESS);
144: }
146: static PetscErrorCode PCApplySymmetricRight_Shell(PC pc, Vec x, Vec y)
147: {
148: PC_Shell *shell = (PC_Shell *)pc->data;
150: PetscFunctionBegin;
151: PetscCheck(shell->applysymmetricright, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
152: PetscCallBack("PCSHELL callback apply symmetric right", (*shell->applysymmetricright)(pc, x, y));
153: PetscFunctionReturn(PETSC_SUCCESS);
154: }
156: static PetscErrorCode PCApplyBA_Shell(PC pc, PCSide side, Vec x, Vec y, Vec w)
157: {
158: PC_Shell *shell = (PC_Shell *)pc->data;
159: PetscObjectState instate, outstate;
161: PetscFunctionBegin;
162: PetscCheck(shell->applyBA, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applyBA() routine provided to Shell PC");
163: PetscCall(PetscObjectStateGet((PetscObject)w, &instate));
164: PetscCallBack("PCSHELL callback applyBA", (*shell->applyBA)(pc, side, x, y, w));
165: PetscCall(PetscObjectStateGet((PetscObject)w, &outstate));
166: /* increase the state of the output vector if the user did not update its state themself as should have been done */
167: if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)w));
168: PetscFunctionReturn(PETSC_SUCCESS);
169: }
171: static PetscErrorCode PCPreSolveChangeRHS_Shell(PC pc, PetscBool *change)
172: {
173: PetscFunctionBegin;
174: *change = PETSC_TRUE;
175: PetscFunctionReturn(PETSC_SUCCESS);
176: }
178: static PetscErrorCode PCPreSolve_Shell(PC pc, KSP ksp, Vec b, Vec x)
179: {
180: PC_Shell *shell = (PC_Shell *)pc->data;
182: PetscFunctionBegin;
183: PetscCheck(shell->presolve, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No presolve() routine provided to Shell PC");
184: PetscCallBack("PCSHELL callback presolve", (*shell->presolve)(pc, ksp, b, x));
185: PetscFunctionReturn(PETSC_SUCCESS);
186: }
188: static PetscErrorCode PCPostSolve_Shell(PC pc, KSP ksp, Vec b, Vec x)
189: {
190: PC_Shell *shell = (PC_Shell *)pc->data;
192: PetscFunctionBegin;
193: PetscCheck(shell->postsolve, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No postsolve() routine provided to Shell PC");
194: PetscCallBack("PCSHELL callback postsolve()", (*shell->postsolve)(pc, ksp, b, x));
195: PetscFunctionReturn(PETSC_SUCCESS);
196: }
198: static PetscErrorCode PCApplyTranspose_Shell(PC pc, Vec x, Vec y)
199: {
200: PC_Shell *shell = (PC_Shell *)pc->data;
201: PetscObjectState instate, outstate;
203: PetscFunctionBegin;
204: PetscCheck(shell->applytranspose, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applytranspose() routine provided to Shell PC");
205: PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
206: PetscCallBack("PCSHELL callback applytranspose", (*shell->applytranspose)(pc, x, y));
207: PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
208: /* increase the state of the output vector if the user did not update its state themself as should have been done */
209: if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: static PetscErrorCode PCApplyRichardson_Shell(PC pc, Vec x, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt it, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
214: {
215: PC_Shell *shell = (PC_Shell *)pc->data;
216: PetscObjectState instate, outstate;
218: PetscFunctionBegin;
219: PetscCheck(shell->applyrich, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applyrichardson() routine provided to Shell PC");
220: PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
221: PetscCallBack("PCSHELL callback applyrichardson", (*shell->applyrich)(pc, x, y, w, rtol, abstol, dtol, it, guesszero, outits, reason));
222: PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
223: /* increase the state of the output vector since the user did not update its state themself as should have been done */
224: if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
225: PetscFunctionReturn(PETSC_SUCCESS);
226: }
228: static PetscErrorCode PCDestroy_Shell(PC pc)
229: {
230: PC_Shell *shell = (PC_Shell *)pc->data;
232: PetscFunctionBegin;
233: PetscCall(PetscFree(shell->name));
234: if (shell->destroy) PetscCallBack("PCSHELL callback destroy", (*shell->destroy)(pc));
235: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetDestroy_C", NULL));
236: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetSetUp_C", NULL));
237: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApply_C", NULL));
238: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApply_C", NULL));
239: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricLeft_C", NULL));
240: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricRight_C", NULL));
241: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyBA_C", NULL));
242: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPreSolve_C", NULL));
243: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPostSolve_C", NULL));
244: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetView_C", NULL));
245: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyTranspose_C", NULL));
246: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetName_C", NULL));
247: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellGetName_C", NULL));
248: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyRichardson_C", NULL));
249: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
250: PetscCall(PetscFree(pc->data));
251: PetscFunctionReturn(PETSC_SUCCESS);
252: }
254: static PetscErrorCode PCView_Shell(PC pc, PetscViewer viewer)
255: {
256: PC_Shell *shell = (PC_Shell *)pc->data;
257: PetscBool iascii;
259: PetscFunctionBegin;
260: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
261: if (iascii) {
262: if (shell->name) PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", shell->name));
263: else PetscCall(PetscViewerASCIIPrintf(viewer, " no name\n"));
264: }
265: if (shell->view) {
266: PetscCall(PetscViewerASCIIPushTab(viewer));
267: PetscCall((*shell->view)(pc, viewer));
268: PetscCall(PetscViewerASCIIPopTab(viewer));
269: }
270: PetscFunctionReturn(PETSC_SUCCESS);
271: }
273: static PetscErrorCode PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(PC))
274: {
275: PC_Shell *shell = (PC_Shell *)pc->data;
277: PetscFunctionBegin;
278: shell->destroy = destroy;
279: PetscFunctionReturn(PETSC_SUCCESS);
280: }
282: static PetscErrorCode PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(PC))
283: {
284: PC_Shell *shell = (PC_Shell *)pc->data;
286: PetscFunctionBegin;
287: shell->setup = setup;
288: if (setup) pc->ops->setup = PCSetUp_Shell;
289: else pc->ops->setup = NULL;
290: PetscFunctionReturn(PETSC_SUCCESS);
291: }
293: static PetscErrorCode PCShellSetApply_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
294: {
295: PC_Shell *shell = (PC_Shell *)pc->data;
297: PetscFunctionBegin;
298: shell->apply = apply;
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: static PetscErrorCode PCShellSetMatApply_Shell(PC pc, PetscErrorCode (*matapply)(PC, Mat, Mat))
303: {
304: PC_Shell *shell = (PC_Shell *)pc->data;
306: PetscFunctionBegin;
307: shell->matapply = matapply;
308: if (matapply) pc->ops->matapply = PCMatApply_Shell;
309: else pc->ops->matapply = NULL;
310: PetscFunctionReturn(PETSC_SUCCESS);
311: }
313: static PetscErrorCode PCShellSetApplySymmetricLeft_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
314: {
315: PC_Shell *shell = (PC_Shell *)pc->data;
317: PetscFunctionBegin;
318: shell->applysymmetricleft = apply;
319: PetscFunctionReturn(PETSC_SUCCESS);
320: }
322: static PetscErrorCode PCShellSetApplySymmetricRight_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
323: {
324: PC_Shell *shell = (PC_Shell *)pc->data;
326: PetscFunctionBegin;
327: shell->applysymmetricright = apply;
328: PetscFunctionReturn(PETSC_SUCCESS);
329: }
331: static PetscErrorCode PCShellSetApplyBA_Shell(PC pc, PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec))
332: {
333: PC_Shell *shell = (PC_Shell *)pc->data;
335: PetscFunctionBegin;
336: shell->applyBA = applyBA;
337: if (applyBA) pc->ops->applyBA = PCApplyBA_Shell;
338: else pc->ops->applyBA = NULL;
339: PetscFunctionReturn(PETSC_SUCCESS);
340: }
342: static PetscErrorCode PCShellSetPreSolve_Shell(PC pc, PetscErrorCode (*presolve)(PC, KSP, Vec, Vec))
343: {
344: PC_Shell *shell = (PC_Shell *)pc->data;
346: PetscFunctionBegin;
347: shell->presolve = presolve;
348: if (presolve) {
349: pc->ops->presolve = PCPreSolve_Shell;
350: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_Shell));
351: } else {
352: pc->ops->presolve = NULL;
353: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
354: }
355: PetscFunctionReturn(PETSC_SUCCESS);
356: }
358: static PetscErrorCode PCShellSetPostSolve_Shell(PC pc, PetscErrorCode (*postsolve)(PC, KSP, Vec, Vec))
359: {
360: PC_Shell *shell = (PC_Shell *)pc->data;
362: PetscFunctionBegin;
363: shell->postsolve = postsolve;
364: if (postsolve) pc->ops->postsolve = PCPostSolve_Shell;
365: else pc->ops->postsolve = NULL;
366: PetscFunctionReturn(PETSC_SUCCESS);
367: }
369: static PetscErrorCode PCShellSetView_Shell(PC pc, PetscErrorCode (*view)(PC, PetscViewer))
370: {
371: PC_Shell *shell = (PC_Shell *)pc->data;
373: PetscFunctionBegin;
374: shell->view = view;
375: PetscFunctionReturn(PETSC_SUCCESS);
376: }
378: static PetscErrorCode PCShellSetApplyTranspose_Shell(PC pc, PetscErrorCode (*applytranspose)(PC, Vec, Vec))
379: {
380: PC_Shell *shell = (PC_Shell *)pc->data;
382: PetscFunctionBegin;
383: shell->applytranspose = applytranspose;
384: if (applytranspose) pc->ops->applytranspose = PCApplyTranspose_Shell;
385: else pc->ops->applytranspose = NULL;
386: PetscFunctionReturn(PETSC_SUCCESS);
387: }
389: static PetscErrorCode PCShellSetApplyRichardson_Shell(PC pc, PetscErrorCode (*applyrich)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *))
390: {
391: PC_Shell *shell = (PC_Shell *)pc->data;
393: PetscFunctionBegin;
394: shell->applyrich = applyrich;
395: if (applyrich) pc->ops->applyrichardson = PCApplyRichardson_Shell;
396: else pc->ops->applyrichardson = NULL;
397: PetscFunctionReturn(PETSC_SUCCESS);
398: }
400: static PetscErrorCode PCShellSetName_Shell(PC pc, const char name[])
401: {
402: PC_Shell *shell = (PC_Shell *)pc->data;
404: PetscFunctionBegin;
405: PetscCall(PetscFree(shell->name));
406: PetscCall(PetscStrallocpy(name, &shell->name));
407: PetscFunctionReturn(PETSC_SUCCESS);
408: }
410: static PetscErrorCode PCShellGetName_Shell(PC pc, const char *name[])
411: {
412: PC_Shell *shell = (PC_Shell *)pc->data;
414: PetscFunctionBegin;
415: *name = shell->name;
416: PetscFunctionReturn(PETSC_SUCCESS);
417: }
419: /*@C
420: PCShellSetDestroy - Sets routine to use to destroy the user-provided application context that was provided with `PCShellSetContext()`
422: Logically Collective
424: Input Parameters:
425: + pc - the preconditioner context
426: - destroy - the application-provided destroy routine
428: Calling sequence of `destroy`:
429: . pc - the preconditioner
431: Level: intermediate
433: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellGetContext()`
434: @*/
435: PetscErrorCode PCShellSetDestroy(PC pc, PetscErrorCode (*destroy)(PC pc))
436: {
437: PetscFunctionBegin;
439: PetscTryMethod(pc, "PCShellSetDestroy_C", (PC, PetscErrorCode (*)(PC)), (pc, destroy));
440: PetscFunctionReturn(PETSC_SUCCESS);
441: }
443: /*@C
444: PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
445: matrix operator is changed.
447: Logically Collective
449: Input Parameters:
450: + pc - the preconditioner context
451: - setup - the application-provided setup routine
453: Calling sequence of `setup`:
454: . pc - the preconditioner
456: Level: intermediate
458: Note:
459: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `setup`.
461: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetApply()`, `PCShellSetContext()`, , `PCShellGetContext()`
462: @*/
463: PetscErrorCode PCShellSetSetUp(PC pc, PetscErrorCode (*setup)(PC pc))
464: {
465: PetscFunctionBegin;
467: PetscTryMethod(pc, "PCShellSetSetUp_C", (PC, PetscErrorCode (*)(PC)), (pc, setup));
468: PetscFunctionReturn(PETSC_SUCCESS);
469: }
471: /*@C
472: PCShellSetView - Sets routine to use as viewer of a `PCSHELL` shell preconditioner
474: Logically Collective
476: Input Parameters:
477: + pc - the preconditioner context
478: - view - the application-provided view routine
480: Calling sequence of `view`:
481: + pc - the preconditioner
482: - v - viewer
484: Level: advanced
486: Note:
487: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `view`.
489: .seealso: [](ch_ksp), `PC`, `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellGetContext()`
490: @*/
491: PetscErrorCode PCShellSetView(PC pc, PetscErrorCode (*view)(PC pc, PetscViewer v))
492: {
493: PetscFunctionBegin;
495: PetscTryMethod(pc, "PCShellSetView_C", (PC, PetscErrorCode (*)(PC, PetscViewer)), (pc, view));
496: PetscFunctionReturn(PETSC_SUCCESS);
497: }
499: /*@C
500: PCShellSetApply - Sets routine to use as preconditioner.
502: Logically Collective
504: Input Parameters:
505: + pc - the preconditioner context
506: - apply - the application-provided preconditioning routine
508: Calling sequence of `apply`:
509: + pc - the preconditioner, get the application context with `PCShellGetContext()`
510: . xin - input vector
511: - xout - output vector
513: Level: intermediate
515: Note:
516: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.
518: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellSetApplyBA()`, `PCShellSetApplySymmetricRight()`, `PCShellSetApplySymmetricLeft()`, `PCShellGetContext()`
519: @*/
520: PetscErrorCode PCShellSetApply(PC pc, PetscErrorCode (*apply)(PC pc, Vec xin, Vec xout))
521: {
522: PetscFunctionBegin;
524: PetscTryMethod(pc, "PCShellSetApply_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, apply));
525: PetscFunctionReturn(PETSC_SUCCESS);
526: }
528: /*@C
529: PCShellSetMatApply - Sets routine to use as preconditioner on a block of vectors.
531: Logically Collective
533: Input Parameters:
534: + pc - the preconditioner context
535: - matapply - the application-provided preconditioning routine
537: Calling sequence of `matapply`:
538: + pc - the preconditioner
539: . Xin - input block of vectors represented as a dense `Mat`
540: - Xout - output block of vectors represented as a dense `Mat`
542: Level: advanced
544: Note:
545: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `matapply`.
547: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellGetContext()`
548: @*/
549: PetscErrorCode PCShellSetMatApply(PC pc, PetscErrorCode (*matapply)(PC pc, Mat Xin, Mat Xout))
550: {
551: PetscFunctionBegin;
553: PetscTryMethod(pc, "PCShellSetMatApply_C", (PC, PetscErrorCode (*)(PC, Mat, Mat)), (pc, matapply));
554: PetscFunctionReturn(PETSC_SUCCESS);
555: }
557: /*@C
558: PCShellSetApplySymmetricLeft - Sets routine to use as left preconditioner (when the `PC_SYMMETRIC` is used).
560: Logically Collective
562: Input Parameters:
563: + pc - the preconditioner context
564: - apply - the application-provided left preconditioning routine
566: Calling sequence of `apply`:
567: + pc - the preconditioner
568: . xin - input vector
569: - xout - output vector
571: Level: advanced
573: Note:
574: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.
576: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`
577: @*/
578: PetscErrorCode PCShellSetApplySymmetricLeft(PC pc, PetscErrorCode (*apply)(PC pc, Vec xin, Vec xout))
579: {
580: PetscFunctionBegin;
582: PetscTryMethod(pc, "PCShellSetApplySymmetricLeft_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, apply));
583: PetscFunctionReturn(PETSC_SUCCESS);
584: }
586: /*@C
587: PCShellSetApplySymmetricRight - Sets routine to use as right preconditioner (when the `PC_SYMMETRIC` is used).
589: Logically Collective
591: Input Parameters:
592: + pc - the preconditioner context
593: - apply - the application-provided right preconditioning routine
595: Calling sequence of `apply`:
596: + pc - the preconditioner
597: . xin - input vector
598: - xout - output vector
600: Level: advanced
602: Note:
603: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.
605: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetApplySymmetricLeft()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellGetContext()`
606: @*/
607: PetscErrorCode PCShellSetApplySymmetricRight(PC pc, PetscErrorCode (*apply)(PC pc, Vec xin, Vec xout))
608: {
609: PetscFunctionBegin;
611: PetscTryMethod(pc, "PCShellSetApplySymmetricRight_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, apply));
612: PetscFunctionReturn(PETSC_SUCCESS);
613: }
615: /*@C
616: PCShellSetApplyBA - Sets routine to use as the preconditioner times the operator.
618: Logically Collective
620: Input Parameters:
621: + pc - the preconditioner context
622: - applyBA - the application-provided BA routine
624: Calling sequence of `applyBA`:
625: + pc - the preconditioner
626: . side - `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
627: . xin - input vector
628: . xout - output vector
629: - w - work vector
631: Level: intermediate
633: Note:
634: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `applyBA`.
636: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellSetApply()`, `PCShellGetContext()`, `PCSide`
637: @*/
638: PetscErrorCode PCShellSetApplyBA(PC pc, PetscErrorCode (*applyBA)(PC pc, PCSide side, Vec xin, Vec xout, Vec w))
639: {
640: PetscFunctionBegin;
642: PetscTryMethod(pc, "PCShellSetApplyBA_C", (PC, PetscErrorCode (*)(PC, PCSide, Vec, Vec, Vec)), (pc, applyBA));
643: PetscFunctionReturn(PETSC_SUCCESS);
644: }
646: /*@C
647: PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.
649: Logically Collective
651: Input Parameters:
652: + pc - the preconditioner context
653: - applytranspose - the application-provided preconditioning transpose routine
655: Calling sequence of `applytranspose`:
656: + pc - the preconditioner
657: . xin - input vector
658: - xout - output vector
660: Level: intermediate
662: Note:
663: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `applytranspose`.
665: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCSetContext()`, `PCShellSetApplyBA()`, `PCGetContext()`
666: @*/
667: PetscErrorCode PCShellSetApplyTranspose(PC pc, PetscErrorCode (*applytranspose)(PC pc, Vec xin, Vec xout))
668: {
669: PetscFunctionBegin;
671: PetscTryMethod(pc, "PCShellSetApplyTranspose_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, applytranspose));
672: PetscFunctionReturn(PETSC_SUCCESS);
673: }
675: /*@C
676: PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a `KSPSolve()` is
677: applied. This usually does something like scale the linear system in some application
678: specific way.
680: Logically Collective
682: Input Parameters:
683: + pc - the preconditioner context
684: - presolve - the application-provided presolve routine
686: Calling sequence of `presolve`:
687: + pc - the preconditioner
688: . ksp - the `KSP` that contains `pc`
689: . xin - input vector
690: - xout - output vector
692: Level: advanced
694: Note:
695: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `presolve`.
697: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetPostSolve()`, `PCShellSetContext()`, `PCGetContext()`
698: @*/
699: PetscErrorCode PCShellSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC pc, KSP ksp, Vec xin, Vec xout))
700: {
701: PetscFunctionBegin;
703: PetscTryMethod(pc, "PCShellSetPreSolve_C", (PC, PetscErrorCode (*)(PC, KSP, Vec, Vec)), (pc, presolve));
704: PetscFunctionReturn(PETSC_SUCCESS);
705: }
707: /*@C
708: PCShellSetPostSolve - Sets routine to apply to the operators/vectors after a `KSPSolve()` is
709: applied. This usually does something like scale the linear system in some application
710: specific way.
712: Logically Collective
714: Input Parameters:
715: + pc - the preconditioner context
716: - postsolve - the application-provided presolve routine
718: Calling sequence of `postsolve`:
719: + pc - the preconditioner
720: . ksp - the `KSP` that contains `pc`
721: . xin - input vector
722: - xout - output vector
724: Level: advanced
726: Note:
727: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `postsolve`.
729: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetPreSolve()`, `PCShellSetContext()`, `PCGetContext()`
730: @*/
731: PetscErrorCode PCShellSetPostSolve(PC pc, PetscErrorCode (*postsolve)(PC pc, KSP ksp, Vec xin, Vec xout))
732: {
733: PetscFunctionBegin;
735: PetscTryMethod(pc, "PCShellSetPostSolve_C", (PC, PetscErrorCode (*)(PC, KSP, Vec, Vec)), (pc, postsolve));
736: PetscFunctionReturn(PETSC_SUCCESS);
737: }
739: /*@
740: PCShellSetName - Sets an optional name to associate with a `PCSHELL`
741: preconditioner.
743: Not Collective
745: Input Parameters:
746: + pc - the preconditioner context
747: - name - character string describing shell preconditioner
749: Level: intermediate
751: Note:
752: This is separate from the name you can provide with `PetscObjectSetName()`
754: .seealso: [](ch_ksp), `PCSHELL`, `PCShellGetName()`, `PetscObjectSetName()`, `PetscObjectGetName()`
755: @*/
756: PetscErrorCode PCShellSetName(PC pc, const char name[])
757: {
758: PetscFunctionBegin;
760: PetscTryMethod(pc, "PCShellSetName_C", (PC, const char[]), (pc, name));
761: PetscFunctionReturn(PETSC_SUCCESS);
762: }
764: /*@
765: PCShellGetName - Gets an optional name that the user has set for a `PCSHELL` with `PCShellSetName()`
766: preconditioner.
768: Not Collective
770: Input Parameter:
771: . pc - the preconditioner context
773: Output Parameter:
774: . name - character string describing shell preconditioner (you should not free this)
776: Level: intermediate
778: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetName()`, `PetscObjectSetName()`, `PetscObjectGetName()`
779: @*/
780: PetscErrorCode PCShellGetName(PC pc, const char *name[])
781: {
782: PetscFunctionBegin;
784: PetscAssertPointer(name, 2);
785: PetscUseMethod(pc, "PCShellGetName_C", (PC, const char *[]), (pc, name));
786: PetscFunctionReturn(PETSC_SUCCESS);
787: }
789: /*@C
790: PCShellSetApplyRichardson - Sets routine to use as preconditioner
791: in Richardson iteration.
793: Logically Collective
795: Input Parameters:
796: + pc - the preconditioner context
797: - apply - the application-provided preconditioning routine
799: Calling sequence of `apply`:
800: + pc - the preconditioner
801: . b - right-hand side
802: . x - current iterate
803: . r - work space
804: . rtol - relative tolerance of residual norm to stop at
805: . abstol - absolute tolerance of residual norm to stop at
806: . dtol - if residual norm increases by this factor than return
807: . maxits - number of iterations to run
808: . zeroinitialguess - `PETSC_TRUE` if `x` is known to be initially zero
809: . its - returns the number of iterations used
810: - reason - returns the reason the iteration has converged
812: Level: advanced
814: Note:
815: You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.
817: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`, `PCRichardsonConvergedReason()`, `PCShellGetContext()`
818: @*/
819: PetscErrorCode PCShellSetApplyRichardson(PC pc, PetscErrorCode (*apply)(PC pc, Vec b, Vec x, Vec r, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt maxits, PetscBool zeroinitialguess, PetscInt *its, PCRichardsonConvergedReason *reason))
820: {
821: PetscFunctionBegin;
823: PetscTryMethod(pc, "PCShellSetApplyRichardson_C", (PC, PetscErrorCode (*)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *)), (pc, apply));
824: PetscFunctionReturn(PETSC_SUCCESS);
825: }
827: /*MC
828: PCSHELL - Creates a new preconditioner class for use with a users
829: own private data storage format and preconditioner application code
831: Level: advanced
833: Usage:
834: .vb
835: extern PetscErrorCode apply(PC,Vec,Vec);
836: extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec);
837: extern PetscErrorCode applytranspose(PC,Vec,Vec);
838: extern PetscErrorCode setup(PC);
839: extern PetscErrorCode destroy(PC);
841: PCCreate(comm,&pc);
842: PCSetType(pc,PCSHELL);
843: PCShellSetContext(pc,ctx)
844: PCShellSetApply(pc,apply);
845: PCShellSetApplyBA(pc,applyba); (optional)
846: PCShellSetApplyTranspose(pc,applytranspose); (optional)
847: PCShellSetSetUp(pc,setup); (optional)
848: PCShellSetDestroy(pc,destroy); (optional)
849: .ve
851: Note:
852: Information required for the preconditioner and its internal datastructures can be set with `PCShellSetContext()` and then accessed
853: with `PCShellGetContext()` inside the routines provided above
855: .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
856: `MATSHELL`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCShellSetView()`, `PCShellSetDestroy()`, `PCShellSetPostSolve()`,
857: `PCShellSetApplyTranspose()`, `PCShellSetName()`, `PCShellSetApplyRichardson()`, `PCShellSetPreSolve()`, `PCShellSetView()`,
858: `PCShellGetName()`, `PCShellSetContext()`, `PCShellGetContext()`, `PCShellSetApplyBA()`, `MATSHELL`, `PCShellSetMatApply()`,
859: M*/
861: PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc)
862: {
863: PC_Shell *shell;
865: PetscFunctionBegin;
866: PetscCall(PetscNew(&shell));
867: pc->data = (void *)shell;
869: pc->ops->destroy = PCDestroy_Shell;
870: pc->ops->view = PCView_Shell;
871: pc->ops->apply = PCApply_Shell;
872: pc->ops->applysymmetricleft = PCApplySymmetricLeft_Shell;
873: pc->ops->applysymmetricright = PCApplySymmetricRight_Shell;
874: pc->ops->matapply = NULL;
875: pc->ops->applytranspose = NULL;
876: pc->ops->applyrichardson = NULL;
877: pc->ops->setup = NULL;
878: pc->ops->presolve = NULL;
879: pc->ops->postsolve = NULL;
881: shell->apply = NULL;
882: shell->applytranspose = NULL;
883: shell->name = NULL;
884: shell->applyrich = NULL;
885: shell->presolve = NULL;
886: shell->postsolve = NULL;
887: shell->ctx = NULL;
888: shell->setup = NULL;
889: shell->view = NULL;
890: shell->destroy = NULL;
891: shell->applysymmetricleft = NULL;
892: shell->applysymmetricright = NULL;
894: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetDestroy_C", PCShellSetDestroy_Shell));
895: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetSetUp_C", PCShellSetSetUp_Shell));
896: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApply_C", PCShellSetApply_Shell));
897: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApply_C", PCShellSetMatApply_Shell));
898: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricLeft_C", PCShellSetApplySymmetricLeft_Shell));
899: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricRight_C", PCShellSetApplySymmetricRight_Shell));
900: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyBA_C", PCShellSetApplyBA_Shell));
901: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPreSolve_C", PCShellSetPreSolve_Shell));
902: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPostSolve_C", PCShellSetPostSolve_Shell));
903: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetView_C", PCShellSetView_Shell));
904: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyTranspose_C", PCShellSetApplyTranspose_Shell));
905: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetName_C", PCShellSetName_Shell));
906: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellGetName_C", PCShellGetName_Shell));
907: PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyRichardson_C", PCShellSetApplyRichardson_Shell));
908: PetscFunctionReturn(PETSC_SUCCESS);
909: }