xref: /petsc/src/ksp/pc/impls/shell/shellpc.c (revision fcca9d3d5c45103cafcd0f6bc9babe194d935ced)
1 /*$Id: shellpc.c,v 1.77 2001/08/21 21:03:18 bsmith Exp $*/
2 
3 /*
4    This provides a simple shell for Fortran (and C programmers) to
5   create their own preconditioner without writing much interface code.
6 */
7 
8 #include "src/ksp/pc/pcimpl.h"        /*I "petscpc.h" I*/
9 #include "src/vec/vecimpl.h"
10 
11 EXTERN_C_BEGIN
12 typedef struct {
13   void *ctx,*ctxrich;    /* user provided contexts for preconditioner */
14   int  (*setup)(void *);
15   int  (*apply)(void *,Vec,Vec);
16   int  (*view)(void *,PetscViewer);
17   int  (*applytranspose)(void *,Vec,Vec);
18   int  (*applyrich)(void *,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int);
19   char *name;
20 } PC_Shell;
21 EXTERN_C_END
22 
23 #undef __FUNCT__
24 #define __FUNCT__ "PCApply_SetUp"
25 static int PCSetUp_Shell(PC pc)
26 {
27   PC_Shell *shell;
28   int      ierr;
29 
30   PetscFunctionBegin;
31   shell = (PC_Shell*)pc->data;
32   if (shell->setup) {
33     ierr  = (*shell->setup)(shell->ctx);CHKERRQ(ierr);
34   }
35   PetscFunctionReturn(0);
36 }
37 
38 #undef __FUNCT__
39 #define __FUNCT__ "PCApply_Shell"
40 static int PCApply_Shell(PC pc,Vec x,Vec y)
41 {
42   PC_Shell *shell;
43   int      ierr;
44 
45   PetscFunctionBegin;
46   shell = (PC_Shell*)pc->data;
47   if (!shell->apply) SETERRQ(1,"No apply() routine provided to Shell PC");
48   ierr  = (*shell->apply)(shell->ctx,x,y);CHKERRQ(ierr);
49   PetscFunctionReturn(0);
50 }
51 
52 #undef __FUNCT__
53 #define __FUNCT__ "PCApplyTranspose_Shell"
54 static int PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
55 {
56   PC_Shell *shell;
57   int      ierr;
58 
59   PetscFunctionBegin;
60   shell = (PC_Shell*)pc->data;
61   if (!shell->applytranspose) SETERRQ(1,"No applytranspose() routine provided to Shell PC");
62   ierr  = (*shell->applytranspose)(shell->ctx,x,y);CHKERRQ(ierr);
63   PetscFunctionReturn(0);
64 }
65 
66 #undef __FUNCT__
67 #define __FUNCT__ "PCApplyRichardson_Shell"
68 static int PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int it)
69 {
70   int      ierr;
71   PC_Shell *shell;
72 
73   PetscFunctionBegin;
74   shell = (PC_Shell*)pc->data;
75   ierr  = (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,atol,dtol,it);CHKERRQ(ierr);
76   PetscFunctionReturn(0);
77 }
78 
79 #undef __FUNCT__
80 #define __FUNCT__ "PCDestroy_Shell"
81 static int PCDestroy_Shell(PC pc)
82 {
83   PC_Shell *shell = (PC_Shell*)pc->data;
84   int      ierr;
85 
86   PetscFunctionBegin;
87   if (shell->name) {ierr = PetscFree(shell->name);}
88   ierr = PetscFree(shell);CHKERRQ(ierr);
89   PetscFunctionReturn(0);
90 }
91 
92 #undef __FUNCT__
93 #define __FUNCT__ "PCView_Shell"
94 static int PCView_Shell(PC pc,PetscViewer viewer)
95 {
96   PC_Shell   *shell = (PC_Shell*)pc->data;
97   int        ierr;
98   PetscTruth isascii;
99 
100   PetscFunctionBegin;
101   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
102   if (isascii) {
103     if (shell->name) {ierr = PetscViewerASCIIPrintf(viewer,"  Shell: %s\n",shell->name);CHKERRQ(ierr);}
104     else             {ierr = PetscViewerASCIIPrintf(viewer,"  Shell: no name\n");CHKERRQ(ierr);}
105   }
106   if (shell->view) {
107     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
108     ierr  = (*shell->view)(shell->ctx,viewer);CHKERRQ(ierr);
109     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
110   }
111   PetscFunctionReturn(0);
112 }
113 
114 /* ------------------------------------------------------------------------------*/
115 EXTERN_C_BEGIN
116 #undef __FUNCT__
117 #define __FUNCT__ "PCShellSetSetUp_Shell"
118 int PCShellSetSetUp_Shell(PC pc, int (*setup)(void*))
119 {
120   PC_Shell *shell;
121 
122   PetscFunctionBegin;
123   shell        = (PC_Shell*)pc->data;
124   shell->setup = setup;
125   PetscFunctionReturn(0);
126 }
127 EXTERN_C_END
128 
129 EXTERN_C_BEGIN
130 #undef __FUNCT__
131 #define __FUNCT__ "PCShellSetApply_Shell"
132 int PCShellSetApply_Shell(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
133 {
134   PC_Shell *shell;
135 
136   PetscFunctionBegin;
137   shell        = (PC_Shell*)pc->data;
138   shell->apply = apply;
139   shell->ctx   = ptr;
140   PetscFunctionReturn(0);
141 }
142 EXTERN_C_END
143 
144 EXTERN_C_BEGIN
145 #undef __FUNCT__
146 #define __FUNCT__ "PCShellSetView_Shell"
147 int PCShellSetView_Shell(PC pc,int (*view)(void*,PetscViewer))
148 {
149   PC_Shell *shell;
150 
151   PetscFunctionBegin;
152   shell        = (PC_Shell*)pc->data;
153   shell->view = view;
154   PetscFunctionReturn(0);
155 }
156 EXTERN_C_END
157 
158 EXTERN_C_BEGIN
159 #undef __FUNCT__
160 #define __FUNCT__ "PCShellSetApplyTranspose_Shell"
161 int PCShellSetApplyTranspose_Shell(PC pc,int (*applytranspose)(void*,Vec,Vec))
162 {
163   PC_Shell *shell;
164 
165   PetscFunctionBegin;
166   shell                 = (PC_Shell*)pc->data;
167   shell->applytranspose = applytranspose;
168   PetscFunctionReturn(0);
169 }
170 EXTERN_C_END
171 
172 EXTERN_C_BEGIN
173 #undef __FUNCT__
174 #define __FUNCT__ "PCShellSetName_Shell"
175 int PCShellSetName_Shell(PC pc,const char name[])
176 {
177   PC_Shell *shell;
178   int      ierr;
179 
180   PetscFunctionBegin;
181   shell = (PC_Shell*)pc->data;
182   ierr  = PetscStrallocpy(name,&shell->name);CHKERRQ(ierr);
183   PetscFunctionReturn(0);
184 }
185 EXTERN_C_END
186 
187 EXTERN_C_BEGIN
188 #undef __FUNCT__
189 #define __FUNCT__ "PCShellGetName_Shell"
190 int PCShellGetName_Shell(PC pc,char *name[])
191 {
192   PC_Shell *shell;
193 
194   PetscFunctionBegin;
195   shell  = (PC_Shell*)pc->data;
196   *name  = shell->name;
197   PetscFunctionReturn(0);
198 }
199 EXTERN_C_END
200 
201 EXTERN_C_BEGIN
202 #undef __FUNCT__
203 #define __FUNCT__ "PCShellSetApplyRichardson_Shell"
204 int PCShellSetApplyRichardson_Shell(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
205 {
206   PC_Shell *shell;
207 
208   PetscFunctionBegin;
209   shell                     = (PC_Shell*)pc->data;
210   pc->ops->applyrichardson  = PCApplyRichardson_Shell;
211   shell->applyrich          = apply;
212   shell->ctxrich            = ptr;
213   PetscFunctionReturn(0);
214 }
215 EXTERN_C_END
216 
217 /* -------------------------------------------------------------------------------*/
218 
219 #undef __FUNCT__
220 #define __FUNCT__ "PCShellSetSetUp"
221 /*@C
222    PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
223    matrix operator is changed.
224 
225    Collective on PC
226 
227    Input Parameters:
228 +  pc - the preconditioner context
229 .  setup - the application-provided setup routine
230 
231    Calling sequence of setup:
232 .vb
233    int setup (void *ptr)
234 .ve
235 
236 .  ptr - the application context
237 
238    Level: developer
239 
240 .keywords: PC, shell, set, setup, user-provided
241 
242 .seealso: PCShellSetApplyRichardson(), PCShellSetApply()
243 @*/
244 int PCShellSetSetUp(PC pc,int (*setup)(void*))
245 {
246   int ierr,(*f)(PC,int (*)(void*));
247 
248   PetscFunctionBegin;
249   PetscValidHeaderSpecific(pc,PC_COOKIE);
250   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetSetUp_C",(void (**)(void))&f);CHKERRQ(ierr);
251   if (f) {
252     ierr = (*f)(pc,setup);CHKERRQ(ierr);
253   }
254   PetscFunctionReturn(0);
255 }
256 
257 
258 #undef __FUNCT__
259 #define __FUNCT__ "PCShellSetView"
260 /*@C
261    PCShellSetView - Sets routine to use as viewer of shell preconditioner
262 
263    Collective on PC
264 
265    Input Parameters:
266 +  pc - the preconditioner context
267 -  view - the application-provided view routine
268 
269    Calling sequence of apply:
270 .vb
271    int view(void *ptr,PetscViewer v)
272 .ve
273 
274 +  ptr - the application context
275 -  v   - viewer
276 
277    Level: developer
278 
279 .keywords: PC, shell, set, apply, user-provided
280 
281 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
282 @*/
283 int PCShellSetView(PC pc,int (*view)(void*,PetscViewer))
284 {
285   int ierr,(*f)(PC,int (*)(void*,PetscViewer));
286 
287   PetscFunctionBegin;
288   PetscValidHeaderSpecific(pc,PC_COOKIE);
289   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetView_C",(void (**)(void))&f);CHKERRQ(ierr);
290   if (f) {
291     ierr = (*f)(pc,view);CHKERRQ(ierr);
292   }
293   PetscFunctionReturn(0);
294 }
295 
296 #undef __FUNCT__
297 #define __FUNCT__ "PCShellSetApply"
298 /*@C
299    PCShellSetApply - Sets routine to use as preconditioner.
300 
301    Collective on PC
302 
303    Input Parameters:
304 +  pc - the preconditioner context
305 .  apply - the application-provided preconditioning routine
306 -  ptr - pointer to data needed by this routine
307 
308    Calling sequence of apply:
309 .vb
310    int apply (void *ptr,Vec xin,Vec xout)
311 .ve
312 
313 +  ptr - the application context
314 .  xin - input vector
315 -  xout - output vector
316 
317    Level: developer
318 
319 .keywords: PC, shell, set, apply, user-provided
320 
321 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApplyTranspose()
322 @*/
323 int PCShellSetApply(PC pc,int (*apply)(void*,Vec,Vec),void *ptr)
324 {
325   int ierr,(*f)(PC,int (*)(void*,Vec,Vec),void *);
326 
327   PetscFunctionBegin;
328   PetscValidHeaderSpecific(pc,PC_COOKIE);
329   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApply_C",(void (**)(void))&f);CHKERRQ(ierr);
330   if (f) {
331     ierr = (*f)(pc,apply,ptr);CHKERRQ(ierr);
332   }
333   PetscFunctionReturn(0);
334 }
335 
336 #undef __FUNCT__
337 #define __FUNCT__ "PCShellSetApplyTranspose"
338 /*@C
339    PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.
340 
341    Collective on PC
342 
343    Input Parameters:
344 +  pc - the preconditioner context
345 -  apply - the application-provided preconditioning transpose routine
346 
347    Calling sequence of apply:
348 .vb
349    int applytranspose (void *ptr,Vec xin,Vec xout)
350 .ve
351 
352 +  ptr - the application context
353 .  xin - input vector
354 -  xout - output vector
355 
356    Level: developer
357 
358    Notes:
359    Uses the same context variable as PCShellSetApply().
360 
361 .keywords: PC, shell, set, apply, user-provided
362 
363 .seealso: PCShellSetApplyRichardson(), PCShellSetSetUp(), PCShellSetApply()
364 @*/
365 int PCShellSetApplyTranspose(PC pc,int (*applytranspose)(void*,Vec,Vec))
366 {
367   int ierr,(*f)(PC,int (*)(void*,Vec,Vec));
368 
369   PetscFunctionBegin;
370   PetscValidHeaderSpecific(pc,PC_COOKIE);
371   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyTranspose_C",(void (**)(void))&f);CHKERRQ(ierr);
372   if (f) {
373     ierr = (*f)(pc,applytranspose);CHKERRQ(ierr);
374   }
375   PetscFunctionReturn(0);
376 }
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "PCShellSetName"
380 /*@C
381    PCShellSetName - Sets an optional name to associate with a shell
382    preconditioner.
383 
384    Not Collective
385 
386    Input Parameters:
387 +  pc - the preconditioner context
388 -  name - character string describing shell preconditioner
389 
390    Level: developer
391 
392 .keywords: PC, shell, set, name, user-provided
393 
394 .seealso: PCShellGetName()
395 @*/
396 int PCShellSetName(PC pc,const char name[])
397 {
398   int ierr,(*f)(PC,const char []);
399 
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(pc,PC_COOKIE);
402   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetName_C",(void (**)(void))&f);CHKERRQ(ierr);
403   if (f) {
404     ierr = (*f)(pc,name);CHKERRQ(ierr);
405   }
406   PetscFunctionReturn(0);
407 }
408 
409 #undef __FUNCT__
410 #define __FUNCT__ "PCShellGetName"
411 /*@C
412    PCShellGetName - Gets an optional name that the user has set for a shell
413    preconditioner.
414 
415    Not Collective
416 
417    Input Parameter:
418 .  pc - the preconditioner context
419 
420    Output Parameter:
421 .  name - character string describing shell preconditioner (you should not free this)
422 
423    Level: developer
424 
425 .keywords: PC, shell, get, name, user-provided
426 
427 .seealso: PCShellSetName()
428 @*/
429 int PCShellGetName(PC pc,char *name[])
430 {
431   int ierr,(*f)(PC,char *[]);
432 
433   PetscFunctionBegin;
434   PetscValidHeaderSpecific(pc,PC_COOKIE);
435   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);CHKERRQ(ierr);
436   if (f) {
437     ierr = (*f)(pc,name);CHKERRQ(ierr);
438   } else {
439     SETERRQ(1,"Not shell preconditioner, cannot get name");
440   }
441   PetscFunctionReturn(0);
442 }
443 
444 #undef __FUNCT__
445 #define __FUNCT__ "PCShellSetApplyRichardson"
446 /*@C
447    PCShellSetApplyRichardson - Sets routine to use as preconditioner
448    in Richardson iteration.
449 
450    Collective on PC
451 
452    Input Parameters:
453 +  pc - the preconditioner context
454 .  apply - the application-provided preconditioning routine
455 -  ptr - pointer to data needed by this routine
456 
457    Calling sequence of apply:
458 .vb
459    int apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal atol,PetscReal dtol,int maxits)
460 .ve
461 
462 +  ptr - the application context
463 .  b - right-hand-side
464 .  x - current iterate
465 .  r - work space
466 .  rtol - relative tolerance of residual norm to stop at
467 .  atol - absolute tolerance of residual norm to stop at
468 .  dtol - if residual norm increases by this factor than return
469 -  maxits - number of iterations to run
470 
471    Level: developer
472 
473 .keywords: PC, shell, set, apply, Richardson, user-provided
474 
475 .seealso: PCShellSetApply()
476 @*/
477 int PCShellSetApplyRichardson(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
478 {
479   int ierr,(*f)(PC,int (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *);
480 
481   PetscFunctionBegin;
482   PetscValidHeaderSpecific(pc,PC_COOKIE);
483   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);CHKERRQ(ierr);
484   if (f) {
485     ierr = (*f)(pc,apply,ptr);CHKERRQ(ierr);
486   }
487   PetscFunctionReturn(0);
488 }
489 
490 /*MC
491    PCSHELL - Creates a new preconditioner class for use with your
492               own private data storage format.
493 
494    Level: advanced
495 
496    Concepts: providing your own preconditioner
497 
498   Usage:
499 $             int (*mult)(void *,Vec,Vec);
500 $             int (*setup)(void *);
501 $             PCCreate(comm,&pc);
502 $             PCSetType(pc,PCSHELL);
503 $             PCShellSetApply(pc,mult,ctx);
504 $             PCShellSetSetUp(pc,setup);       (optional)
505 
506 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
507            KSPSHELL(), MATSHELL(), PCShellSetUp(), PCShellSetApply(), PCShellSetView(),
508            PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(),
509            PCShellGetName()
510 M*/
511 
512 EXTERN_C_BEGIN
513 #undef __FUNCT__
514 #define __FUNCT__ "PCCreate_Shell"
515 int PCCreate_Shell(PC pc)
516 {
517   int      ierr;
518   PC_Shell *shell;
519 
520   PetscFunctionBegin;
521   pc->ops->destroy    = PCDestroy_Shell;
522   ierr                = PetscNew(PC_Shell,&shell);CHKERRQ(ierr);
523   PetscLogObjectMemory(pc,sizeof(PC_Shell));
524 
525   pc->data         = (void*)shell;
526   pc->name         = 0;
527 
528   pc->ops->apply           = PCApply_Shell;
529   pc->ops->view            = PCView_Shell;
530   pc->ops->applytranspose  = PCApplyTranspose_Shell;
531   pc->ops->applyrichardson = 0;
532   pc->ops->setup           = PCSetUp_Shell;
533   pc->ops->view            = PCView_Shell;
534 
535   shell->apply          = 0;
536   shell->applytranspose = 0;
537   shell->name           = 0;
538   shell->applyrich      = 0;
539   shell->ctxrich        = 0;
540   shell->ctx            = 0;
541   shell->setup          = 0;
542   shell->view           = 0;
543 
544   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
545                     PCShellSetSetUp_Shell);CHKERRQ(ierr);
546   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
547                     PCShellSetApply_Shell);CHKERRQ(ierr);
548   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell",
549                     PCShellSetView_Shell);CHKERRQ(ierr);
550   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C",
551                     "PCShellSetApplyTranspose_Shell",
552                     PCShellSetApplyTranspose_Shell);CHKERRQ(ierr);
553   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
554                     PCShellSetName_Shell);CHKERRQ(ierr);
555   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
556                     PCShellGetName_Shell);CHKERRQ(ierr);
557   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C",
558                     "PCShellSetApplyRichardson_Shell",
559                     PCShellSetApplyRichardson_Shell);CHKERRQ(ierr);
560 
561   PetscFunctionReturn(0);
562 }
563 EXTERN_C_END
564 
565 
566 
567 
568 
569 
570