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