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