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