Actual source code: iterativ.c

  1: /*$Id: iterativ.c,v 1.105 2001/04/04 18:19:34 bsmith Exp $*/

  3: /*
  4:    This file contains some simple default routines.  
  5:    These routines should be SHORT, since they will be included in every
  6:    executable image that uses the iterative routines (note that, through
  7:    the registry system, we provide a way to load only the truely necessary
  8:    files) 
  9:  */
 10: #include "src/sles/ksp/kspimpl.h"   /*I "petscksp.h" I*/

 12: /*
 13:   KSPDefaultFreeWork - Free work vectors

 15:   Input Parameters:
 16: . ksp  - iterative context
 17:  */
 18: int KSPDefaultFreeWork(KSP ksp)
 19: {
 23:   if (ksp->work)  {
 24:     VecDestroyVecs(ksp->work,ksp->nwork);
 25:   }
 26:   return(0);
 27: }

 29: /*@C
 30:    KSPGetResidualNorm - Gets the last (approximate preconditioned)
 31:    residual norm that has been computed.
 32:  
 33:    Not Collective

 35:    Input Parameters:
 36: .  ksp - the iterative context

 38:    Output Parameters:
 39: .  rnorm - residual norm

 41:    Level: intermediate

 43: .keywords: KSP, get, residual norm

 45: .seealso: KSPComputeResidual()
 46: @*/
 47: int KSPGetResidualNorm(KSP ksp,PetscReal *rnorm)
 48: {
 51:   *rnorm = ksp->rnorm;
 52:   return(0);
 53: }

 55: /*@
 56:    KSPGetIterationNumber - Gets the current iteration number (if the 
 57:          KSPSolve() (SLESSolve()) is complete, returns the number of iterations
 58:          used.
 59:  
 60:    Not Collective

 62:    Input Parameters:
 63: .  ksp - the iterative context

 65:    Output Parameters:
 66: .  its - number of iterations

 68:    Level: intermediate

 70:    Notes:
 71:       During the ith iteration this returns i-1
 72: .keywords: KSP, get, residual norm

 74: .seealso: KSPComputeResidual(), KSPGetResidualNorm()
 75: @*/
 76: int KSPGetIterationNumber(KSP ksp,int *its)
 77: {
 80:   *its = ksp->its;
 81:   return(0);
 82: }

 84: /*@C
 85:     KSPSingularValueMonitor - Prints the two norm of the true residual and
 86:     estimation of the extreme singular values of the preconditioned problem
 87:     at each iteration.
 88:  
 89:     Collective on KSP

 91:     Input Parameters:
 92: +   ksp - the iterative context
 93: .   n  - the iteration
 94: -   rnorm - the two norm of the residual

 96:     Options Database Key:
 97: .   -ksp_singmonitor - Activates KSPSingularValueMonitor()

 99:     Notes:
100:     The CG solver uses the Lanczos technique for eigenvalue computation, 
101:     while GMRES uses the Arnoldi technique; other iterative methods do
102:     not currently compute singular values.

104:     Level: intermediate

106: .keywords: KSP, CG, default, monitor, extreme, singular values, Lanczos, Arnoldi

108: .seealso: KSPComputeExtremeSingularValues()
109: @*/
110: int KSPSingularValueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
111: {
112:   PetscReal emin,emax,c;
113:   int    ierr;

117:   if (!ksp->calc_sings) {
118:     PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e n",n,rnorm);
119:   } else {
120:     KSPComputeExtremeSingularValues(ksp,&emax,&emin);
121:     c = emax/emin;
122:     PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e %% max %g min %g max/min %gn",n,rnorm,emax,emin,c);
123:   }
124:   return(0);
125: }

