xref: /petsc/src/ksp/pc/impls/shell/shellpc.c (revision 63dd3a1af947c5d07342e150a17d503f381a847e)
1 #define PETSCKSP_DLL
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 "vecimpl.h"
10 
11 EXTERN_C_BEGIN
12 typedef struct {
13   void           *ctx,*ctxrich;    /* user provided contexts for preconditioner */
14   PetscErrorCode (*setup)(void*);
15   PetscErrorCode (*apply)(void*,Vec,Vec);
16   PetscErrorCode (*view)(void*,PetscViewer);
17   PetscErrorCode (*applytranspose)(void*,Vec,Vec);
18   PetscErrorCode (*applyrich)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt);
19   char           *name;
20 } PC_Shell;
21 EXTERN_C_END
22 
23 #undef __FUNCT__
24 #define __FUNCT__ "PCApply_SetUp"
25 static PetscErrorCode PCSetUp_Shell(PC pc)
26 {
27   PC_Shell       *shell;
28   PetscErrorCode 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 PetscErrorCode PCApply_Shell(PC pc,Vec x,Vec y)
41 {
42   PC_Shell       *shell;
43   PetscErrorCode ierr;
44 
45   PetscFunctionBegin;
46   shell = (PC_Shell*)pc->data;
47   if (!shell->apply) SETERRQ(PETSC_ERR_USER,"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 PetscErrorCode PCApplyTranspose_Shell(PC pc,Vec x,Vec y)
55 {
56   PC_Shell       *shell;
57   PetscErrorCode ierr;
58 
59   PetscFunctionBegin;
60   shell = (PC_Shell*)pc->data;
61   if (!shell->applytranspose) SETERRQ(PETSC_ERR_USER,"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 PetscErrorCode PCApplyRichardson_Shell(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt it)
69 {
70   PetscErrorCode ierr;
71   PC_Shell       *shell;
72 
73   PetscFunctionBegin;
74   shell = (PC_Shell*)pc->data;
75   ierr  = (*shell->applyrich)(shell->ctxrich,x,y,w,rtol,abstol,dtol,it);CHKERRQ(ierr);
76   PetscFunctionReturn(0);
77 }
78 
79 #undef __FUNCT__
80 #define __FUNCT__ "PCDestroy_Shell"
81 static PetscErrorCode PCDestroy_Shell(PC pc)
82 {
83   PC_Shell       *shell = (PC_Shell*)pc->data;
84   PetscErrorCode 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 PetscErrorCode PCView_Shell(PC pc,PetscViewer viewer)
95 {
96   PC_Shell       *shell = (PC_Shell*)pc->data;
97   PetscErrorCode ierr;
98   PetscTruth     iascii;
99 
100   PetscFunctionBegin;
101   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
102   if (iascii) {
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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply_Shell(PC pc,PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView_Shell(PC pc,PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose_Shell(PC pc,PetscErrorCode (*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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName_Shell(PC pc,const char name[])
176 {
177   PC_Shell       *shell;
178   PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson_Shell(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt),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    PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetSetUp(PC pc,PetscErrorCode (*setup)(void*))
245 {
246   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(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    PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetView(PC pc,PetscErrorCode (*view)(void*,PetscViewer))
284 {
285   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(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    PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApply(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec),void *ptr)
324 {
325   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(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    PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyTranspose(PC pc,PetscErrorCode (*applytranspose)(void*,Vec,Vec))
366 {
367   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetName(PC pc,const char name[])
397 {
398   PetscErrorCode 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellGetName(PC pc,char *name[])
430 {
431   PetscErrorCode 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(PETSC_ERR_ARG_WRONG,"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    PetscErrorCode apply (void *ptr,Vec b,Vec x,Vec r,PetscReal rtol,PetscReal abstol,PetscReal dtol,PetscInt 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 .  abstol - 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 PetscErrorCode PETSCKSP_DLLEXPORT PCShellSetApplyRichardson(PC pc,PetscErrorCode (*apply)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt),void *ptr)
479 {
480   PetscErrorCode ierr,(*f)(PC,PetscErrorCode (*)(void*,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,PetscInt),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 $             PetscErrorCode (*mult)(void*,Vec,Vec);
501 $             PetscErrorCode (*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            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 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Shell(PC pc)
517 {
518   PetscErrorCode ierr;
519   PC_Shell       *shell;
520 
521   PetscFunctionBegin;
522   pc->ops->destroy    = PCDestroy_Shell;
523   ierr                = PetscNew(PC_Shell,&shell);CHKERRQ(ierr);
524   ierr = PetscLogObjectMemory(pc,sizeof(PC_Shell));CHKERRQ(ierr);
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