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