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