127: /*@C
128:    KSPVecViewMonitor - Monitors progress of the KSP solvers by calling 
129:    VecView() for the approximate solution at each iteration.

131:    Collective on KSP

133:    Input Parameters:
134: +  ksp - the KSP context
135: .  its - iteration number
136: .  fgnorm - 2-norm of residual (or gradient)
137: -  dummy - either a viewer or PETSC_NULL

139:    Level: intermediate

141:    Notes:
142:     For some Krylov methods such as GMRES constructing the solution at
143:   each iteration is expensive, hence using this will slow the code.

145: .keywords: KSP, nonlinear, vector, monitor, view

147: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), VecView()
148: @*/
149: int KSPVecViewMonitor(KSP ksp,int its,PetscReal fgnorm,void *dummy)
150: {
151:   int         ierr;
152:   Vec         x;
153:   PetscViewer viewer = (PetscViewer) dummy;

156:   KSPBuildSolution(ksp,PETSC_NULL,&x);
157:   if (!viewer) {
158:     MPI_Comm comm;
159:     ierr   = PetscObjectGetComm((PetscObject)ksp,&comm);
160:     viewer = PETSC_VIEWER_DRAW_(comm);
161:   }
162:   VecView(x,viewer);

164:   return(0);
165: }

167: /*@C
168:    KSPDefaultMonitor - Print the residual norm at each iteration of an
169:    iterative solver.

171:    Collective on KSP

173:    Input Parameters:
174: +  ksp   - iterative context
175: .  n     - iteration number
176: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).  
177: -  dummy - unused monitor context 

179:    Level: intermediate

181: .keywords: KSP, default, monitor, residual

183: .seealso: KSPSetMonitor(), KSPTrueMonitor(), KSPLGMonitorCreate()
184: @*/
185: int KSPDefaultMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
186: {
187:   int         ierr;
188:   PetscViewer viewer = (PetscViewer) dummy;

191:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
192:   PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %14.12e n",n,rnorm);
193:   return(0);
194: }

196: /*@C
197:    KSPTrueMonitor - Prints the true residual norm as well as the preconditioned
198:    residual norm at each iteration of an iterative solver.

200:    Collective on KSP

202:    Input Parameters:
203: +  ksp   - iterative context
204: .  n     - iteration number
205: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).  
206: -  dummy - unused monitor context 

208:    Options Database Key:
209: .  -ksp_truemonitor - Activates KSPTrueMonitor()

211:    Notes:
212:    When using right preconditioning, these values are equivalent.

214:    When using either ICC or ILU preconditioners in BlockSolve95 
215:    (via MATMPIROWBS matrix format), then use this monitor will
216:    print both the residual norm associated with the original
217:    (unscaled) matrix.

219:    Level: intermediate

221: .keywords: KSP, default, monitor, residual

223: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), KSPLGMonitorCreate()
224: @*/
225: int KSPTrueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
226: {
227:   int          ierr;
228:   Vec          resid,work;
229:   PetscReal    scnorm;
230:   PC           pc;
231:   Mat          A,B;
232:   PetscViewer  viewer = (PetscViewer) dummy;
233: 
235:   VecDuplicate(ksp->vec_rhs,&work);
236:   KSPBuildResidual(ksp,0,work,&resid);

238:   /*
239:      Unscale the residual if the matrix is, for example, a BlockSolve matrix
240:     but only if both matrices are the same matrix, since only then would 
241:     they be scaled.
242:   */
243:   VecCopy(resid,work);
244:   KSPGetPC(ksp,&pc);
245:   PCGetOperators(pc,&A,&B,PETSC_NULL);
246:   if (A == B) {
247:     MatUnScaleSystem(A,PETSC_NULL,work);
248:   }
249:   VecNorm(work,NORM_2,&scnorm);
250:   VecDestroy(work);
251:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
252:   PetscViewerASCIIPrintf(viewer,"%3d KSP preconditioned resid norm %14.12e true resid norm %14.12en",n,rnorm,scnorm);
253:   return(0);
254: }

