xref: /petsc/src/ksp/pc/impls/shell/shellpc.c (revision 697336901c45ac77e1fd620fe1fca906cf3f95c8)
1 
2 /*
3    This provides a simple shell for Fortran (and C programmers) to
4   create their own preconditioner without writing much interface code.
5 */
6 
7 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
8 
9 typedef struct {
10   void *ctx; /* user provided contexts for preconditioner */
11 
12   PetscErrorCode (*destroy)(PC);
13   PetscErrorCode (*setup)(PC);
14   PetscErrorCode (*apply)(PC, Vec, Vec);
15   PetscErrorCode (*matapply)(PC, Mat, Mat);
16   PetscErrorCode (*applysymmetricleft)(PC, Vec, Vec);
17   PetscErrorCode (*applysymmetricright)(PC, Vec, Vec);
18   PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec);
19   PetscErrorCode (*presolve)(PC, KSP, Vec, Vec);
20   PetscErrorCode (*postsolve)(PC, KSP, Vec, Vec);
21   PetscErrorCode (*view)(PC, PetscViewer);
22   PetscErrorCode (*applytranspose)(PC, Vec, Vec);
23   PetscErrorCode (*applyrich)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *);
24 
25   char *name;
26 } PC_Shell;
27 
28 /*@C
29   PCShellGetContext - Returns the user-provided context associated with a shell `PC`
30 
31   Not Collective
32 
33   Input Parameter:
34 . pc - of type `PCSHELL` created with `PCSetType`(pc,shell)
35 
36   Output Parameter:
37 . ctx - the user provided context
38 
39   Level: advanced
40 
41   Note:
42   This routine is intended for use within various shell routines
43 
44   Fortran Notes:
45   To use this from Fortran you must write a Fortran interface definition for this
46   function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
47 
48 .seealso: `PCSHELL`, `PCShellSetContext()`
49 @*/
50 PetscErrorCode PCShellGetContext(PC pc, void *ctx)
51 {
52   PetscBool flg;
53 
54   PetscFunctionBegin;
55   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
56   PetscValidPointer(ctx, 2);
57   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCSHELL, &flg));
58   if (!flg) *(void **)ctx = NULL;
59   else *(void **)ctx = ((PC_Shell *)(pc->data))->ctx;
60   PetscFunctionReturn(PETSC_SUCCESS);
61 }
62 
63 /*@
64   PCShellSetContext - sets the context for a shell `PC`
65 
66   Logically Collective
67 
68   Input Parameters:
69 + pc  - the `PC` of type `PCSHELL`
70 - ctx - the context
71 
72   Level: advanced
73 
74   Fortran Notes:
75   To use this from Fortran you must write a Fortran interface definition for this
76   function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
77 
78 .seealso: `PCShellGetContext()`, `PCSHELL`
79 @*/
80 PetscErrorCode PCShellSetContext(PC pc, void *ctx)
81 {
82   PC_Shell *shell = (PC_Shell *)pc->data;
83   PetscBool flg;
84 
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
87   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCSHELL, &flg));
88   if (flg) shell->ctx = ctx;
89   PetscFunctionReturn(PETSC_SUCCESS);
90 }
91 
92 static PetscErrorCode PCSetUp_Shell(PC pc)
93 {
94   PC_Shell *shell = (PC_Shell *)pc->data;
95 
96   PetscFunctionBegin;
97   PetscCheck(shell->setup, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No setup() routine provided to Shell PC");
98   PetscCallBack("PCSHELL callback setup", (*shell->setup)(pc));
99   PetscFunctionReturn(PETSC_SUCCESS);
100 }
101 
102 static PetscErrorCode PCApply_Shell(PC pc, Vec x, Vec y)
103 {
104   PC_Shell        *shell = (PC_Shell *)pc->data;
105   PetscObjectState instate, outstate;
106 
107   PetscFunctionBegin;
108   PetscCheck(shell->apply, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
109   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
110   PetscCallBack("PCSHELL callback apply", (*shell->apply)(pc, x, y));
111   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
112   /* increase the state of the output vector if the user did not update its state themself as should have been done */
113   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
114   PetscFunctionReturn(PETSC_SUCCESS);
115 }
116 
117 static PetscErrorCode PCMatApply_Shell(PC pc, Mat X, Mat Y)
118 {
119   PC_Shell        *shell = (PC_Shell *)pc->data;
120   PetscObjectState instate, outstate;
121 
122   PetscFunctionBegin;
123   PetscCheck(shell->matapply, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
124   PetscCall(PetscObjectStateGet((PetscObject)Y, &instate));
125   PetscCallBack("PCSHELL callback apply", (*shell->matapply)(pc, X, Y));
126   PetscCall(PetscObjectStateGet((PetscObject)Y, &outstate));
127   /* increase the state of the output vector if the user did not update its state themself as should have been done */
128   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)Y));
129   PetscFunctionReturn(PETSC_SUCCESS);
130 }
131 
132 static PetscErrorCode PCApplySymmetricLeft_Shell(PC pc, Vec x, Vec y)
133 {
134   PC_Shell *shell = (PC_Shell *)pc->data;
135 
136   PetscFunctionBegin;
137   PetscCheck(shell->applysymmetricleft, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
138   PetscCallBack("PCSHELL callback apply symmetric left", (*shell->applysymmetricleft)(pc, x, y));
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 static PetscErrorCode PCApplySymmetricRight_Shell(PC pc, Vec x, Vec y)
143 {
144   PC_Shell *shell = (PC_Shell *)pc->data;
145 
146   PetscFunctionBegin;
147   PetscCheck(shell->applysymmetricright, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
148   PetscCallBack("PCSHELL callback apply symmetric right", (*shell->applysymmetricright)(pc, x, y));
149   PetscFunctionReturn(PETSC_SUCCESS);
150 }
151 
152 static PetscErrorCode PCApplyBA_Shell(PC pc, PCSide side, Vec x, Vec y, Vec w)
153 {
154   PC_Shell        *shell = (PC_Shell *)pc->data;
155   PetscObjectState instate, outstate;
156 
157   PetscFunctionBegin;
158   PetscCheck(shell->applyBA, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applyBA() routine provided to Shell PC");
159   PetscCall(PetscObjectStateGet((PetscObject)w, &instate));
160   PetscCallBack("PCSHELL callback applyBA", (*shell->applyBA)(pc, side, x, y, w));
161   PetscCall(PetscObjectStateGet((PetscObject)w, &outstate));
162   /* increase the state of the output vector if the user did not update its state themself as should have been done */
163   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)w));
164   PetscFunctionReturn(PETSC_SUCCESS);
165 }
166 
167 static PetscErrorCode PCPreSolveChangeRHS_Shell(PC pc, PetscBool *change)
168 {
169   PetscFunctionBegin;
170   *change = PETSC_TRUE;
171   PetscFunctionReturn(PETSC_SUCCESS);
172 }
173 
174 static PetscErrorCode PCPreSolve_Shell(PC pc, KSP ksp, Vec b, Vec x)
175 {
176   PC_Shell *shell = (PC_Shell *)pc->data;
177 
178   PetscFunctionBegin;
179   PetscCheck(shell->presolve, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No presolve() routine provided to Shell PC");
180   PetscCallBack("PCSHELL callback presolve", (*shell->presolve)(pc, ksp, b, x));
181   PetscFunctionReturn(PETSC_SUCCESS);
182 }
183 
184 static PetscErrorCode PCPostSolve_Shell(PC pc, KSP ksp, Vec b, Vec x)
185 {
186   PC_Shell *shell = (PC_Shell *)pc->data;
187 
188   PetscFunctionBegin;
189   PetscCheck(shell->postsolve, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No postsolve() routine provided to Shell PC");
190   PetscCallBack("PCSHELL callback postsolve()", (*shell->postsolve)(pc, ksp, b, x));
191   PetscFunctionReturn(PETSC_SUCCESS);
192 }
193 
194 static PetscErrorCode PCApplyTranspose_Shell(PC pc, Vec x, Vec y)
195 {
196   PC_Shell        *shell = (PC_Shell *)pc->data;
197   PetscObjectState instate, outstate;
198 
199   PetscFunctionBegin;
200   PetscCheck(shell->applytranspose, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applytranspose() routine provided to Shell PC");
201   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
202   PetscCallBack("PCSHELL callback applytranspose", (*shell->applytranspose)(pc, x, y));
203   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
204   /* increase the state of the output vector if the user did not update its state themself as should have been done */
205   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
206   PetscFunctionReturn(PETSC_SUCCESS);
207 }
208 
209 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)
210 {
211   PC_Shell        *shell = (PC_Shell *)pc->data;
212   PetscObjectState instate, outstate;
213 
214   PetscFunctionBegin;
215   PetscCheck(shell->applyrich, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applyrichardson() routine provided to Shell PC");
216   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
217   PetscCallBack("PCSHELL callback applyrichardson", (*shell->applyrich)(pc, x, y, w, rtol, abstol, dtol, it, guesszero, outits, reason));
218   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
219   /* increase the state of the output vector since the user did not update its state themself as should have been done */
220   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
221   PetscFunctionReturn(PETSC_SUCCESS);
222 }
223 
224 static PetscErrorCode PCDestroy_Shell(PC pc)
225 {
226   PC_Shell *shell = (PC_Shell *)pc->data;
227 
228   PetscFunctionBegin;
229   PetscCall(PetscFree(shell->name));
230   if (shell->destroy) PetscCallBack("PCSHELL callback destroy", (*shell->destroy)(pc));
231   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetDestroy_C", NULL));
232   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetSetUp_C", NULL));
233   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApply_C", NULL));
234   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApply_C", NULL));
235   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricLeft_C", NULL));
236   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricRight_C", NULL));
237   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyBA_C", NULL));
238   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPreSolve_C", NULL));
239   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPostSolve_C", NULL));
240   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetView_C", NULL));
241   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyTranspose_C", NULL));
242   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetName_C", NULL));
243   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellGetName_C", NULL));
244   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyRichardson_C", NULL));
245   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
246   PetscCall(PetscFree(pc->data));
247   PetscFunctionReturn(PETSC_SUCCESS);
248 }
249 
250 static PetscErrorCode PCView_Shell(PC pc, PetscViewer viewer)
251 {
252   PC_Shell *shell = (PC_Shell *)pc->data;
253   PetscBool iascii;
254 
255   PetscFunctionBegin;
256   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
257   if (iascii) {
258     if (shell->name) PetscCall(PetscViewerASCIIPrintf(viewer, "  %s\n", shell->name));
259     else PetscCall(PetscViewerASCIIPrintf(viewer, "  no name\n"));
260   }
261   if (shell->view) {
262     PetscCall(PetscViewerASCIIPushTab(viewer));
263     PetscCall((*shell->view)(pc, viewer));
264     PetscCall(PetscViewerASCIIPopTab(viewer));
265   }
266   PetscFunctionReturn(PETSC_SUCCESS);
267 }
268 
269 static PetscErrorCode PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(PC))
270 {
271   PC_Shell *shell = (PC_Shell *)pc->data;
272 
273   PetscFunctionBegin;
274   shell->destroy = destroy;
275   PetscFunctionReturn(PETSC_SUCCESS);
276 }
277 
278 static PetscErrorCode PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(PC))
279 {
280   PC_Shell *shell = (PC_Shell *)pc->data;
281 
282   PetscFunctionBegin;
283   shell->setup = setup;
284   if (setup) pc->ops->setup = PCSetUp_Shell;
285   else pc->ops->setup = NULL;
286   PetscFunctionReturn(PETSC_SUCCESS);
287 }
288 
289 static PetscErrorCode PCShellSetApply_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
290 {
291   PC_Shell *shell = (PC_Shell *)pc->data;
292 
293   PetscFunctionBegin;
294   shell->apply = apply;
295   PetscFunctionReturn(PETSC_SUCCESS);
296 }
297 
298 static PetscErrorCode PCShellSetMatApply_Shell(PC pc, PetscErrorCode (*matapply)(PC, Mat, Mat))
299 {
300   PC_Shell *shell = (PC_Shell *)pc->data;
301 
302   PetscFunctionBegin;
303   shell->matapply = matapply;
304   if (matapply) pc->ops->matapply = PCMatApply_Shell;
305   else pc->ops->matapply = NULL;
306   PetscFunctionReturn(PETSC_SUCCESS);
307 }
308 
309 static PetscErrorCode PCShellSetApplySymmetricLeft_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
310 {
311   PC_Shell *shell = (PC_Shell *)pc->data;
312 
313   PetscFunctionBegin;
314   shell->applysymmetricleft = apply;
315   PetscFunctionReturn(PETSC_SUCCESS);
316 }
317 
318 static PetscErrorCode PCShellSetApplySymmetricRight_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
319 {
320   PC_Shell *shell = (PC_Shell *)pc->data;
321 
322   PetscFunctionBegin;
323   shell->applysymmetricright = apply;
324   PetscFunctionReturn(PETSC_SUCCESS);
325 }
326 
327 static PetscErrorCode PCShellSetApplyBA_Shell(PC pc, PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec))
328 {
329   PC_Shell *shell = (PC_Shell *)pc->data;
330 
331   PetscFunctionBegin;
332   shell->applyBA = applyBA;
333   if (applyBA) pc->ops->applyBA = PCApplyBA_Shell;
334   else pc->ops->applyBA = NULL;
335   PetscFunctionReturn(PETSC_SUCCESS);
336 }
337 
338 static PetscErrorCode PCShellSetPreSolve_Shell(PC pc, PetscErrorCode (*presolve)(PC, KSP, Vec, Vec))
339 {
340   PC_Shell *shell = (PC_Shell *)pc->data;
341 
342   PetscFunctionBegin;
343   shell->presolve = presolve;
344   if (presolve) {
345     pc->ops->presolve = PCPreSolve_Shell;
346     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_Shell));
347   } else {
348     pc->ops->presolve = NULL;
349     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
350   }
351   PetscFunctionReturn(PETSC_SUCCESS);
352 }
353 
354 static PetscErrorCode PCShellSetPostSolve_Shell(PC pc, PetscErrorCode (*postsolve)(PC, KSP, Vec, Vec))
355 {
356   PC_Shell *shell = (PC_Shell *)pc->data;
357 
358   PetscFunctionBegin;
359   shell->postsolve = postsolve;
360   if (postsolve) pc->ops->postsolve = PCPostSolve_Shell;
361   else pc->ops->postsolve = NULL;
362   PetscFunctionReturn(PETSC_SUCCESS);
363 }
364 
365 static PetscErrorCode PCShellSetView_Shell(PC pc, PetscErrorCode (*view)(PC, PetscViewer))
366 {
367   PC_Shell *shell = (PC_Shell *)pc->data;
368 
369   PetscFunctionBegin;
370   shell->view = view;
371   PetscFunctionReturn(PETSC_SUCCESS);
372 }
373 
374 static PetscErrorCode PCShellSetApplyTranspose_Shell(PC pc, PetscErrorCode (*applytranspose)(PC, Vec, Vec))
375 {
376   PC_Shell *shell = (PC_Shell *)pc->data;
377 
378   PetscFunctionBegin;
379   shell->applytranspose = applytranspose;
380   if (applytranspose) pc->ops->applytranspose = PCApplyTranspose_Shell;
381   else pc->ops->applytranspose = NULL;
382   PetscFunctionReturn(PETSC_SUCCESS);
383 }
384 
385 static PetscErrorCode PCShellSetApplyRichardson_Shell(PC pc, PetscErrorCode (*applyrich)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *))
386 {
387   PC_Shell *shell = (PC_Shell *)pc->data;
388 
389   PetscFunctionBegin;
390   shell->applyrich = applyrich;
391   if (applyrich) pc->ops->applyrichardson = PCApplyRichardson_Shell;
392   else pc->ops->applyrichardson = NULL;
393   PetscFunctionReturn(PETSC_SUCCESS);
394 }
395 
396 static PetscErrorCode PCShellSetName_Shell(PC pc, const char name[])
397 {
398   PC_Shell *shell = (PC_Shell *)pc->data;
399 
400   PetscFunctionBegin;
401   PetscCall(PetscFree(shell->name));
402   PetscCall(PetscStrallocpy(name, &shell->name));
403   PetscFunctionReturn(PETSC_SUCCESS);
404 }
405 
406 static PetscErrorCode PCShellGetName_Shell(PC pc, const char *name[])
407 {
408   PC_Shell *shell = (PC_Shell *)pc->data;
409 
410   PetscFunctionBegin;
411   *name = shell->name;
412   PetscFunctionReturn(PETSC_SUCCESS);
413 }
414 
415 /*@C
416   PCShellSetDestroy - Sets routine to use to destroy the user-provided
417   application context.
418 
419   Logically Collective
420 
421   Input Parameters:
422 + pc      - the preconditioner context
423 - destroy - the application-provided destroy routine
424 
425   Calling sequence of `destroy`:
426 $  PetscErrorCode destroy(PC pc)
427 . pc - the preconditioner, get the application context with `PCShellGetContext()`
428 
429   Level: intermediate
430 
431 .seealso: `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`
432 @*/
433 PetscErrorCode PCShellSetDestroy(PC pc, PetscErrorCode (*destroy)(PC))
434 {
435   PetscFunctionBegin;
436   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
437   PetscTryMethod(pc, "PCShellSetDestroy_C", (PC, PetscErrorCode(*)(PC)), (pc, destroy));
438   PetscFunctionReturn(PETSC_SUCCESS);
439 }
440 
441 /*@C
442   PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
443   matrix operator is changed.
444 
445   Logically Collective
446 
447   Input Parameters:
448 + pc    - the preconditioner context
449 - setup - the application-provided setup routine
450 
451   Calling sequence of `setup`:
452 $   PetscErrorCode setup(PC pc)
453 . pc - the preconditioner, get the application context with `PCShellGetContext()`
454 
455   Note:
456   the function MUST return an error code of 0 on success and nonzero on failure.
457 
458   Level: intermediate
459 
460 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetApply()`, `PCShellSetContext()`
461 @*/
462 PetscErrorCode PCShellSetSetUp(PC pc, PetscErrorCode (*setup)(PC))
463 {
464   PetscFunctionBegin;
465   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
466   PetscTryMethod(pc, "PCShellSetSetUp_C", (PC, PetscErrorCode(*)(PC)), (pc, setup));
467   PetscFunctionReturn(PETSC_SUCCESS);
468 }
469 
470 /*@C
471   PCShellSetView - Sets routine to use as viewer of shell preconditioner
472 
473   Logically Collective
474 
475   Input Parameters:
476 + pc   - the preconditioner context
477 - view - the application-provided view routine
478 
479   Calling sequence of `view`:
480 .vb
481    PetscErrorCode view(PC pc, PetscViewer v)
482 .ve
483 + pc - the preconditioner, get the application context with `PCShellGetContext()`
484 -  v   - viewer
485 
486   Level: advanced
487 
488 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`
489 @*/
490 PetscErrorCode PCShellSetView(PC pc, PetscErrorCode (*view)(PC, PetscViewer))
491 {
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
494   PetscTryMethod(pc, "PCShellSetView_C", (PC, PetscErrorCode(*)(PC, PetscViewer)), (pc, view));
495   PetscFunctionReturn(PETSC_SUCCESS);
496 }
497 
498 /*@C
499   PCShellSetApply - Sets routine to use as preconditioner.
500 
501   Logically Collective
502 
503   Input Parameters:
504 + pc    - the preconditioner context
505 - apply - the application-provided preconditioning routine
506 
507   Calling sequence of `apply`:
508 .vb
509    PetscErrorCode apply(PC pc, Vec xin, Vec xout)
510 .ve
511 + pc - the preconditioner, get the application context with `PCShellGetContext()`
512 .  xin - input vector
513 -  xout - output vector
514 
515   Level: intermediate
516 
517 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellSetApplyBA()`, `PCShellSetApplySymmetricRight()`, `PCShellSetApplySymmetricLeft()`
518 @*/
519 PetscErrorCode PCShellSetApply(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
520 {
521   PetscFunctionBegin;
522   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
523   PetscTryMethod(pc, "PCShellSetApply_C", (PC, PetscErrorCode(*)(PC, Vec, Vec)), (pc, apply));
524   PetscFunctionReturn(PETSC_SUCCESS);
525 }
526 
527 /*@C
528   PCShellSetMatApply - Sets routine to use as preconditioner on a block of vectors.
529 
530   Logically Collective
531 
532   Input Parameters:
533 + pc - the preconditioner context
534 -  apply - the application-provided preconditioning routine
535 
536   Calling sequence of `apply`:
537 .vb
538    PetscErrorCode apply(PC pc, Mat Xin, Mat Xout)
539 .ve
540 + pc - the preconditioner, get the application context with `PCShellGetContext()`
541 .  Xin - input block of vectors
542 -  Xout - output block of vectors
543 
544   Level: advanced
545 
546 .seealso: `PCSHELL`, `PCShellSetApply()`
547 @*/
548 PetscErrorCode PCShellSetMatApply(PC pc, PetscErrorCode (*matapply)(PC, Mat, Mat))
549 {
550   PetscFunctionBegin;
551   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
552   PetscTryMethod(pc, "PCShellSetMatApply_C", (PC, PetscErrorCode(*)(PC, Mat, Mat)), (pc, matapply));
553   PetscFunctionReturn(PETSC_SUCCESS);
554 }
555 
556 /*@C
557   PCShellSetApplySymmetricLeft - Sets routine to use as left preconditioner (when the `PC_SYMMETRIC` is used).
558 
559   Logically Collective
560 
561   Input Parameters:
562 + pc    - the preconditioner context
563 - apply - the application-provided left preconditioning routine
564 
565   Calling sequence of `apply`:
566 .vb
567    PetscErrorCode apply(PC pc, Vec xin, Vec xout)
568 .ve
569 + pc - the preconditioner, get the application context with `PCShellGetContext()`
570 .  xin - input vector
571 -  xout - output vector
572 
573   Level: advanced
574 
575 .seealso: `PCSHELL`, `PCShellSetApply()`, `PCShellSetApplySymmetricLeft()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`
576 @*/
577 PetscErrorCode PCShellSetApplySymmetricLeft(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
578 {
579   PetscFunctionBegin;
580   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
581   PetscTryMethod(pc, "PCShellSetApplySymmetricLeft_C", (PC, PetscErrorCode(*)(PC, Vec, Vec)), (pc, apply));
582   PetscFunctionReturn(PETSC_SUCCESS);
583 }
584 
585 /*@C
586   PCShellSetApplySymmetricRight - Sets routine to use as right preconditioner (when the `PC_SYMMETRIC` is used).
587 
588   Logically Collective
589 
590   Input Parameters:
591 + pc    - the preconditioner context
592 - apply - the application-provided right preconditioning routine
593 
594   Calling sequence of `apply`:
595 .vb
596    PetscErrorCode apply(PC pc, Vec xin, Vec xout)
597 .ve
598 + pc - the preconditioner, get the application context with PCShellGetContext()
599 .  xin - input vector
600 -  xout - output vector
601 
602   Level: advanced
603 
604 .seealso: `PCSHELL`, `PCShellSetApply()`, `PCShellSetApplySymmetricLeft()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`
605 @*/
606 PetscErrorCode PCShellSetApplySymmetricRight(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
607 {
608   PetscFunctionBegin;
609   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
610   PetscTryMethod(pc, "PCShellSetApplySymmetricRight_C", (PC, PetscErrorCode(*)(PC, Vec, Vec)), (pc, apply));
611   PetscFunctionReturn(PETSC_SUCCESS);
612 }
613 
614 /*@C
615   PCShellSetApplyBA - Sets routine to use as preconditioner times operator.
616 
617   Logically Collective
618 
619   Input Parameters:
620 + pc      - the preconditioner context
621 - applyBA - the application-provided BA routine
622 
623   Calling sequence of `applyBA`:
624 .vb
625    PetscErrorCode applyBA(PC pc, Vec xin, Vec xout)
626 .ve
627 + pc - the preconditioner, get the application context with `PCShellGetContext()`
628 .  xin - input vector
629 -  xout - output vector
630 
631   Level: intermediate
632 
633 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellSetApply()`
634 @*/
635 PetscErrorCode PCShellSetApplyBA(PC pc, PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec))
636 {
637   PetscFunctionBegin;
638   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
639   PetscTryMethod(pc, "PCShellSetApplyBA_C", (PC, PetscErrorCode(*)(PC, PCSide, Vec, Vec, Vec)), (pc, applyBA));
640   PetscFunctionReturn(PETSC_SUCCESS);
641 }
642 
643 /*@C
644   PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.
645 
646   Logically Collective
647 
648   Input Parameters:
649 + pc             - the preconditioner context
650 - applytranspose - the application-provided preconditioning transpose routine
651 
652   Calling sequence of `applytranspose`:
653 .vb
654    PetscErrorCode applytranspose(PC pc, Vec xin, Vec xout)
655 .ve
656 +  pc - the preconditioner, get the application context with `PCShellGetContext()`
657 .  xin - input vector
658 -  xout - output vector
659 
660   Level: intermediate
661 
662   Note:
663   Uses the same context variable as `PCShellSetApply()`.
664 
665 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCSetContext()`, `PCShellSetApplyBA()`
666 @*/
667 PetscErrorCode PCShellSetApplyTranspose(PC pc, PetscErrorCode (*applytranspose)(PC, Vec, Vec))
668 {
669   PetscFunctionBegin;
670   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
671   PetscTryMethod(pc, "PCShellSetApplyTranspose_C", (PC, PetscErrorCode(*)(PC, Vec, Vec)), (pc, applytranspose));
672   PetscFunctionReturn(PETSC_SUCCESS);
673 }
674 
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.
679 
680   Logically Collective
681 
682   Input Parameters:
683 + pc       - the preconditioner context
684 - presolve - the application-provided presolve routine
685 
686   Calling sequence of `presolve`:
687 .vb
688    PetscErrorCode presolve(PC pc, KSP ksp, Vec b, Vec x)
689 .ve
690 + pc - the preconditioner, get the application context with `PCShellGetContext()`
691 .  xin - input vector
692 -  xout - output vector
693 
694   Level: advanced
695 
696 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetPostSolve()`, `PCShellSetContext()`
697 @*/
698 PetscErrorCode PCShellSetPreSolve(PC pc, PetscErrorCode (*presolve)(PC, KSP, Vec, Vec))
699 {
700   PetscFunctionBegin;
701   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
702   PetscTryMethod(pc, "PCShellSetPreSolve_C", (PC, PetscErrorCode(*)(PC, KSP, Vec, Vec)), (pc, presolve));
703   PetscFunctionReturn(PETSC_SUCCESS);
704 }
705 
706 /*@C
707   PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a `KSPSolve()` is
708   applied. This usually does something like scale the linear system in some application
709   specific way.
710 
711   Logically Collective
712 
713   Input Parameters:
714 + pc        - the preconditioner context
715 - postsolve - the application-provided presolve routine
716 
717   Calling sequence of `postsolve`:
718 .vb
719    PetscErrorCode postsolve(PC pc, KSP ksp, Vec b, Vec x)
720 .ve
721 + pc - the preconditioner, get the application context with `PCShellGetContext()`
722 .  xin - input vector
723 -  xout - output vector
724 
725   Level: advanced
726 
727 .seealso: `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetPreSolve()`, `PCShellSetContext()`
728 @*/
729 PetscErrorCode PCShellSetPostSolve(PC pc, PetscErrorCode (*postsolve)(PC, KSP, Vec, Vec))
730 {
731   PetscFunctionBegin;
732   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
733   PetscTryMethod(pc, "PCShellSetPostSolve_C", (PC, PetscErrorCode(*)(PC, KSP, Vec, Vec)), (pc, postsolve));
734   PetscFunctionReturn(PETSC_SUCCESS);
735 }
736 
737 /*@C
738   PCShellSetName - Sets an optional name to associate with a `PCSHELL`
739   preconditioner.
740 
741   Not Collective
742 
743   Input Parameters:
744 + pc   - the preconditioner context
745 - name - character string describing shell preconditioner
746 
747   Level: intermediate
748 
749 .seealso: `PCSHELL`, `PCShellGetName()`
750 @*/
751 PetscErrorCode PCShellSetName(PC pc, const char name[])
752 {
753   PetscFunctionBegin;
754   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
755   PetscTryMethod(pc, "PCShellSetName_C", (PC, const char[]), (pc, name));
756   PetscFunctionReturn(PETSC_SUCCESS);
757 }
758 
759 /*@C
760   PCShellGetName - Gets an optional name that the user has set for a `PCSHELL`
761   preconditioner.
762 
763   Not Collective
764 
765   Input Parameter:
766 . pc - the preconditioner context
767 
768   Output Parameter:
769 . name - character string describing shell preconditioner (you should not free this)
770 
771   Level: intermediate
772 
773 .seealso: `PCSHELL`, `PCShellSetName()`
774 @*/
775 PetscErrorCode PCShellGetName(PC pc, const char *name[])
776 {
777   PetscFunctionBegin;
778   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
779   PetscValidPointer(name, 2);
780   PetscUseMethod(pc, "PCShellGetName_C", (PC, const char *[]), (pc, name));
781   PetscFunctionReturn(PETSC_SUCCESS);
782 }
783 
784 /*@C
785   PCShellSetApplyRichardson - Sets routine to use as preconditioner
786   in Richardson iteration.
787 
788   Logically Collective
789 
790   Input Parameters:
791 + pc    - the preconditioner context
792 - apply - the application-provided preconditioning routine
793 
794   Calling sequence of `apply`:
795 .vb
796    PetscErrorCode apply(PC pc, Vec b, Vec x, Vec r, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt maxits)
797 .ve
798 + pc - the preconditioner, get the application context with `PCShellGetContext()`
799 .  b - right-hand-side
800 .  x - current iterate
801 .  r - work space
802 .  rtol - relative tolerance of residual norm to stop at
803 .  abstol - absolute tolerance of residual norm to stop at
804 .  dtol - if residual norm increases by this factor than return
805 -  maxits - number of iterations to run
806 
807   Level: advanced
808 
809 .seealso: `PCShellSetApply()`, `PCShellSetContext()`
810 @*/
811 PetscErrorCode PCShellSetApplyRichardson(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *))
812 {
813   PetscFunctionBegin;
814   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
815   PetscTryMethod(pc, "PCShellSetApplyRichardson_C", (PC, PetscErrorCode(*)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *)), (pc, apply));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*MC
820    PCSHELL - Creates a new preconditioner class for use with a users
821               own private data storage format and preconditioner application code
822 
823    Level: advanced
824 
825   Usage:
826 .vb
827        extern PetscErrorCode apply(PC,Vec,Vec);
828        extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec);
829        extern PetscErrorCode applytranspose(PC,Vec,Vec);
830        extern PetscErrorCode setup(PC);
831        extern PetscErrorCode destroy(PC);
832 
833        PCCreate(comm,&pc);
834        PCSetType(pc,PCSHELL);
835        PCShellSetContext(pc,ctx)
836        PCShellSetApply(pc,apply);
837        PCShellSetApplyBA(pc,applyba);               (optional)
838        PCShellSetApplyTranspose(pc,applytranspose); (optional)
839        PCShellSetSetUp(pc,setup);                   (optional)
840        PCShellSetDestroy(pc,destroy);               (optional)
841 .ve
842 
843 .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
844           `MATSHELL`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCShellSetView()`, `PCShellSetDestroy()`, `PCShellSetPostSolve()`,
845           `PCShellSetApplyTranspose()`, `PCShellSetName()`, `PCShellSetApplyRichardson()`, `PCShellSetPreSolve()`, `PCShellSetView()`,
846           `PCShellGetName()`, `PCShellSetContext()`, `PCShellGetContext()`, `PCShellSetApplyBA()`, `MATSHELL`, `PCShellSetMatApply()`,
847 M*/
848 
849 PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc)
850 {
851   PC_Shell *shell;
852 
853   PetscFunctionBegin;
854   PetscCall(PetscNew(&shell));
855   pc->data = (void *)shell;
856 
857   pc->ops->destroy             = PCDestroy_Shell;
858   pc->ops->view                = PCView_Shell;
859   pc->ops->apply               = PCApply_Shell;
860   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_Shell;
861   pc->ops->applysymmetricright = PCApplySymmetricRight_Shell;
862   pc->ops->matapply            = NULL;
863   pc->ops->applytranspose      = NULL;
864   pc->ops->applyrichardson     = NULL;
865   pc->ops->setup               = NULL;
866   pc->ops->presolve            = NULL;
867   pc->ops->postsolve           = NULL;
868 
869   shell->apply               = NULL;
870   shell->applytranspose      = NULL;
871   shell->name                = NULL;
872   shell->applyrich           = NULL;
873   shell->presolve            = NULL;
874   shell->postsolve           = NULL;
875   shell->ctx                 = NULL;
876   shell->setup               = NULL;
877   shell->view                = NULL;
878   shell->destroy             = NULL;
879   shell->applysymmetricleft  = NULL;
880   shell->applysymmetricright = NULL;
881 
882   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetDestroy_C", PCShellSetDestroy_Shell));
883   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetSetUp_C", PCShellSetSetUp_Shell));
884   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApply_C", PCShellSetApply_Shell));
885   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApply_C", PCShellSetMatApply_Shell));
886   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricLeft_C", PCShellSetApplySymmetricLeft_Shell));
887   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricRight_C", PCShellSetApplySymmetricRight_Shell));
888   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyBA_C", PCShellSetApplyBA_Shell));
889   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPreSolve_C", PCShellSetPreSolve_Shell));
890   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPostSolve_C", PCShellSetPostSolve_Shell));
891   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetView_C", PCShellSetView_Shell));
892   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyTranspose_C", PCShellSetApplyTranspose_Shell));
893   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetName_C", PCShellSetName_Shell));
894   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellGetName_C", PCShellGetName_Shell));
895   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyRichardson_C", PCShellSetApplyRichardson_Shell));
896   PetscFunctionReturn(PETSC_SUCCESS);
897 }
898