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