256: /*
257:   Default (short) KSP Monitor, same as KSPDefaultMonitor() except
258:   it prints fewer digits of the residual as the residual gets smaller.
259:   This is because the later digits are meaningless and are often 
260:   different on different machines; by using this routine different 
261:   machines will usually generate the same output.
262: */
263: int KSPDefaultSMonitor(KSP ksp,int its,PetscReal fnorm,void *dummy)
264: {
265:   int         ierr;
266:   PetscViewer viewer = (PetscViewer) dummy;

269:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);

271:   if (fnorm > 1.e-9) {
272:     PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %g n",its,fnorm);
273:   } else if (fnorm > 1.e-11){
274:     PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %5.3e n",its,fnorm);
275:   } else {
276:     PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm < 1.e-11n",its);
277:   }
278:   return(0);
279: }

281: /*@C
282:    KSPSkipConverged - Convergence test that NEVER returns as converged.

284:    Collective on KSP

286:    Input Parameters:
287: +  ksp   - iterative context
288: .  n     - iteration number
289: .  rnorm - 2-norm residual value (may be estimated)
290: -  dummy - unused convergence context 

292:    Returns:
293: .  0 - always

295:    Notes:
296:    This is used as the convergence test with the option KSPSetAvoidNorms(),
297:    since norms of the residual are not computed. Convergence is then declared 
298:    after a fixed number of iterations have been used. Useful when one is 
299:    using CG or Bi-CG-stab as a smoother.
300:                     
301:    Level: advanced

303: .keywords: KSP, default, convergence, residual

305: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetAvoidNorms()
306: @*/
307: int KSPSkipConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
308: {
311:   return(0);
312: }

314: /*@C
315:    KSPDefaultConverged - Determines convergence of
316:    the iterative solvers (default code).

318:    Collective on KSP

320:    Input Parameters:
321: +  ksp   - iterative context
322: .  n     - iteration number
323: .  rnorm - 2-norm residual value (may be estimated)
324: -  dummy - unused convergence context 

326:    Returns:
327: +   1 - if the iteration has converged;
328: .  -1 - if residual norm exceeds divergence threshold;
329: -   0 - otherwise.

331:    Notes:
332:    KSPDefaultConverged() reaches convergence when
333: $      rnorm < MAX (rtol * rnorm_0, atol);
334:    Divergence is detected if
335: $      rnorm > dtol * rnorm_0,

337:    where 
338: +     rtol = relative tolerance,
339: .     atol = absolute tolerance.
340: .     dtol = divergence tolerance,
341: -     rnorm_0 = initial residual norm

343:    Use KSPSetTolerances() to alter the defaults for rtol, atol, dtol.

345:    Level: intermediate

347: .keywords: KSP, default, convergence, residual

349: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged()
350: @*/
351: int KSPDefaultConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
352: {
355:   *reason = KSP_CONVERGED_ITERATING;

357:   if (!n) {
358:     ksp->ttol   = PetscMax(ksp->rtol*rnorm,ksp->atol);
359:     ksp->rnorm0 = rnorm;
360:   }
361:   if (rnorm <= ksp->ttol) {
362:     if (rnorm < ksp->atol) *reason = KSP_CONVERGED_ATOL;
363:     else                   *reason = KSP_CONVERGED_RTOL;
364:   } else if (rnorm >= ksp->divtol*ksp->rnorm0 || rnorm != rnorm) {
365:    *reason = KSP_DIVERGED_DTOL;
366:   }
367:   return(0);
368: }

