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