Actual source code: iterativ.c

  1: /*$Id: iterativ.c,v 1.108 2001/08/07 03:03:45 balay 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/ksp/ksp/kspimpl.h

 14: /*
 15:   KSPDefaultFreeWork - Free work vectors

 17:   Input Parameters:
 18: . ksp  - iterative context
 19:  */
 20: int KSPDefaultFreeWork(KSP ksp)
 21: {
 25:   if (ksp->work)  {
 26:     VecDestroyVecs(ksp->work,ksp->nwork);
 27:     ksp->work = PETSC_NULL;
 28:   }
 29:   return(0);
 30: }

 34: /*@C
 35:    KSPGetResidualNorm - Gets the last (approximate preconditioned)
 36:    residual norm that has been computed.
 37:  
 38:    Not Collective

 40:    Input Parameters:
 41: .  ksp - the iterative context

 43:    Output Parameters:
 44: .  rnorm - residual norm

 46:    Level: intermediate

 48: .keywords: KSP, get, residual norm

 50: .seealso: KSPComputeResidual()
 51: @*/
 52: int KSPGetResidualNorm(KSP ksp,PetscReal *rnorm)
 53: {
 57:   *rnorm = ksp->rnorm;
 58:   return(0);
 59: }

 63: /*@
 64:    KSPGetIterationNumber - Gets the current iteration number; if the 
 65:          KSPSolve() is complete, returns the number of iterations
 66:          used.
 67:  
 68:    Not Collective

 70:    Input Parameters:
 71: .  ksp - the iterative context

 73:    Output Parameters:
 74: .  its - number of iterations

 76:    Level: intermediate

 78:    Notes:
 79:       During the ith iteration this returns i-1
 80: .keywords: KSP, get, residual norm

 82: .seealso: KSPComputeResidual(), KSPGetResidualNorm()
 83: @*/
 84: int KSPGetIterationNumber(KSP ksp,int *its)
 85: {
 89:   *its = ksp->its;
 90:   return(0);
 91: }

 95: /*@C
 96:     KSPSingularValueMonitor - Prints the two norm of the true residual and
 97:     estimation of the extreme singular values of the preconditioned problem
 98:     at each iteration.
 99:  
100:     Collective on KSP

102:     Input Parameters:
103: +   ksp - the iterative context
104: .   n  - the iteration
105: -   rnorm - the two norm of the residual

107:     Options Database Key:
108: .   -ksp_singmonitor - Activates KSPSingularValueMonitor()

110:     Notes:
111:     The CG solver uses the Lanczos technique for eigenvalue computation, 
112:     while GMRES uses the Arnoldi technique; other iterative methods do
113:     not currently compute singular values.

115:     Level: intermediate

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

119: .seealso: KSPComputeExtremeSingularValues()
120: @*/
121: int KSPSingularValueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
122: {
123:   PetscReal emin,emax,c;
124:   int    ierr;

128:   if (!ksp->calc_sings) {
129:     PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e \n",n,rnorm);
130:   } else {
131:     KSPComputeExtremeSingularValues(ksp,&emax,&emin);
132:     c = emax/emin;
133:     PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e %% max %g min %g max/min %g\n",n,rnorm,emax,emin,c);
134:   }
135:   return(0);
136: }

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

144:    Collective on KSP

146:    Input Parameters:
147: +  ksp - the KSP context
148: .  its - iteration number
149: .  fgnorm - 2-norm of residual (or gradient)
150: -  dummy - either a viewer or PETSC_NULL

152:    Level: intermediate

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

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

160: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), VecView()
161: @*/
162: int KSPVecViewMonitor(KSP ksp,int its,PetscReal fgnorm,void *dummy)
163: {
164:   int         ierr;
165:   Vec         x;
166:   PetscViewer viewer = (PetscViewer) dummy;

169:   KSPBuildSolution(ksp,PETSC_NULL,&x);
170:   if (!viewer) {
171:     MPI_Comm comm;
172:     PetscObjectGetComm((PetscObject)ksp,&comm);
173:     viewer = PETSC_VIEWER_DRAW_(comm);
174:   }
175:   VecView(x,viewer);

177:   return(0);
178: }

182: /*@C
183:    KSPDefaultMonitor - Print the residual norm at each iteration of an
184:    iterative solver.

186:    Collective on KSP

188:    Input Parameters:
189: +  ksp   - iterative context
190: .  n     - iteration number
191: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).  
192: -  dummy - unused monitor context 

194:    Level: intermediate

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

198: .seealso: KSPSetMonitor(), KSPTrueMonitor(), KSPLGMonitorCreate()
199: @*/
200: int KSPDefaultMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
201: {
202:   int         ierr;
203:   PetscViewer viewer = (PetscViewer) dummy;

206:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
207:   PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %14.12e \n",n,rnorm);
208:   return(0);
209: }