370: /*
371:    KSPDefaultBuildSolution - Default code to create/move the solution.

373:    Input Parameters:
374: +  ksp - iterative context
375: -  v   - pointer to the user's vector  

377:    Output Parameter:
378: .  V - pointer to a vector containing the solution

380:    Level: advanced

382: .keywords:  KSP, build, solution, default

384: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
385: */
386: int KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
387: {
390:   if (ksp->pc_side == PC_RIGHT) {
391:     if (ksp->B) {
392:       if (v) {KSP_PCApply(ksp,ksp->B,ksp->vec_sol,v); *V = v;}
393:       else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
394:     } else {
395:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
396:       else { *V = ksp->vec_sol;}
397:     }
398:   } else if (ksp->pc_side == PC_SYMMETRIC) {
399:     if (ksp->B) {
400:       if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
401:       if (v) {PCApplySymmetricRight(ksp->B,ksp->vec_sol,v); *V = v;}
402:       else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
403:     } else  {
404:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
405:       else { *V = ksp->vec_sol;}
406:     }
407:   } else {
408:     if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
409:     else { *V = ksp->vec_sol; }
410:   }
411:   return(0);
412: }

414: /*
415:    KSPDefaultBuildResidual - Default code to compute the residual.

417:    Input Parameters:
418: .  ksp - iterative context
419: .  t   - pointer to temporary vector
420: .  v   - pointer to user vector  

422:    Output Parameter:
423: .  V - pointer to a vector containing the residual

425:    Level: advanced

427: .keywords:  KSP, build, residual, default

429: .seealso: KSPDefaultBuildSolution()
430: */
431: int KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
432: {
433:   int          ierr;
434:   MatStructure pflag;
435:   Vec          T;
436:   Scalar       mone = -1.0;
437:   Mat          Amat,Pmat;

440:   PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
441:   KSPBuildSolution(ksp,t,&T);
442:   KSP_MatMult(ksp,Amat,t,v);
443:   VecAYPX(&mone,ksp->vec_rhs,v);
444:   *V = v;
445:   return(0);
446: }

448: /*
449:   KSPDefaultGetWork - Gets a number of work vectors.

451:   Input Parameters:
452: . ksp  - iterative context
453: . nw   - number of work vectors to allocate

455:   Notes:
456:   Call this only if no work vectors have been allocated 
457:  */
458: int  KSPDefaultGetWork(KSP ksp,int nw)
459: {

463:   if (ksp->work) {KSPDefaultFreeWork(ksp);}
464:   ksp->nwork = nw;
465:   VecDuplicateVecs(ksp->vec_rhs,nw,&ksp->work);
466:   PetscLogObjectParents(ksp,nw,ksp->work);
467:   return(0);
468: }

470: /*
471:   KSPDefaultDestroy - Destroys a iterative context variable for methods with
472:   no separate context.  Preferred calling sequence KSPDestroy().

474:   Input Parameter: 
475: . ksp - the iterative context
476: */
477: int KSPDefaultDestroy(KSP ksp)
478: {

483:   if (ksp->data) {PetscFree(ksp->data);}

485:   /* free work vectors */
486:   KSPDefaultFreeWork(ksp);
487:   return(0);
488: }

490: /*@C
491:    KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.

493:    Not Collective

495:    Input Parameter:
496: .  ksp - the KSP context

498:    Output Parameter:
499: .  reason - negative value indicates diverged, positive value converged, see KSPConvergedReason

501:    Possible values for reason:
502: +  KSP_CONVERGED_RTOL (residual norm decreased by a factor of rtol)
503: .  KSP_CONVERGED_ATOL (residual norm less than atol)
504: .  KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration) 
505: .  KSP_CONVERGED_QCG_NEG_CURVE
506: .  KSP_CONVERGED_QCG_CONSTRAINED
507: .  KSP_CONVERGED_STEP_LENGTH
508: .  KSP_DIVERGED_ITS  (required more than its to reach convergence)
509: .  KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
510: .  KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
511: -  KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
512:                                 residual. Try a different preconditioner, or a different initial guess.
513:  

515:    Level: intermediate

517:    Notes: Can only be called after the call the KSPSolve() is complete.

519: .keywords: KSP, nonlinear, set, convergence, test

521: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
522: @*/
523: int KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
524: {
527:   *reason = ksp->reason;
528:   return(0);
529: }