Actual source code: iterativ.c

  1: #define PETSCKSP_DLL

  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: PetscErrorCode 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: KSPBuildResidual()
 51: @*/
 52: PetscErrorCode PETSCKSP_DLLEXPORT 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: KSPBuildResidual(), KSPGetResidualNorm()
 83: @*/
 84: PetscErrorCode PETSCKSP_DLLEXPORT KSPGetIterationNumber(KSP ksp,PetscInt *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: PetscErrorCode PETSCKSP_DLLEXPORT KSPSingularValueMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
122: {
123:   PetscReal emin,emax,c;

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: PetscErrorCode PETSCKSP_DLLEXPORT KSPVecViewMonitor(KSP ksp,PetscInt its,PetscReal fgnorm,void *dummy)
163: {
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: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
201: {
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: PetscErrorCode PETSCKSP_DLLEXPORT KSPTrueMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
243: {
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: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultSMonitor(KSP ksp,PetscInt its,PetscReal fnorm,void *dummy)
283: {
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: .  reason - always KSP_CONVERGED_ITERATING

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: PetscErrorCode PETSCKSP_DLLEXPORT KSPSkipConverged(KSP ksp,PetscInt 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: +   positive - if the iteration has converged;
351: .   negative - if residual norm exceeds divergence threshold;
352: -   0 - otherwise.

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

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

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

368:    The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
369:    are defined in petscksp.h.

371:    Level: intermediate

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

375: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged(), KSPConvergedReason, KSPGetConvergedReason()
376: @*/
377: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
378: {

384:   *reason = KSP_CONVERGED_ITERATING;

386:   if (!n) {
387:     /* if user gives initial guess need to compute norm of b */
388:     if (!ksp->guess_zero) {
389:       PetscReal      snorm;
390:       if (ksp->normtype == KSP_UNPRECONDITIONED_NORM || ksp->pc_side == PC_RIGHT) {
391:         PetscLogInfo((ksp,"KSPDefaultConverged:user has provided nonzero initial guess, computing 2-norm of RHS\n"));
392:         VecNorm(ksp->vec_rhs,NORM_2,&snorm);        /*     <- b'*b */
393:       } else {
394:         Vec z;
395:         VecDuplicate(ksp->vec_rhs,&z);
396:         KSP_PCApply(ksp,ksp->vec_rhs,z);
397:         if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
398:           PetscLogInfo((ksp,"KSPDefaultConverged:user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n"));
399:           VecNorm(z,NORM_2,&snorm);                 /*    dp <- b'*B'*B*b */
400:         } else if (ksp->normtype == KSP_NATURAL_NORM) {
401:           PetscScalar norm;
402:           PetscLogInfo((ksp,"KSPDefaultConverged:user has provided nonzero initial guess, computing natural norm of RHS\n"));
403:           VecDot(ksp->vec_rhs,z,&norm);
404:           snorm = sqrt(PetscAbsScalar(norm));                            /*    dp <- b'*B*b */
405:         }
406:         VecDestroy(z);
407:       }
408:       /* handle special case of zero RHS and nonzero guess */
409:       if (!snorm) {
410:         PetscLogInfo((ksp,"KSPDefaultConverged:Special case, user has provided nonzero initial guess and zero RHS\n"));
411:         snorm = rnorm;
412:       }
413:       ksp->ttol   = PetscMax(ksp->rtol*snorm,ksp->abstol);
414:       ksp->rnorm0 = snorm;
415:     } else {
416:       ksp->ttol   = PetscMax(ksp->rtol*rnorm,ksp->abstol);
417:       ksp->rnorm0 = rnorm;
418:     }
419:   }

421:   if (rnorm != rnorm) {
422:     PetscLogInfo((ksp,"KSPDefaultConverged:Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n"));
423:     *reason = KSP_DIVERGED_NAN;
424:   } else if (rnorm <= ksp->ttol) {
425:     if (rnorm < ksp->abstol) {
426:       PetscLogInfo((ksp,"KSPDefaultConverged:Linear solver has converged. Residual norm %g is less than absolute tolerance %g at iteration %D\n",rnorm,ksp->abstol,n));
427:       *reason = KSP_CONVERGED_ATOL;
428:     } else {
429:       PetscLogInfo((ksp,"KSPDefaultConverged:Linear solver has converged. Residual norm %g is less than relative tolerance %g times initial right hand side norm %g at iteration %D\n",rnorm,ksp->rtol,ksp->rnorm0,n));
430:       *reason = KSP_CONVERGED_RTOL;
431:     }
432:   } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
433:     PetscLogInfo((ksp,"KSPDefaultConverged:Linear solver is diverging. Initial right hand size norm %g, current residual norm %g at iteration %D\n",ksp->rnorm0,rnorm,n));
434:     *reason = KSP_DIVERGED_DTOL;
435:   }
436:   return(0);
437: }

441: /*
442:    KSPDefaultBuildSolution - Default code to create/move the solution.

444:    Input Parameters:
445: +  ksp - iterative context
446: -  v   - pointer to the user's vector  

448:    Output Parameter:
449: .  V - pointer to a vector containing the solution

451:    Level: advanced

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

455: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
456: */
457: PetscErrorCode KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
458: {
461:   if (ksp->pc_side == PC_RIGHT) {
462:     if (ksp->pc) {
463:       if (v) {KSP_PCApply(ksp,ksp->vec_sol,v); *V = v;}
464:       else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
465:     } else {
466:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
467:       else { *V = ksp->vec_sol;}
468:     }
469:   } else if (ksp->pc_side == PC_SYMMETRIC) {
470:     if (ksp->pc) {
471:       if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
472:       if (v) {PCApplySymmetricRight(ksp->pc,ksp->vec_sol,v); *V = v;}
473:       else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
474:     } else  {
475:       if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
476:       else { *V = ksp->vec_sol;}
477:     }
478:   } else {
479:     if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
480:     else { *V = ksp->vec_sol; }
481:   }
482:   return(0);
483: }

487: /*
488:    KSPDefaultBuildResidual - Default code to compute the residual.

490:    Input Parameters:
491: .  ksp - iterative context
492: .  t   - pointer to temporary vector
493: .  v   - pointer to user vector  

495:    Output Parameter:
496: .  V - pointer to a vector containing the residual

498:    Level: advanced

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

502: .seealso: KSPDefaultBuildSolution()
503: */
504: PetscErrorCode KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
505: {
507:   MatStructure pflag;
508:   Vec          T;
509:   PetscScalar  mone = -1.0;
510:   Mat          Amat,Pmat;

513:   PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
514:   KSPBuildSolution(ksp,t,&T);
515:   KSP_MatMult(ksp,Amat,t,v);
516:   VecAYPX(v,mone,ksp->vec_rhs);
517:   *V = v;
518:   return(0);
519: }

523: /*
524:   KSPDefaultGetWork - Gets a number of work vectors.

526:   Input Parameters:
527: . ksp  - iterative context
528: . nw   - number of work vectors to allocate

530:   Output Parameter:
531: .  work - the array of vectors created

533:  */
534: PetscErrorCode KSPGetVecs(KSP ksp,PetscInt nw,Vec **work)
535: {
537:   Vec vec;

540:   if (ksp->vec_rhs) vec = ksp->vec_rhs;
541:   else {
542:     Mat pmat;
543:     PCGetOperators(ksp->pc,0,&pmat,0);
544:     MatGetVecs(pmat,&vec,0);
545:   }
546:   VecDuplicateVecs(vec,nw,work);
547:   if (!ksp->vec_rhs) {
548:     VecDestroy(vec);
549:   }
550:   return(0);
551: }

555: /*
556:   KSPDefaultGetWork - Gets a number of work vectors.

558:   Input Parameters:
559: . ksp  - iterative context
560: . nw   - number of work vectors to allocate

562:   Notes:
563:   Call this only if no work vectors have been allocated 
564:  */
565: PetscErrorCode KSPDefaultGetWork(KSP ksp,PetscInt nw)
566: {

570:   if (ksp->work) {KSPDefaultFreeWork(ksp);}
571:   ksp->nwork = nw;
572:   KSPGetVecs(ksp,nw,&ksp->work);
573:   PetscLogObjectParents(ksp,nw,ksp->work);
574:   return(0);
575: }

579: /*
580:   KSPDefaultDestroy - Destroys a iterative context variable for methods with
581:   no separate context.  Preferred calling sequence KSPDestroy().

583:   Input Parameter: 
584: . ksp - the iterative context
585: */
586: PetscErrorCode KSPDefaultDestroy(KSP ksp)
587: {

592:   if (ksp->data) {
593:     PetscFree(ksp->data);
594:     ksp->data = 0;
595:   }

597:   /* free work vectors */
598:   KSPDefaultFreeWork(ksp);
599:   return(0);
600: }

604: /*@C
605:    KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.

607:    Not Collective

609:    Input Parameter:
610: .  ksp - the KSP context

612:    Output Parameter:
613: .  reason - negative value indicates diverged, positive value converged, see KSPConvergedReason

615:    Possible values for reason:
616: +  KSP_CONVERGED_RTOL (residual 2-norm decreased by a factor of rtol, from 2-norm of right hand side)
617: .  KSP_CONVERGED_ATOL (residual 2-norm less than abstol)
618: .  KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration) 
619: .  KSP_CONVERGED_QCG_NEG_CURVE
620: .  KSP_CONVERGED_QCG_CONSTRAINED
621: .  KSP_CONVERGED_STEP_LENGTH
622: .  KSP_DIVERGED_ITS  (required more than its to reach convergence)
623: .  KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
624: .  KSP_DIVERGED_NAN (residual norm became Not-a-number likely do to 0/0)
625: .  KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
626: -  KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
627:                                 residual. Try a different preconditioner, or a different initial guess.)
628:  

630:    Level: beginner

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

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

636: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
637: @*/
638: PetscErrorCode PETSCKSP_DLLEXPORT KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
639: {
643:   *reason = ksp->reason;
644:   return(0);
645: }