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