Actual source code: jacobi.c
1: /*$Id: jacobi.c,v 1.75 2001/08/07 03:03:32 balay Exp $*/
3: /* --------------------------------------------------------------------
5: This file implements a Jacobi preconditioner for matrices that use
6: the Mat interface (various matrix formats). Actually, the only
7: matrix operation used here is MatGetDiagonal(), which extracts
8: diagonal elements of the preconditioning matrix.
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.
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.
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().
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().
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().
45: -------------------------------------------------------------------- */
47: /*
48: Include files needed for the Jacobi preconditioner:
49: pcimpl.h - private include file intended for use by all preconditioners
50: */
52: #include src/sles/pc/pcimpl.h
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: } PC_Jacobi;
66: EXTERN_C_BEGIN
67: int PCJacobiSetUseRowMax_Jacobi(PC pc)
68: {
69: PC_Jacobi *j;
72: j = (PC_Jacobi*)pc->data;
73: j->userowmax = PETSC_TRUE;
74: return(0);
75: }
76: EXTERN_C_END
78: /* -------------------------------------------------------------------------- */
79: /*
80: PCSetUp_Jacobi - Prepares for the use of the Jacobi preconditioner
81: by setting data structures and options.
83: Input Parameter:
84: . pc - the preconditioner context
86: Application Interface Routine: PCSetUp()
88: Notes:
89: The interface routine PCSetUp() is not usually called directly by
90: the user, but instead is called by PCApply() if necessary.
91: */
92: static int PCSetUp_Jacobi(PC pc)
93: {
94: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
95: Vec diag,diagsqrt;
96: int ierr,n,i,zeroflag=0;
97: PetscScalar *x;
101: /*
102: For most preconditioners the code would begin here something like
104: if (pc->setupcalled == 0) { allocate space the first time this is ever called
105: VecDuplicate(pc->vec,&jac->diag);
106: PetscLogObjectParent(pc,jac->diag);
107: }
109: But for this preconditioner we want to support use of both the matrix' diagonal
110: elements (for left or right preconditioning) and square root of diagonal elements
111: (for symmetric preconditioning). Hence we do not allocate space here, since we
112: don't know at this point which will be needed (diag and/or diagsqrt) until the user
113: applies the preconditioner, and we don't want to allocate BOTH unless we need
114: them both. Thus, the diag and diagsqrt are allocated in PCSetUp_Jacobi_NonSymmetric()
115: and PCSetUp_Jacobi_Symmetric(), respectively.
116: */
118: /*
119: Here we set up the preconditioner; that is, we copy the diagonal values from
120: the matrix and put them into a format to make them quick to apply as a preconditioner.
121: */
122: diag = jac->diag;
123: diagsqrt = jac->diagsqrt;
125: if (diag) {
126: if (jac->userowmax) {
127: MatGetRowMax(pc->pmat,diag);
128: } else {
129: MatGetDiagonal(pc->pmat,diag);
130: }
131: VecReciprocal(diag);
132: VecGetLocalSize(diag,&n);
133: VecGetArray(diag,&x);
134: for (i=0; i<n; i++) {
135: if (x[i] == 0.0) {
136: x[i] = 1.0;
137: zeroflag = 1;
138: }
139: }
140: VecRestoreArray(diag,&x);
141: }
142: if (diagsqrt) {
143: if (jac->userowmax) {
144: MatGetRowMax(pc->pmat,diagsqrt);
145: } else {
146: MatGetDiagonal(pc->pmat,diagsqrt);
147: }
148: VecGetLocalSize(diagsqrt,&n);
149: VecGetArray(diagsqrt,&x);
150: for (i=0; i<n; i++) {
151: if (x[i] != 0.0) x[i] = 1.0/sqrt(PetscAbsScalar(x[i]));
152: else {
153: x[i] = 1.0;
154: zeroflag = 1;
155: }
156: }
157: VecRestoreArray(diagsqrt,&x);
158: }
159: if (zeroflag) {
160: PetscLogInfo(pc,"PCSetUp_Jacobi:Zero detected in diagonal of matrix, using 1 at those locationsn");
161: }
163: return(0);
164: }
165: /* -------------------------------------------------------------------------- */
166: /*
167: PCSetUp_Jacobi_Symmetric - Allocates the vector needed to store the
168: inverse of the square root of the diagonal entries of the matrix. This
169: is used for symmetric application of the Jacobi preconditioner.
171: Input Parameter:
172: . pc - the preconditioner context
173: */
174: static int PCSetUp_Jacobi_Symmetric(PC pc)
175: {
176: int ierr;
177: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
181: VecDuplicate(pc->vec,&jac->diagsqrt);
182: PetscLogObjectParent(pc,jac->diagsqrt);
183: PCSetUp_Jacobi(pc);
184: return(0);
185: }
186: /* -------------------------------------------------------------------------- */
187: /*
188: PCSetUp_Jacobi_NonSymmetric - Allocates the vector needed to store the
189: inverse of the diagonal entries of the matrix. This is used for left of
190: right application of the Jacobi preconditioner.
192: Input Parameter:
193: . pc - the preconditioner context
194: */
195: static int PCSetUp_Jacobi_NonSymmetric(PC pc)
196: {
197: int ierr;
198: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
202: VecDuplicate(pc->vec,&jac->diag);
203: PetscLogObjectParent(pc,jac->diag);
204: PCSetUp_Jacobi(pc);
205: return(0);
206: }
207: /* -------------------------------------------------------------------------- */
208: /*
209: PCApply_Jacobi - Applies the Jacobi preconditioner to a vector.
211: Input Parameters:
212: . pc - the preconditioner context
213: . x - input vector
215: Output Parameter:
216: . y - output vector
218: Application Interface Routine: PCApply()
219: */
220: static int PCApply_Jacobi(PC pc,Vec x,Vec y)
221: {
222: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
223: int ierr;
226: if (!jac->diag) {
227: PCSetUp_Jacobi_NonSymmetric(pc);
228: }
229: VecPointwiseMult(x,jac->diag,y);
230: return(0);
231: }
232: /* -------------------------------------------------------------------------- */
233: /*
234: PCApplySymmetricLeftOrRight_Jacobi - Applies the left or right part of a
235: symmetric preconditioner to a vector.
237: Input Parameters:
238: . pc - the preconditioner context
239: . x - input vector
241: Output Parameter:
242: . y - output vector
244: Application Interface Routines: PCApplySymmetricLeft(), PCApplySymmetricRight()
245: */
246: static int PCApplySymmetricLeftOrRight_Jacobi(PC pc,Vec x,Vec y)
247: {
248: int ierr;
249: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
252: if (!jac->diagsqrt) {
253: PCSetUp_Jacobi_Symmetric(pc);
254: }
255: VecPointwiseMult(x,jac->diagsqrt,y);
256: return(0);
257: }
258: /* -------------------------------------------------------------------------- */
259: /*
260: PCDestroy_Jacobi - Destroys the private context for the Jacobi preconditioner
261: that was created with PCCreate_Jacobi().
263: Input Parameter:
264: . pc - the preconditioner context
266: Application Interface Routine: PCDestroy()
267: */
268: static int PCDestroy_Jacobi(PC pc)
269: {
270: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
271: int ierr;
274: if (jac->diag) {VecDestroy(jac->diag);}
275: if (jac->diagsqrt) {VecDestroy(jac->diagsqrt);}
277: /*
278: Free the private data structure that was hanging off the PC
279: */
280: PetscFree(jac);
281: return(0);
282: }
284: static int PCSetFromOptions_Jacobi(PC pc)
285: {
286: PC_Jacobi *jac = (PC_Jacobi*)pc->data;
287: int ierr;
290: PetscOptionsHead("Jacobi options");
291: PetscOptionsLogical("-pc_jacobi_rowmax","Use row maximums for diagonal","PCJacobiSetUseRowMax",jac->userowmax,
292: &jac->userowmax,PETSC_NULL);
293: PetscOptionsTail();
294: return(0);
295: }
297: /* -------------------------------------------------------------------------- */
298: /*
299: PCCreate_Jacobi - Creates a Jacobi preconditioner context, PC_Jacobi,
300: and sets this as the private data within the generic preconditioning
301: context, PC, that was created within PCCreate().
303: Input Parameter:
304: . pc - the preconditioner context
306: Application Interface Routine: PCCreate()
307: */
308: EXTERN_C_BEGIN
309: int PCCreate_Jacobi(PC pc)
310: {
311: PC_Jacobi *jac;
312: int ierr;
316: /*
317: Creates the private data structure for this preconditioner and
318: attach it to the PC object.
319: */
320: ierr = PetscNew(PC_Jacobi,&jac);
321: pc->data = (void*)jac;
323: /*
324: Logs the memory usage; this is not needed but allows PETSc to
325: monitor how much memory is being used for various purposes.
326: */
327: PetscLogObjectMemory(pc,sizeof(PC_Jacobi));
329: /*
330: Initialize the pointers to vectors to ZERO; these will be used to store
331: diagonal entries of the matrix for fast preconditioner application.
332: */
333: jac->diag = 0;
334: jac->diagsqrt = 0;
335: jac->userowmax = PETSC_FALSE;
337: /*
338: Set the pointers for the functions that are provided above.
339: Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
340: are called, they will automatically call these functions. Note we
341: choose not to provide a couple of these functions since they are
342: not needed.
343: */
344: pc->ops->apply = PCApply_Jacobi;
345: pc->ops->applytranspose = PCApply_Jacobi;
346: pc->ops->setup = PCSetUp_Jacobi;
347: pc->ops->destroy = PCDestroy_Jacobi;
348: pc->ops->setfromoptions = PCSetFromOptions_Jacobi;
349: pc->ops->view = 0;
350: pc->ops->applyrichardson = 0;
351: pc->ops->applysymmetricleft = PCApplySymmetricLeftOrRight_Jacobi;
352: pc->ops->applysymmetricright = PCApplySymmetricLeftOrRight_Jacobi;
353: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCJacobiSetUseRowMax_C","PCJacobiSetUseRowMax_Jacobi",
354: PCJacobiSetUseRowMax_Jacobi);
355: return(0);
356: }
357: EXTERN_C_END
359: /*@
360: PCJacobiSetUseRowMax - Causes the Jacobi preconditioner to use the
361: maximum entry in each row as the diagonal preconditioner, instead of
362: the diagonal entry
364: Collective on PC
366: Input Parameters:
367: . pc - the preconditioner context
370: Options Database Key:
371: . -pc_jacobi_rowmax
373: Level: intermediate
375: Concepts: Jacobi preconditioner
377: @*/
378: int PCJacobiSetUseRowMax(PC pc)
379: {
380: int ierr,(*f)(PC);
384: PetscObjectQueryFunction((PetscObject)pc,"PCJacobiSetRowMax_C",(void (**)(void))&f);
385: if (f) {
386: (*f)(pc);
387: }
388: return(0);
389: }