xref: /petsc/src/ksp/pc/impls/jacobi/jacobi.c (revision e5bd52469b00a8f2942d86b46a52285e84b32048)
1 #define PETSCKSP_DLL
2 
3 /*  --------------------------------------------------------------------
4 
5      This file implements a Jacobi preconditioner in PETSc as part of PC.
6      You can use this as a starting point for implementing your own
7      preconditioner that is not provided with PETSc. (You might also consider
8      just using PCSHELL)
9 
10      The following basic routines are required for each preconditioner.
11           PCCreate_XXX()          - Creates a preconditioner context
12           PCSetFromOptions_XXX()  - Sets runtime options
13           PCApply_XXX()           - Applies the preconditioner
14           PCDestroy_XXX()         - Destroys the preconditioner context
15      where the suffix "_XXX" denotes a particular implementation, in
16      this case we use _Jacobi (e.g., PCCreate_Jacobi, PCApply_Jacobi).
17      These routines are actually called via the common user interface
18      routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(),
19      so the application code interface remains identical for all
20      preconditioners.
21 
22      Another key routine is:
23           PCSetUp_XXX()           - Prepares for the use of a preconditioner
24      by setting data structures and options.   The interface routine PCSetUp()
25      is not usually called directly by the user, but instead is called by
26      PCApply() if necessary.
27 
28      Additional basic routines are:
29           PCView_XXX()            - Prints details of runtime options that
30                                     have actually been used.
31      These are called by application codes via the interface routines
32      PCView().
33 
34      The various types of solvers (preconditioners, Krylov subspace methods,
35      nonlinear solvers, timesteppers) are all organized similarly, so the
36      above description applies to these categories also.  One exception is
37      that the analogues of PCApply() for these components are KSPSolve(),
38      SNESSolve(), and TSSolve().
39 
40      Additional optional functionality unique to preconditioners is left and
41      right symmetric preconditioner application via PCApplySymmetricLeft()
42      and PCApplySymmetricRight().  The Jacobi implementation is
43      PCApplySymmetricLeftOrRight_Jacobi().
44 
45     -------------------------------------------------------------------- */
46 
47 /*
48    Include files needed for the Jacobi preconditioner:
49      pcimpl.h - private include file intended for use by all preconditioners
50 */
51 
52 #include "private/pcimpl.h"   /*I "petscpc.h" I*/
53 
54 /*
55    Private context (data structure) for the Jacobi preconditioner.
56 */
57 typedef struct {
58   Vec        diag;               /* vector containing the reciprocals of the diagonal elements
59                                     of the preconditioner matrix */
60   Vec        diagsqrt;           /* vector containing the reciprocals of the square roots of
61                                     the diagonal elements of the preconditioner matrix (used
62                                     only for symmetric preconditioner application) */
63   PetscTruth userowmax;
64   PetscTruth userowsum;
65   PetscTruth useabs;             /* use the absolute values of the diagonal entries */
66 } PC_Jacobi;
67 
68 EXTERN_C_BEGIN
69 #undef __FUNCT__
70 #define __FUNCT__ "PCJacobiSetUseRowMax_Jacobi"
71 PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseRowMax_Jacobi(PC pc)
72 {
73   PC_Jacobi *j;
74 
75   PetscFunctionBegin;
76   j            = (PC_Jacobi*)pc->data;
77   j->userowmax = PETSC_TRUE;
78   PetscFunctionReturn(0);
79 }
80 EXTERN_C_END
81 
82 EXTERN_C_BEGIN
83 #undef __FUNCT__
84 #define __FUNCT__ "PCJacobiSetUseRowSum_Jacobi"
85 PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseRowSum_Jacobi(PC pc)
86 {
87   PC_Jacobi *j;
88 
89   PetscFunctionBegin;
90   j            = (PC_Jacobi*)pc->data;
91   j->userowsum = PETSC_TRUE;
92   PetscFunctionReturn(0);
93 }
94 EXTERN_C_END
95 
96 EXTERN_C_BEGIN
97 #undef __FUNCT__
98 #define __FUNCT__ "PCJacobiSetUseAbs_Jacobi"
99 PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseAbs_Jacobi(PC pc)
100 {
101   PC_Jacobi *j;
102 
103   PetscFunctionBegin;
104   j         = (PC_Jacobi*)pc->data;
105   j->useabs = PETSC_TRUE;
106   PetscFunctionReturn(0);
107 }
108 EXTERN_C_END
109 
110 /* -------------------------------------------------------------------------- */
111 /*
112    PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner
113                     by setting data structures and options.
114 
115    Input Parameter:
116 .  pc - the preconditioner context
117 
118    Application Interface Routine: PCSetUp()
119 
120    Notes:
121    The interface routine PCSetUp() is not usually called directly by
122    the user, but instead is called by PCApply() if necessary.
123 */
124 #undef __FUNCT__
125 #define __FUNCT__ "PCSetUp_Jacobi"
126 static PetscErrorCode PCSetUp_Jacobi(PC pc)
127 {
128   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
129   Vec            diag,diagsqrt;
130   PetscErrorCode ierr;
131   PetscInt       n,i;
132   PetscScalar    *x;
133   PetscTruth     zeroflag = PETSC_FALSE;
134 
135   PetscFunctionBegin;
136   /*
137        For most preconditioners the code would begin here something like
138 
139   if (pc->setupcalled == 0) { allocate space the first time this is ever called
140     ierr = MatGetVecs(pc->mat,&jac->diag);CHKERRQ(ierr);
141     PetscLogObjectParent(pc,jac->diag);
142   }
143 
144     But for this preconditioner we want to support use of both the matrix' diagonal
145     elements (for left or right preconditioning) and square root of diagonal elements
146     (for symmetric preconditioning).  Hence we do not allocate space here, since we
147     don't know at this point which will be needed (diag and/or diagsqrt) until the user
148     applies the preconditioner, and we don't want to allocate BOTH unless we need
149     them both.  Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric()
150     and PCSetUp_Jacobi_Symmetric(), respectively.
151   */
152 
153   /*
154     Here we set up the preconditioner; that is, we copy the diagonal values from
155     the matrix and put them into a format to make them quick to apply as a preconditioner.
156   */
157   diag     = jac->diag;
158   diagsqrt = jac->diagsqrt;
159 
160   if (diag) {
161     if (jac->userowmax) {
162       ierr = MatGetRowMaxAbs(pc->pmat,diag,PETSC_NULL);CHKERRQ(ierr);
163     } else if (jac->userowsum) {
164       ierr = MatGetRowSum(pc->pmat,diag);CHKERRQ(ierr);
165     } else {
166       ierr = MatGetDiagonal(pc->pmat,diag);CHKERRQ(ierr);
167     }
168     ierr = VecReciprocal(diag);CHKERRQ(ierr);
169     ierr = VecGetLocalSize(diag,&n);CHKERRQ(ierr);
170     ierr = VecGetArray(diag,&x);CHKERRQ(ierr);
171     if (jac->useabs) {
172       for (i=0; i<n; i++) {
173         x[i]     = PetscAbsScalar(x[i]);
174       }
175     }
176     for (i=0; i<n; i++) {
177       if (x[i] == 0.0) {
178         x[i]     = 1.0;
179         zeroflag = PETSC_TRUE;
180       }
181     }
182     ierr = VecRestoreArray(diag,&x);CHKERRQ(ierr);
183   }
184   if (diagsqrt) {
185     if (jac->userowmax) {
186       ierr = MatGetRowMaxAbs(pc->pmat,diagsqrt,PETSC_NULL);CHKERRQ(ierr);
187     } else if (jac->userowsum) {
188       ierr = MatGetRowSum(pc->pmat,diagsqrt);CHKERRQ(ierr);
189     } else {
190       ierr = MatGetDiagonal(pc->pmat,diagsqrt);CHKERRQ(ierr);
191     }
192     ierr = VecGetLocalSize(diagsqrt,&n);CHKERRQ(ierr);
193     ierr = VecGetArray(diagsqrt,&x);CHKERRQ(ierr);
194     for (i=0; i<n; i++) {
195       if (x[i] != 0.0) x[i] = 1.0/sqrt(PetscAbsScalar(x[i]));
196       else {
197         x[i]     = 1.0;
198         zeroflag = PETSC_TRUE;
199       }
200     }
201     ierr = VecRestoreArray(diagsqrt,&x);CHKERRQ(ierr);
202   }
203   if (zeroflag) {
204     ierr = PetscInfo(pc,"Zero detected in diagonal of matrix, using 1 at those locations\n");CHKERRQ(ierr);
205   }
206   PetscFunctionReturn(0);
207 }
208 /* -------------------------------------------------------------------------- */
209 /*
210    PCSetUp_Jacobi_Symmetric - Allocates the vector needed to store the
211    inverse of the square root of the diagonal entries of the matrix.  This
212    is used for symmetric application of the Jacobi preconditioner.
213 
214    Input Parameter:
215 .  pc - the preconditioner context
216 */
217 #undef __FUNCT__
218 #define __FUNCT__ "PCSetUp_Jacobi_Symmetric"
219 static PetscErrorCode PCSetUp_Jacobi_Symmetric(PC pc)
220 {
221   PetscErrorCode ierr;
222   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
223 
224   PetscFunctionBegin;
225   ierr = MatGetVecs(pc->pmat,&jac->diagsqrt,0);CHKERRQ(ierr);
226   ierr = PetscLogObjectParent(pc,jac->diagsqrt);CHKERRQ(ierr);
227   ierr = PCSetUp_Jacobi(pc);CHKERRQ(ierr);
228   PetscFunctionReturn(0);
229 }
230 /* -------------------------------------------------------------------------- */
231 /*
232    PCSetUp_Jacobi_NonSymmetric - Allocates the vector needed to store the
233    inverse of the diagonal entries of the matrix.  This is used for left of
234    right application of the Jacobi preconditioner.
235 
236    Input Parameter:
237 .  pc - the preconditioner context
238 */
239 #undef __FUNCT__
240 #define __FUNCT__ "PCSetUp_Jacobi_NonSymmetric"
241 static PetscErrorCode PCSetUp_Jacobi_NonSymmetric(PC pc)
242 {
243   PetscErrorCode ierr;
244   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
245 
246   PetscFunctionBegin;
247   ierr = MatGetVecs(pc->pmat,&jac->diag,0);CHKERRQ(ierr);
248   ierr = PetscLogObjectParent(pc,jac->diag);CHKERRQ(ierr);
249   ierr = PCSetUp_Jacobi(pc);CHKERRQ(ierr);
250   PetscFunctionReturn(0);
251 }
252 /* -------------------------------------------------------------------------- */
253 /*
254    PCApply_Jacobi - Applies the Jacobi preconditioner to a vector.
255 
256    Input Parameters:
257 .  pc - the preconditioner context
258 .  x - input vector
259 
260    Output Parameter:
261 .  y - output vector
262 
263    Application Interface Routine: PCApply()
264  */
265 #undef __FUNCT__
266 #define __FUNCT__ "PCApply_Jacobi"
267 static PetscErrorCode PCApply_Jacobi(PC pc,Vec x,Vec y)
268 {
269   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
270   PetscErrorCode ierr;
271 
272   PetscFunctionBegin;
273   if (!jac->diag) {
274     ierr = PCSetUp_Jacobi_NonSymmetric(pc);CHKERRQ(ierr);
275   }
276   ierr = VecPointwiseMult(y,x,jac->diag);CHKERRQ(ierr);
277   PetscFunctionReturn(0);
278 }
279 /* -------------------------------------------------------------------------- */
280 /*
281    PCApplySymmetricLeftOrRight_Jacobi - Applies the left or right part of a
282    symmetric preconditioner to a vector.
283 
284    Input Parameters:
285 .  pc - the preconditioner context
286 .  x - input vector
287 
288    Output Parameter:
289 .  y - output vector
290 
291    Application Interface Routines: PCApplySymmetricLeft(), PCApplySymmetricRight()
292 */
293 #undef __FUNCT__
294 #define __FUNCT__ "PCApplySymmetricLeftOrRight_Jacobi"
295 static PetscErrorCode PCApplySymmetricLeftOrRight_Jacobi(PC pc,Vec x,Vec y)
296 {
297   PetscErrorCode ierr;
298   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
299 
300   PetscFunctionBegin;
301   if (!jac->diagsqrt) {
302     ierr = PCSetUp_Jacobi_Symmetric(pc);CHKERRQ(ierr);
303   }
304   VecPointwiseMult(y,x,jac->diagsqrt);
305   PetscFunctionReturn(0);
306 }
307 /* -------------------------------------------------------------------------- */
308 /*
309    PCDestroy_Jacobi - Destroys the private context for the Jacobi preconditioner
310    that was created with PCCreate_Jacobi().
311 
312    Input Parameter:
313 .  pc - the preconditioner context
314 
315    Application Interface Routine: PCDestroy()
316 */
317 #undef __FUNCT__
318 #define __FUNCT__ "PCDestroy_Jacobi"
319 static PetscErrorCode PCDestroy_Jacobi(PC pc)
320 {
321   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
322   PetscErrorCode ierr;
323 
324   PetscFunctionBegin;
325   if (jac->diag)     {ierr = VecDestroy(jac->diag);CHKERRQ(ierr);}
326   if (jac->diagsqrt) {ierr = VecDestroy(jac->diagsqrt);CHKERRQ(ierr);}
327 
328   /*
329       Free the private data structure that was hanging off the PC
330   */
331   ierr = PetscFree(jac);CHKERRQ(ierr);
332   PetscFunctionReturn(0);
333 }
334 
335 #undef __FUNCT__
336 #define __FUNCT__ "PCSetFromOptions_Jacobi"
337 static PetscErrorCode PCSetFromOptions_Jacobi(PC pc)
338 {
339   PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
340   PetscErrorCode ierr;
341 
342   PetscFunctionBegin;
343   ierr = PetscOptionsHead("Jacobi options");CHKERRQ(ierr);
344     ierr = PetscOptionsTruth("-pc_jacobi_rowmax","Use row maximums for diagonal","PCJacobiSetUseRowMax",jac->userowmax,
345                           &jac->userowmax,PETSC_NULL);CHKERRQ(ierr);
346     ierr = PetscOptionsTruth("-pc_jacobi_rowsum","Use row sums for diagonal","PCJacobiSetUseRowSum",jac->userowsum,
347                           &jac->userowsum,PETSC_NULL);CHKERRQ(ierr);
348     ierr = PetscOptionsTruth("-pc_jacobi_abs","Use absolute values of diagaonal entries","PCJacobiSetUseAbs",jac->useabs,
349                           &jac->useabs,PETSC_NULL);CHKERRQ(ierr);
350   ierr = PetscOptionsTail();CHKERRQ(ierr);
351   PetscFunctionReturn(0);
352 }
353 
354 /* -------------------------------------------------------------------------- */
355 /*
356    PCCreate_Jacobi - Creates a Jacobi preconditioner context, PC_Jacobi,
357    and sets this as the private data within the generic preconditioning
358    context, PC, that was created within PCCreate().
359 
360    Input Parameter:
361 .  pc - the preconditioner context
362 
363    Application Interface Routine: PCCreate()
364 */
365 
366 /*MC
367      PCJACOBI - Jacobi (i.e. diagonal scaling preconditioning)
368 
369    Options Database Key:
370 +    -pc_jacobi_rowmax - use the maximum absolute value in each row as the scaling factor,
371                         rather than the diagonal
372 .    -pc_jacobi_rowsum - use the maximum absolute value in each row as the scaling factor,
373                         rather than the diagonal
374 -    -pc_jacobi_abs - use the absolute value of the diagaonl entry
375 
376    Level: beginner
377 
378   Concepts: Jacobi, diagonal scaling, preconditioners
379 
380   Notes: By using KSPSetPreconditionerSide(ksp,PC_SYMMETRIC) or -ksp_symmetric_pc you
381          can scale each side of the matrix by the squareroot of the diagonal entries.
382 
383          Zero entries along the diagonal are replaced with the value 1.0
384 
385 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
386            PCJacobiSetUseRowMax(), PCJacobiSetUseRowSum(), PCJacobiSetUseAbs()
387 M*/
388 
389 EXTERN_C_BEGIN
390 #undef __FUNCT__
391 #define __FUNCT__ "PCCreate_Jacobi"
392 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Jacobi(PC pc)
393 {
394   PC_Jacobi      *jac;
395   PetscErrorCode ierr;
396 
397   PetscFunctionBegin;
398   /*
399      Creates the private data structure for this preconditioner and
400      attach it to the PC object.
401   */
402   ierr      = PetscNew(PC_Jacobi,&jac);CHKERRQ(ierr);
403   pc->data  = (void*)jac;
404 
405   /*
406      Logs the memory usage; this is not needed but allows PETSc to
407      monitor how much memory is being used for various purposes.
408   */
409   ierr = PetscLogObjectMemory(pc,sizeof(PC_Jacobi));CHKERRQ(ierr);
410 
411   /*
412      Initialize the pointers to vectors to ZERO; these will be used to store
413      diagonal entries of the matrix for fast preconditioner application.
414   */
415   jac->diag          = 0;
416   jac->diagsqrt      = 0;
417   jac->userowmax     = PETSC_FALSE;
418   jac->userowsum     = PETSC_FALSE;
419   jac->useabs        = PETSC_FALSE;
420 
421   /*
422       Set the pointers for the functions that are provided above.
423       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
424       are called, they will automatically call these functions.  Note we
425       choose not to provide a couple of these functions since they are
426       not needed.
427   */
428   pc->ops->apply               = PCApply_Jacobi;
429   pc->ops->applytranspose      = PCApply_Jacobi;
430   pc->ops->setup               = PCSetUp_Jacobi;
431   pc->ops->destroy             = PCDestroy_Jacobi;
432   pc->ops->setfromoptions      = PCSetFromOptions_Jacobi;
433   pc->ops->view                = 0;
434   pc->ops->applyrichardson     = 0;
435   pc->ops->applysymmetricleft  = PCApplySymmetricLeftOrRight_Jacobi;
436   pc->ops->applysymmetricright = PCApplySymmetricLeftOrRight_Jacobi;
437   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCJacobiSetUseRowMax_C","PCJacobiSetUseRowMax_Jacobi",PCJacobiSetUseRowMax_Jacobi);CHKERRQ(ierr);
438   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCJacobiSetUseRowSum_C","PCJacobiSetUseRowSum_Jacobi",PCJacobiSetUseRowSum_Jacobi);CHKERRQ(ierr);
439   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCJacobiSetUseAbs_C","PCJacobiSetUseAbs_Jacobi",PCJacobiSetUseAbs_Jacobi);CHKERRQ(ierr);
440   PetscFunctionReturn(0);
441 }
442 EXTERN_C_END
443 
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "PCJacobiSetUseAbs"
447 /*@
448    PCJacobiSetUseAbs - Causes the Jacobi preconditioner to use the
449       absolute value of the diagonal to for the preconditioner
450 
451    Collective on PC
452 
453    Input Parameters:
454 .  pc - the preconditioner context
455 
456 
457    Options Database Key:
458 .  -pc_jacobi_abs
459 
460    Level: intermediate
461 
462    Concepts: Jacobi preconditioner
463 
464 .seealso: PCJacobiaUseRowMax(), PCJacobiaUseRowSum()
465 
466 @*/
467 PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseAbs(PC pc)
468 {
469   PetscErrorCode ierr,(*f)(PC);
470 
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
473   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCJacobiSetUseAbs_C",(void (**)(void))&f);CHKERRQ(ierr);
474   if (f) {
475     ierr = (*f)(pc);CHKERRQ(ierr);
476   }
477   PetscFunctionReturn(0);
478 }
479 
480 #undef __FUNCT__
481 #define __FUNCT__ "PCJacobiSetUseRowMax"
482 /*@
483    PCJacobiSetUseRowMax - Causes the Jacobi preconditioner to use the
484       maximum entry in each row as the diagonal preconditioner, instead of
485       the diagonal entry
486 
487    Collective on PC
488 
489    Input Parameters:
490 .  pc - the preconditioner context
491 
492 
493    Options Database Key:
494 .  -pc_jacobi_rowmax
495 
496    Level: intermediate
497 
498    Concepts: Jacobi preconditioner
499 
500 .seealso: PCJacobiaUseAbs()
501 @*/
502 PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseRowMax(PC pc)
503 {
504   PetscErrorCode ierr,(*f)(PC);
505 
506   PetscFunctionBegin;
507   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
508   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCJacobiSetUseRowMax_C",(void (**)(void))&f);CHKERRQ(ierr);
509   if (f) {
510     ierr = (*f)(pc);CHKERRQ(ierr);
511   }
512   PetscFunctionReturn(0);
513 }
514 
515 #undef __FUNCT__
516 #define __FUNCT__ "PCJacobiSetUseRowSum"
517 /*@
518    PCJacobiSetUseRowSum - Causes the Jacobi preconditioner to use the
519       sum of each row as the diagonal preconditioner, instead of
520       the diagonal entry
521 
522    Collective on PC
523 
524    Input Parameters:
525 .  pc - the preconditioner context
526 
527 
528    Options Database Key:
529 .  -pc_jacobi_rowsum
530 
531    Level: intermediate
532 
533    Concepts: Jacobi preconditioner
534 
535 .seealso: PCJacobiaUseAbs(), PCJacobiaUseRowSum()
536 @*/
537 PetscErrorCode PETSCKSP_DLLEXPORT PCJacobiSetUseRowSum(PC pc)
538 {
539   PetscErrorCode ierr,(*f)(PC);
540 
541   PetscFunctionBegin;
542   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
543   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCJacobiSetUseRowSum_C",(void (**)(void))&f);CHKERRQ(ierr);
544   if (f) {
545     ierr = (*f)(pc);CHKERRQ(ierr);
546   }
547   PetscFunctionReturn(0);
548 }
549 
550