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: }