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/sles/ksp/kspimpl.h

 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 KSPSetNormType(ksp,KSP_NO_NORM),
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(), KSPSetNormType()
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) {
363:       PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g at iteration %dn",rnorm,ksp->atol,n);
364:       *reason = KSP_CONVERGED_ATOL;
365:     } else {
366:       PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than relative tolerance %g times initial residual norm %g at iteration %dn",rnorm,ksp->rtol,ksp->rnorm0,n);
367:       *reason = KSP_CONVERGED_RTOL;
368:     }
369:   } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
370:     PetscLogInfo(ksp,"Linear solver is diverging. Initial residual norm %g, current residual norm %g at iteration %dn",ksp->rnorm0,rnorm,n);
371:     *reason = KSP_DIVERGED_DTOL;
372:   } else if (rnorm != rnorm) {
373:     PetscLogInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergencen");
374:     *reason = KSP_DIVERGED_DTOL;
375:   }
376:   return(0);
377: }

379: /*
380:    KSPDefaultBuildSolution - Default code to create/move the solution.

382:    Input Parameters:
383: +  ksp - iterative context
384: -  v   - pointer to the user's vector  

386:    Output Parameter:
387: .  V - pointer to a vector containing the solution

389:    Level: advanced

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

393: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
394: */
395: int KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
396: {
399:   if (ksp->pc_side == PC_RIGHT) {
400:     if (ksp->B) {
401:       if (v) {KSP_PCApply(ksp,ksp->B,ksp->vec_sol,v); *V = v;}
402:       else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
403:     } else {
404:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
405:       else { *V = ksp->vec_sol;}
406:     }
407:   } else if (ksp->pc_side == PC_SYMMETRIC) {
408:     if (ksp->B) {
409:       if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
410:       if (v) {PCApplySymmetricRight(ksp->B,ksp->vec_sol,v); *V = v;}
411:       else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
412:     } else  {
413:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
414:       else { *V = ksp->vec_sol;}
415:     }
416:   } else {
417:     if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
418:     else { *V = ksp->vec_sol; }
419:   }
420:   return(0);
421: }

423: /*
424:    KSPDefaultBuildResidual - Default code to compute the residual.

426:    Input Parameters:
427: .  ksp - iterative context
428: .  t   - pointer to temporary vector
429: .  v   - pointer to user vector  

431:    Output Parameter:
432: .  V - pointer to a vector containing the residual

434:    Level: advanced

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

438: .seealso: KSPDefaultBuildSolution()
439: */
440: int KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
441: {
442:   int          ierr;
443:   MatStructure pflag;
444:   Vec          T;
445:   PetscScalar  mone = -1.0;
446:   Mat          Amat,Pmat;

449:   PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
450:   KSPBuildSolution(ksp,t,&T);
451:   KSP_MatMult(ksp,Amat,t,v);
452:   VecAYPX(&mone,ksp->vec_rhs,v);
453:   *V = v;
454:   return(0);
455: }

457: /*
458:   KSPDefaultGetWork - Gets a number of work vectors.

460:   Input Parameters:
461: . ksp  - iterative context
462: . nw   - number of work vectors to allocate

464:   Notes:
465:   Call this only if no work vectors have been allocated 
466:  */
467: int  KSPDefaultGetWork(KSP ksp,int nw)
468: {

472:   if (ksp->work) {KSPDefaultFreeWork(ksp);}
473:   ksp->nwork = nw;
474:   VecDuplicateVecs(ksp->vec_rhs,nw,&ksp->work);
475:   PetscLogObjectParents(ksp,nw,ksp->work);
476:   return(0);
477: }

479: /*
480:   KSPDefaultDestroy - Destroys a iterative context variable for methods with
481:   no separate context.  Preferred calling sequence KSPDestroy().

483:   Input Parameter: 
484: . ksp - the iterative context
485: */
486: int KSPDefaultDestroy(KSP ksp)
487: {

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

494:   /* free work vectors */
495:   KSPDefaultFreeWork(ksp);
496:   return(0);
497: }

499: /*@C
500:    KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.

502:    Not Collective

504:    Input Parameter:
505: .  ksp - the KSP context

507:    Output Parameter:
508: .  reason - negative value indicates diverged, positive value converged, see KSPConvergedReason

510:    Possible values for reason:
511: +  KSP_CONVERGED_RTOL (residual norm decreased by a factor of rtol)
512: .  KSP_CONVERGED_ATOL (residual norm less than atol)
513: .  KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration) 
514: .  KSP_CONVERGED_QCG_NEG_CURVE
515: .  KSP_CONVERGED_QCG_CONSTRAINED
516: .  KSP_CONVERGED_STEP_LENGTH
517: .  KSP_DIVERGED_ITS  (required more than its to reach convergence)
518: .  KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
519: .  KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
520: -  KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
521:                                 residual. Try a different preconditioner, or a different initial guess.
522:  

524:    Level: intermediate

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

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

530: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
531: @*/
532: int KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
533: {
536:   *reason = ksp->reason;
537:   return(0);
538: }