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