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