xref: /petsc/src/ksp/pc/impls/shell/shellpc.c (revision 0cd40bc26a1ce01d47f2b1f8c15c569742939873)
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    Developer Notes: There should also be a PCShellSetApplySymmetricRight() and PCShellSetApplySymmetricLeft().
608 
609    Level: developer
610 
611 .keywords: PC, shell, set, apply, user-provided
612 
613 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApplyBA()
614 @*/
615 PetscErrorCode  PCShellSetApply(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
616 {
617   PetscErrorCode ierr;
618 
619   PetscFunctionBegin;
620   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
621   ierr = PetscTryMethod(pc,"PCShellSetApply_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr);
622   PetscFunctionReturn(0);
623 }
624 
625 #undef __FUNCT__
626 #define __FUNCT__ "PCShellSetApplySymmetricLeft"
627 /*@C
628    PCShellSetApplySymmetricLeft - Sets routine to use as left preconditioner (when the PC_SYMMETRIC is used).
629 
630    Logically Collective on PC
631 
632    Input Parameters:
633 +  pc - the preconditioner context
634 -  apply - the application-provided left preconditioning routine
635 
636    Calling sequence of apply:
637 .vb
638    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
639 .ve
640 
641 +  pc - the preconditioner, get the application context with PCShellGetContext()
642 .  xin - input vector
643 -  xout - output vector
644 
645    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
646 
647    Level: developer
648 
649 .keywords: PC, shell, set, apply, user-provided
650 
651 .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
652 @*/
653 PetscErrorCode  PCShellSetApplySymmetricLeft(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
654 {
655   PetscErrorCode ierr;
656 
657   PetscFunctionBegin;
658   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
659   ierr = PetscTryMethod(pc,"PCShellSetApplySymmetricLeft_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr);
660   PetscFunctionReturn(0);
661 }
662 
663 #undef __FUNCT__
664 #define __FUNCT__ "PCShellSetApplySymmetricRight"
665 /*@C
666    PCShellSetApply - Sets routine to use as right preconditioner (when the PC_SYMMETRIC is used).
667 
668    Logically Collective on PC
669 
670    Input Parameters:
671 +  pc - the preconditioner context
672 -  apply - the application-provided right preconditioning routine
673 
674    Calling sequence of apply:
675 .vb
676    PetscErrorCode apply (PC pc,Vec xin,Vec xout)
677 .ve
678 
679 +  pc - the preconditioner, get the application context with PCShellGetContext()
680 .  xin - input vector
681 -  xout - output vector
682 
683    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
684 
685    Level: developer
686 
687 .keywords: PC, shell, set, apply, user-provided
688 
689 .seealso: PCShellSetApply(), PCShellSetApplySymmetricLeft(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext()
690 @*/
691 PetscErrorCode  PCShellSetApplySymmetricRight(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec))
692 {
693   PetscErrorCode ierr;
694 
695   PetscFunctionBegin;
696   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
697   ierr = PetscTryMethod(pc,"PCShellSetApplySymmetricRight_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,apply));CHKERRQ(ierr);
698   PetscFunctionReturn(0);
699 }
700 
701 #undef __FUNCT__
702 #define __FUNCT__ "PCShellSetApplyBA"
703 /*@C
704    PCShellSetApplyBA - Sets routine to use as preconditioner times operator.
705 
706    Logically Collective on PC
707 
708    Input Parameters:
709 +  pc - the preconditioner context
710 -  applyBA - the application-provided BA routine
711 
712    Calling sequence of apply:
713 .vb
714    PetscErrorCode applyBA (PC pc,Vec xin,Vec xout)
715 .ve
716 
717 +  pc - the preconditioner, get the application context with PCShellGetContext()
718 .  xin - input vector
719 -  xout - output vector
720 
721    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
722 
723    Level: developer
724 
725 .keywords: PC, shell, set, apply, user-provided
726 
727 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetContext(), PCShellSetApply()
728 @*/
729 PetscErrorCode  PCShellSetApplyBA(PC pc,PetscErrorCode (*applyBA)(PC,PCSide,Vec,Vec,Vec))
730 {
731   PetscErrorCode ierr;
732 
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
735   ierr = PetscTryMethod(pc,"PCShellSetApplyBA_C",(PC,PetscErrorCode (*)(PC,PCSide,Vec,Vec,Vec)),(pc,applyBA));CHKERRQ(ierr);
736   PetscFunctionReturn(0);
737 }
738 
739 #undef __FUNCT__
740 #define __FUNCT__ "PCShellSetApplyTranspose"
741 /*@C
742    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.
743 
744    Logically Collective on PC
745 
746    Input Parameters:
747 +  pc - the preconditioner context
748 -  apply - the application-provided preconditioning transpose routine
749 
750    Calling sequence of apply:
751 .vb
752    PetscErrorCode applytranspose (PC pc,Vec xin,Vec xout)
753 .ve
754 
755 +  pc - the preconditioner, get the application context with PCShellGetContext()
756 .  xin - input vector
757 -  xout - output vector
758 
759    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
760 
761    Level: developer
762 
763    Notes:
764    Uses the same context variable as PCShellSetApply().
765 
766 .keywords: PC, shell, set, apply, user-provided
767 
768 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply(), PCSetContext(), PCShellSetApplyBA()
769 @*/
770 PetscErrorCode  PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(PC,Vec,Vec))
771 {
772   PetscErrorCode ierr;
773 
774   PetscFunctionBegin;
775   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
776   ierr = PetscTryMethod(pc,"PCShellSetApplyTranspose_C",(PC,PetscErrorCode (*)(PC,Vec,Vec)),(pc,applytranspose));CHKERRQ(ierr);
777   PetscFunctionReturn(0);
778 }
779 
780 #undef __FUNCT__
781 #define __FUNCT__ "PCShellSetPreSolve"
782 /*@C
783    PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is
784       applied. This usually does something like scale the linear system in some application
785       specific way.
786 
787    Logically Collective on PC
788 
789    Input Parameters:
790 +  pc - the preconditioner context
791 -  presolve - the application-provided presolve routine
792 
793    Calling sequence of presolve:
794 .vb
795    PetscErrorCode presolve (PC,KSP ksp,Vec b,Vec x)
796 .ve
797 
798 +  pc - the preconditioner, get the application context with PCShellGetContext()
799 .  xin - input vector
800 -  xout - output vector
801 
802    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
803 
804    Level: developer
805 
806 .keywords: PC, shell, set, apply, user-provided
807 
808 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPostSolve(), PCShellSetContext()
809 @*/
810 PetscErrorCode  PCShellSetPreSolve(PC pc,PetscErrorCode (*presolve)(PC,KSP,Vec,Vec))
811 {
812   PetscErrorCode ierr;
813 
814   PetscFunctionBegin;
815   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
816   ierr = PetscTryMethod(pc,"PCShellSetPreSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,presolve));CHKERRQ(ierr);
817   PetscFunctionReturn(0);
818 }
819 
820 #undef __FUNCT__
821 #define __FUNCT__ "PCShellSetPostSolve"
822 /*@C
823    PCShellSetPostSolve - Sets routine to apply to the operators/vectors before a KSPSolve() is
824       applied. This usually does something like scale the linear system in some application
825       specific way.
826 
827    Logically Collective on PC
828 
829    Input Parameters:
830 +  pc - the preconditioner context
831 -  postsolve - the application-provided presolve routine
832 
833    Calling sequence of postsolve:
834 .vb
835    PetscErrorCode postsolve(PC,KSP ksp,Vec b,Vec x)
836 .ve
837 
838 +  pc - the preconditioner, get the application context with PCShellGetContext()
839 .  xin - input vector
840 -  xout - output vector
841 
842    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
843 
844    Level: developer
845 
846 .keywords: PC, shell, set, apply, user-provided
847 
848 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose(), PCShellSetPreSolve(), PCShellSetContext()
849 @*/
850 PetscErrorCode  PCShellSetPostSolve(PC pc,PetscErrorCode (*postsolve)(PC,KSP,Vec,Vec))
851 {
852   PetscErrorCode ierr;
853 
854   PetscFunctionBegin;
855   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
856   ierr = PetscTryMethod(pc,"PCShellSetPostSolve_C",(PC,PetscErrorCode (*)(PC,KSP,Vec,Vec)),(pc,postsolve));CHKERRQ(ierr);
857   PetscFunctionReturn(0);
858 }
859 
860 #undef __FUNCT__
861 #define __FUNCT__ "PCShellSetName"
862 /*@C
863    PCShellSetName - Sets an optional name to associate with a shell
864    preconditioner.
865 
866    Not Collective
867 
868    Input Parameters:
869 +  pc - the preconditioner context
870 -  name - character string describing shell preconditioner
871 
872    Level: developer
873 
874 .keywords: PC, shell, set, name, user-provided
875 
876 .seealso: PCShellGetName()
877 @*/
878 PetscErrorCode  PCShellSetName(PC pc,const char name[])
879 {
880   PetscErrorCode ierr;
881 
882   PetscFunctionBegin;
883   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
884   ierr = PetscTryMethod(pc,"PCShellSetName_C",(PC,const char []),(pc,name));CHKERRQ(ierr);
885   PetscFunctionReturn(0);
886 }
887 
888 #undef __FUNCT__
889 #define __FUNCT__ "PCShellGetName"
890 /*@C
891    PCShellGetName - Gets an optional name that the user has set for a shell
892    preconditioner.
893 
894    Not Collective
895 
896    Input Parameter:
897 .  pc - the preconditioner context
898 
899    Output Parameter:
900 .  name - character string describing shell preconditioner (you should not free this)
901 
902    Level: developer
903 
904 .keywords: PC, shell, get, name, user-provided
905 
906 .seealso: PCShellSetName()
907 @*/
908 PetscErrorCode  PCShellGetName(PC pc,const char *name[])
909 {
910   PetscErrorCode ierr;
911 
912   PetscFunctionBegin;
913   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
914   PetscValidPointer(name,2);
915   ierr = PetscUseMethod(pc,"PCShellGetName_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr);
916   PetscFunctionReturn(0);
917 }
918 
919 #undef __FUNCT__
920 #define __FUNCT__ "PCShellSetApplyRichardson"
921 /*@C
922    PCShellSetApplyRichardson - Sets routine to use as preconditioner
923    in Richardson iteration.
924 
925    Logically Collective on PC
926 
927    Input Parameters:
928 +  pc - the preconditioner context
929 -  apply - the application-provided preconditioning routine
930 
931    Calling sequence of apply:
932 .vb
933    PetscErrorCode apply (PC pc,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt maxits)
934 .ve
935 
936 +  pc - the preconditioner, get the application context with PCShellGetContext()
937 .  b - right-hand-side
938 .  x - current iterate
939 .  r - work space
940 .  rtol - relative tolerance of residual norm to stop at
941 .  abstol - absolute tolerance of residual norm to stop at
942 .  dtol - if residual norm increases by this factor than return
943 -  maxits - number of iterations to run
944 
945    Notes: the function MUST return an error code of 0 on success and nonzero on failure.
946 
947    Level: developer
948 
949 .keywords: PC, shell, set, apply, Richardson, user-provided
950 
951 .seealso: PCShellSetApply(), PCShellSetContext()
952 @*/
953 PetscErrorCode  PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*))
954 {
955   PetscErrorCode ierr;
956 
957   PetscFunctionBegin;
958   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
959   ierr = PetscTryMethod(pc,"PCShellSetApplyRichardson_C",(PC,PetscErrorCode (*)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt,PetscBool,PetscInt*,PCRichardsonConvergedReason*)),(pc,apply));CHKERRQ(ierr);
960   PetscFunctionReturn(0);
961 }
962 
963 /*MC
964    PCSHELL - Creates a new preconditioner class for use with your
965               own private data storage format.
966 
967    Level: advanced
968 >
969    Concepts: providing your own preconditioner
970 
971   Usage:
972 $             extern PetscErrorCode apply(PC,Vec,Vec);
973 $             extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec);
974 $             extern PetscErrorCode applytranspose(PC,Vec,Vec);
975 $             extern PetscErrorCode setup(PC);
976 $             extern PetscErrorCode destroy(PC);
977 $
978 $             PCCreate(comm,&pc);
979 $             PCSetType(pc,PCSHELL);
980 $             PCShellSetContext(pc,ctx)
981 $             PCShellSetApply(pc,apply);
982 $             PCShellSetApplyBA(pc,applyba);               (optional)
983 $             PCShellSetApplyTranspose(pc,applytranspose); (optional)
984 $             PCShellSetSetUp(pc,setup);                   (optional)
985 $             PCShellSetDestroy(pc,destroy);               (optional)
986 
987 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
988            MATSHELL, PCShellSetSetUp(), PCShellSetApply(), PCShellSetView(),
989            PCShellSetApplyTranspose(), PCShellSetName(), PCShellSetApplyRichardson(),
990            PCShellGetName(), PCShellSetContext(), PCShellGetContext(), PCShellSetApplyBA()
991 M*/
992 
993 #undef __FUNCT__
994 #define __FUNCT__ "PCCreate_Shell"
995 PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc)
996 {
997   PetscErrorCode ierr;
998   PC_Shell       *shell;
999 
1000   PetscFunctionBegin;
1001   ierr     = PetscNewLog(pc,&shell);CHKERRQ(ierr);
1002   pc->data = (void*)shell;
1003 
1004   pc->ops->destroy         = PCDestroy_Shell;
1005   pc->ops->view            = PCView_Shell;
1006   pc->ops->apply           = PCApply_Shell;
1007   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_Shell;
1008   pc->ops->applysymmetricright = PCApplySymmetricRight_Shell;
1009   pc->ops->applytranspose  = 0;
1010   pc->ops->applyrichardson = 0;
1011   pc->ops->setup           = 0;
1012   pc->ops->presolve        = 0;
1013   pc->ops->postsolve       = 0;
1014 
1015   shell->apply          = 0;
1016   shell->applytranspose = 0;
1017   shell->name           = 0;
1018   shell->applyrich      = 0;
1019   shell->presolve       = 0;
1020   shell->postsolve      = 0;
1021   shell->ctx            = 0;
1022   shell->setup          = 0;
1023   shell->view           = 0;
1024   shell->destroy        = 0;
1025   shell->applysymmetricleft  = 0;
1026   shell->applysymmetricright = 0;
1027 
1028   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetDestroy_C",PCShellSetDestroy_Shell);CHKERRQ(ierr);
1029   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetSetUp_C",PCShellSetSetUp_Shell);CHKERRQ(ierr);
1030   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApply_C",PCShellSetApply_Shell);CHKERRQ(ierr);
1031   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricLeft_C",PCShellSetApplySymmetricLeft_Shell);CHKERRQ(ierr);
1032   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplySymmetricRight_C",PCShellSetApplySymmetricRight_Shell);CHKERRQ(ierr);
1033   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyBA_C",PCShellSetApplyBA_Shell);CHKERRQ(ierr);
1034   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPreSolve_C",PCShellSetPreSolve_Shell);CHKERRQ(ierr);
1035   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetPostSolve_C",PCShellSetPostSolve_Shell);CHKERRQ(ierr);
1036   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetView_C",PCShellSetView_Shell);CHKERRQ(ierr);
1037   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",PCShellSetApplyTranspose_Shell);CHKERRQ(ierr);
1038   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetName_C",PCShellSetName_Shell);CHKERRQ(ierr);
1039   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellGetName_C",PCShellGetName_Shell);CHKERRQ(ierr);
1040   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",PCShellSetApplyRichardson_Shell);CHKERRQ(ierr);
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 
1045 
1046 
1047 
1048 
1049