xref: /petsc/src/ksp/pc/impls/shell/shellpc.c (revision ebe3b25b9af58f1e4889057721e8e5fb9fab5adc)
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,1);
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,1);
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,1);
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,1);
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,1);
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,1);
435   PetscValidPointer(name,2);
436   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellGetName_C",(void (**)(void))&f);CHKERRQ(ierr);
437   if (f) {
438     ierr = (*f)(pc,name);CHKERRQ(ierr);
439   } else {
440     SETERRQ(1,"Not shell preconditioner, cannot get name");
441   }
442   PetscFunctionReturn(0);
443 }
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "PCShellSetApplyRichardson"
447 /*@C
448    PCShellSetApplyRichardson - Sets routine to use as preconditioner
449    in Richardson iteration.
450 
451    Collective on PC
452 
453    Input Parameters:
454 +  pc - the preconditioner context
455 .  apply - the application-provided preconditioning routine
456 -  ptr - pointer to data needed by this routine
457 
458    Calling sequence of apply:
459 .vb
460    int apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal atol,PetscReal dtol,int maxits)
461 .ve
462 
463 +  ptr - the application context
464 .  b - right-hand-side
465 .  x - current iterate
466 .  r - work space
467 .  rtol - relative tolerance of residual norm to stop at
468 .  atol - absolute tolerance of residual norm to stop at
469 .  dtol - if residual norm increases by this factor than return
470 -  maxits - number of iterations to run
471 
472    Level: developer
473 
474 .keywords: PC, shell, set, apply, Richardson, user-provided
475 
476 .seealso: PCShellSetApply()
477 @*/
478 int PCShellSetApplyRichardson(PC pc,int (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *ptr)
479 {
480   int ierr,(*f)(PC,int (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int),void *);
481 
482   PetscFunctionBegin;
483   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
484   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCShellSetApplyRichardson_C",(void (**)(void))&f);CHKERRQ(ierr);
485   if (f) {
486     ierr = (*f)(pc,apply,ptr);CHKERRQ(ierr);
487   }
488   PetscFunctionReturn(0);
489 }
490 
491 /*MC
492    PCSHELL - Creates a new preconditioner class for use with your
493               own private data storage format.
494 
495    Level: advanced
496 
497    Concepts: providing your own preconditioner
498 
499   Usage:
500 $             int (*mult)(void *,Vec,Vec);
501 $             int (*setup)(void *);
502 $             PCCreate(comm,&pc);
503 $             PCSetType(pc,PCSHELL);
504 $             PCShellSetApply(pc,mult,ctx);
505 $             PCShellSetSetUp(pc,setup);       (optional)
506 
507 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
508            KSPSHELL(), MATSHELL(), PCShellSetUp(), PCShellSetApply(), PCShellSetView(),
509            PCShellSetApplyTranpose(), PCShellSetName(), PCShellSetApplyRichardson(),
510            PCShellGetName()
511 M*/
512 
513 EXTERN_C_BEGIN
514 #undef __FUNCT__
515 #define __FUNCT__ "PCCreate_Shell"
516 int PCCreate_Shell(PC pc)
517 {
518   int      ierr;
519   PC_Shell *shell;
520 
521   PetscFunctionBegin;
522   pc->ops->destroy    = PCDestroy_Shell;
523   ierr                = PetscNew(PC_Shell,&shell);CHKERRQ(ierr);
524   PetscLogObjectMemory(pc,sizeof(PC_Shell));
525 
526   pc->data         = (void*)shell;
527   pc->name         = 0;
528 
529   pc->ops->apply           = PCApply_Shell;
530   pc->ops->view            = PCView_Shell;
531   pc->ops->applytranspose  = PCApplyTranspose_Shell;
532   pc->ops->applyrichardson = 0;
533   pc->ops->setup           = PCSetUp_Shell;
534   pc->ops->view            = PCView_Shell;
535 
536   shell->apply          = 0;
537   shell->applytranspose = 0;
538   shell->name           = 0;
539   shell->applyrich      = 0;
540   shell->ctxrich        = 0;
541   shell->ctx            = 0;
542   shell->setup          = 0;
543   shell->view           = 0;
544 
545   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetSetUp_C","PCShellSetSetUp_Shell",
546                     PCShellSetSetUp_Shell);CHKERRQ(ierr);
547   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApply_C","PCShellSetApply_Shell",
548                     PCShellSetApply_Shell);CHKERRQ(ierr);
549   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetView_C","PCShellSetView_Shell",
550                     PCShellSetView_Shell);CHKERRQ(ierr);
551   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyTranspose_C",
552                     "PCShellSetApplyTranspose_Shell",
553                     PCShellSetApplyTranspose_Shell);CHKERRQ(ierr);
554   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetName_C","PCShellSetName_Shell",
555                     PCShellSetName_Shell);CHKERRQ(ierr);
556   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellGetName_C","PCShellGetName_Shell",
557                     PCShellGetName_Shell);CHKERRQ(ierr);
558   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCShellSetApplyRichardson_C",
559                     "PCShellSetApplyRichardson_Shell",
560                     PCShellSetApplyRichardson_Shell);CHKERRQ(ierr);
561 
562   PetscFunctionReturn(0);
563 }
564 EXTERN_C_END
565 
566 
567 
568 
569 
570 
571