213: /*@C
214:    KSPTrueMonitor - Prints the true residual norm as well as the preconditioned
215:    residual norm at each iteration of an iterative solver.

217:    Collective on KSP

219:    Input Parameters:
220: +  ksp   - iterative context
221: .  n     - iteration number
222: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).  
223: -  dummy - unused monitor context 

225:    Options Database Key:
226: .  -ksp_truemonitor - Activates KSPTrueMonitor()

228:    Notes:
229:    When using right preconditioning, these values are equivalent.

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

236:    Level: intermediate

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

240: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), KSPLGMonitorCreate()
241: @*/
242: int KSPTrueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
243: {
244:   int          ierr;
245:   Vec          resid,work;
246:   PetscReal    scnorm;
247:   PC           pc;
248:   Mat          A,B;
249:   PetscViewer  viewer = (PetscViewer) dummy;
250: 
252:   VecDuplicate(ksp->vec_rhs,&work);
253:   KSPBuildResidual(ksp,0,work,&resid);

255:   /*
256:      Unscale the residual if the matrix is, for example, a BlockSolve matrix
257:     but only if both matrices are the same matrix, since only then would 
258:     they be scaled.
259:   */
260:   VecCopy(resid,work);
261:   KSPGetPC(ksp,&pc);
262:   PCGetOperators(pc,&A,&B,PETSC_NULL);
263:   if (A == B) {
264:     MatUnScaleSystem(A,PETSC_NULL,work);
265:   }
266:   VecNorm(work,NORM_2,&scnorm);
267:   VecDestroy(work);
268:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
269:   PetscViewerASCIIPrintf(viewer,"%3d KSP preconditioned resid norm %14.12e true resid norm %14.12e\n",n,rnorm,scnorm);
270:   return(0);
271: }

275: /*
276:   Default (short) KSP Monitor, same as KSPDefaultMonitor() except
277:   it prints fewer digits of the residual as the residual gets smaller.
278:   This is because the later digits are meaningless and are often 
279:   different on different machines; by using this routine different 
280:   machines will usually generate the same output.
281: */
282: int KSPDefaultSMonitor(KSP ksp,int its,PetscReal fnorm,void *dummy)
283: {
284:   int         ierr;
285:   PetscViewer viewer = (PetscViewer) dummy;

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

290:   if (fnorm > 1.e-9) {
291:     PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %g \n",its,fnorm);
292:   } else if (fnorm > 1.e-11){
293:     PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %5.3e \n",its,fnorm);
294:   } else {
295:     PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm < 1.e-11\n",its);
296:   }
297:   return(0);
298: }

302: /*@C
303:    KSPSkipConverged - Convergence test that NEVER returns as converged.

305:    Collective on KSP

307:    Input Parameters:
308: +  ksp   - iterative context
309: .  n     - iteration number
310: .  rnorm - 2-norm residual value (may be estimated)
311: -  dummy - unused convergence context 

313:    Returns:
314: .  0 - always

316:    Notes:
317:    This is used as the convergence test with the option KSPSetNormType(ksp,KSP_NO_NORM),
318:    since norms of the residual are not computed. Convergence is then declared 
319:    after a fixed number of iterations have been used. Useful when one is 
320:    using CG or Bi-CG-stab as a smoother.
321:                     
322:    Level: advanced

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

326: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
327: @*/
328: int KSPSkipConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
329: {
332:   return(0);
333: }

337: /*@C
338:    KSPDefaultConverged - Determines convergence of
339:    the iterative solvers (default code).

341:    Collective on KSP

343:    Input Parameters:
344: +  ksp   - iterative context
345: .  n     - iteration number
346: .  rnorm - 2-norm residual value (may be estimated)
347: -  dummy - unused convergence context 

349:    Returns:
350: +   1 - if the iteration has converged;
351: .  -1 - if residual norm exceeds divergence threshold;
352: -   0 - otherwise.

354:    Notes:
355:    KSPDefaultConverged() reaches convergence when
356: $      rnorm < MAX (rtol * rnorm_0, atol);
357:    Divergence is detected if
358: $      rnorm > dtol * rnorm_0,

360:    where 
361: +     rtol = relative tolerance,
362: .     atol = absolute tolerance.
363: .     dtol = divergence tolerance,
364: -     rnorm_0 = initial residual norm

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

368:    Level: intermediate

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

372: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged()
373: @*/
374: int KSPDefaultConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
375: {
379:   *reason = KSP_CONVERGED_ITERATING;

381:   if (!n) {
382:     ksp->ttol   = PetscMax(ksp->rtol*rnorm,ksp->atol);
383:     ksp->rnorm0 = rnorm;
384:   }
385:   if (rnorm <= ksp->ttol) {
386:     if (rnorm < ksp->atol) {
387:       PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g at iteration %d\n",rnorm,ksp->atol,n);
388:       *reason = KSP_CONVERGED_ATOL;
389:     } else {
390:       PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than relative tolerance %g times initial residual norm %g at iteration %d\n",rnorm,ksp->rtol,ksp->rnorm0,n);
391:       *reason = KSP_CONVERGED_RTOL;
392:     }
393:   } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
394:     PetscLogInfo(ksp,"Linear solver is diverging. Initial residual norm %g, current residual norm %g at iteration %d\n",ksp->rnorm0,rnorm,n);
395:     *reason = KSP_DIVERGED_DTOL;
396:   } else if (rnorm != rnorm) {
397:     PetscLogInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence\n");
398:     *reason = KSP_DIVERGED_DTOL;
399:   }
400:   return(0);
401: }

