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