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