405: /*
406:    KSPDefaultBuildSolution - Default code to create/move the solution.

408:    Input Parameters:
409: +  ksp - iterative context
410: -  v   - pointer to the user's vector  

412:    Output Parameter:
413: .  V - pointer to a vector containing the solution

415:    Level: advanced

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

419: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
420: */
421: int KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
422: {
425:   if (ksp->pc_side == PC_RIGHT) {
426:     if (ksp->B) {
427:       if (v) {KSP_PCApply(ksp,ksp->B,ksp->vec_sol,v); *V = v;}
428:       else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
429:     } else {
430:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
431:       else { *V = ksp->vec_sol;}
432:     }
433:   } else if (ksp->pc_side == PC_SYMMETRIC) {
434:     if (ksp->B) {
435:       if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
436:       if (v) {PCApplySymmetricRight(ksp->B,ksp->vec_sol,v); *V = v;}
437:       else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
438:     } else  {
439:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
440:       else { *V = ksp->vec_sol;}
441:     }
442:   } else {
443:     if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
444:     else { *V = ksp->vec_sol; }
445:   }
446:   return(0);
447: }

451: /*
452:    KSPDefaultBuildResidual - Default code to compute the residual.

454:    Input Parameters:
455: .  ksp - iterative context
456: .  t   - pointer to temporary vector
457: .  v   - pointer to user vector  

459:    Output Parameter:
460: .  V - pointer to a vector containing the residual

462:    Level: advanced

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

466: .seealso: KSPDefaultBuildSolution()
467: */
468: int KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
469: {
470:   int          ierr;
471:   MatStructure pflag;
472:   Vec          T;
473:   PetscScalar  mone = -1.0;
474:   Mat          Amat,Pmat;

477:   PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
478:   KSPBuildSolution(ksp,t,&T);
479:   KSP_MatMult(ksp,Amat,t,v);
480:   VecAYPX(&mone,ksp->vec_rhs,v);
481:   *V = v;
482:   return(0);
483: }

487: /*
488:   KSPDefaultGetWork - Gets a number of work vectors.

490:   Input Parameters:
491: . ksp  - iterative context
492: . nw   - number of work vectors to allocate

494:   Notes:
495:   Call this only if no work vectors have been allocated 
496:  */
497: int  KSPDefaultGetWork(KSP ksp,int nw)
498: {

502:   if (ksp->work) {KSPDefaultFreeWork(ksp);}
503:   ksp->nwork = nw;
504:   VecDuplicateVecs(ksp->vec_rhs,nw,&ksp->work);
505:   PetscLogObjectParents(ksp,nw,ksp->work);
506:   return(0);
507: }

511: /*
512:   KSPDefaultDestroy - Destroys a iterative context variable for methods with
513:   no separate context.  Preferred calling sequence KSPDestroy().

515:   Input Parameter: 
516: . ksp - the iterative context
517: */
518: int KSPDefaultDestroy(KSP ksp)
519: {

524:   if (ksp->data) {
525:     PetscFree(ksp->data);
526:     ksp->data = 0;
527:   }

529:   /* free work vectors */
530:   KSPDefaultFreeWork(ksp);
531:   return(0);
532: }

536: /*@C
537:    KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.

539:    Not Collective

541:    Input Parameter:
542: .  ksp - the KSP context

544:    Output Parameter:
545: .  reason - negative value indicates diverged, positive value converged, see KSPConvergedReason

547:    Possible values for reason:
548: +  KSP_CONVERGED_RTOL (residual norm decreased by a factor of rtol)
549: .  KSP_CONVERGED_ATOL (residual norm less than atol)
550: .  KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration) 
551: .  KSP_CONVERGED_QCG_NEG_CURVE
552: .  KSP_CONVERGED_QCG_CONSTRAINED
553: .  KSP_CONVERGED_STEP_LENGTH
554: .  KSP_DIVERGED_ITS  (required more than its to reach convergence)
555: .  KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
556: .  KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
557: -  KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
558:                                 residual. Try a different preconditioner, or a different initial guess.
559:  

561:    Level: intermediate

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

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

567: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
568: @*/
569: int KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
570: {
574:   *reason = ksp->reason;
575:   return(0);
576: }