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: /*@
 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;
125:   PetscViewer    viewer = (PetscViewer) dummy;

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

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

146:    Collective on KSP

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

154:    Level: intermediate

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

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

162: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), VecView()
163: @*/
164: PetscErrorCode PETSCKSP_DLLEXPORT KSPVecViewMonitor(KSP ksp,PetscInt its,PetscReal fgnorm,void *dummy)
165: {
167:   Vec            x;
168:   PetscViewer    viewer = (PetscViewer) dummy;

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

179:   return(0);
180: }

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

188:    Collective on KSP

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

196:    Level: intermediate

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

200: .seealso: KSPSetMonitor(), KSPTrueMonitor(), KSPLGMonitorCreate()
201: @*/
202: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
203: {
205:   PetscViewer    viewer = (PetscViewer) dummy;

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

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

219:    Collective on KSP

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

227:    Options Database Key:
228: .  -ksp_truemonitor - Activates KSPTrueMonitor()

230:    Notes:
231:    When using right preconditioning, these values are equivalent.

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

238:    Level: intermediate

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

242: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), KSPLGMonitorCreate()
243: @*/
244: PetscErrorCode PETSCKSP_DLLEXPORT KSPTrueMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
245: {
247:   Vec            resid,work;
248:   PetscReal      scnorm;
249:   PC             pc;
250:   Mat            A,B;
251:   PetscViewer    viewer = (PetscViewer) dummy;
252: 
254:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
255:   VecDuplicate(ksp->vec_rhs,&work);
256:   KSPBuildResidual(ksp,0,work,&resid);

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

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

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

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

304: /*@C
305:    KSPSkipConverged - Convergence test that NEVER returns as converged.

307:    Collective on KSP

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

315:    Returns:
316: .  reason - always KSP_CONVERGED_ITERATING

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

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

328: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
329: @*/
330: PetscErrorCode PETSCKSP_DLLEXPORT KSPSkipConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
331: {
334:   return(0);
335: }

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

343:    Collective on KSP

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

351:    Returns:
352: +   positive - if the iteration has converged;
353: .   negative - if residual norm exceeds divergence threshold;
354: -   0 - otherwise.

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

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

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

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

373:    Level: intermediate

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

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

386:   *reason = KSP_CONVERGED_ITERATING;

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

423:   if (rnorm != rnorm) {
424:     PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n");
425:     *reason = KSP_DIVERGED_NAN;
426:   } else if (rnorm <= ksp->ttol) {
427:     if (rnorm < ksp->abstol) {
428:       PetscInfo3(ksp,"Linear solver has converged. Residual norm %G is less than absolute tolerance %G at iteration %D\n",rnorm,ksp->abstol,n);
429:       *reason = KSP_CONVERGED_ATOL;
430:     } else {
431:       PetscInfo4(ksp,"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);
432:       *reason = KSP_CONVERGED_RTOL;
433:     }
434:   } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
435:     PetscInfo3(ksp,"Linear solver is diverging. Initial right hand size norm %G, current residual norm %G at iteration %D\n",ksp->rnorm0,rnorm,n);
436:     *reason = KSP_DIVERGED_DTOL;
437:   }
438:   return(0);
439: }

443: /*
444:    KSPDefaultBuildSolution - Default code to create/move the solution.

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

450:    Output Parameter:
451: .  V - pointer to a vector containing the solution

453:    Level: advanced

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

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

489: /*
490:    KSPDefaultBuildResidual - Default code to compute the residual.

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

497:    Output Parameter:
498: .  V - pointer to a vector containing the residual

500:    Level: advanced

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

504: .seealso: KSPDefaultBuildSolution()
505: */
506: PetscErrorCode KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
507: {
509:   MatStructure   pflag;
510:   Mat            Amat,Pmat;

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

523: /*@C
524:   KSPGetVecs - Gets a number of work vectors.

526:   Input Parameters:
527: + ksp  - iterative context
528: . rightn  - number of right work vectors
529: - leftn   - number of left work vectors to allocate

531:   Output Parameter:
532: +  right - the array of vectors created
533: -  left - the array of left vectors

535:    Note: The right vector has as many elements as the matrix has columns. The left
536:      vector has as many elements as the matrix has rows.

538:    Level: advanced

540: .seealso:   MatGetVecs()

542: @*/
543: PetscErrorCode KSPGetVecs(KSP ksp,PetscInt rightn, Vec **right,PetscInt leftn,Vec **left)
544: {
546:   Vec            vecr,vecl;

549:   if (rightn) {
550:     if (!right) SETERRQ(PETSC_ERR_ARG_INCOMP,"You asked for right vectors but did not pass a pointer to hold them");
551:     if (ksp->vec_sol) vecr = ksp->vec_sol;
552:     else {
553:       Mat pmat;
554:       PCGetOperators(ksp->pc,0,&pmat,0);
555:       MatGetVecs(pmat,&vecr,0);
556:     }
557:     VecDuplicateVecs(vecr,rightn,right);
558:     if (!ksp->vec_sol) {
559:       VecDestroy(vecr);
560:     }
561:   }
562:   if (leftn) {
563:     if (!left) SETERRQ(PETSC_ERR_ARG_INCOMP,"You asked for left vectors but did not pass a pointer to hold them");
564:     if (ksp->vec_rhs) vecl = ksp->vec_rhs;
565:     else {
566:       Mat pmat;
567:       PCGetOperators(ksp->pc,0,&pmat,0);
568:       MatGetVecs(pmat,0,&vecl);
569:     }
570:     VecDuplicateVecs(vecl,leftn,left);
571:     if (!ksp->vec_rhs) {
572:       VecDestroy(vecl);
573:     }
574:   }
575:   return(0);
576: }

580: /*
581:   KSPDefaultGetWork - Gets a number of work vectors.

583:   Input Parameters:
584: . ksp  - iterative context
585: . nw   - number of work vectors to allocate

587:   Notes:
588:   Call this only if no work vectors have been allocated 
589:  */
590: PetscErrorCode KSPDefaultGetWork(KSP ksp,PetscInt nw)
591: {

595:   if (ksp->work) {KSPDefaultFreeWork(ksp);}
596:   ksp->nwork = nw;
597:   KSPGetVecs(ksp,nw,&ksp->work,0,PETSC_NULL);
598:   PetscLogObjectParents(ksp,nw,ksp->work);
599:   return(0);
600: }

604: /*
605:   KSPDefaultDestroy - Destroys a iterative context variable for methods with
606:   no separate context.  Preferred calling sequence KSPDestroy().

608:   Input Parameter: 
609: . ksp - the iterative context
610: */
611: PetscErrorCode KSPDefaultDestroy(KSP ksp)
612: {

617:   PetscFree(ksp->data);

619:   /* free work vectors */
620:   KSPDefaultFreeWork(ksp);
621:   return(0);
622: }

626: /*@
627:    KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.

629:    Not Collective

631:    Input Parameter:
632: .  ksp - the KSP context

634:    Output Parameter:
635: .  reason - negative value indicates diverged, positive value converged, see KSPConvergedReason

637:    Possible values for reason:
638: +  KSP_CONVERGED_RTOL (residual 2-norm decreased by a factor of rtol, from 2-norm of right hand side)
639: .  KSP_CONVERGED_ATOL (residual 2-norm less than abstol)
640: .  KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration) 
641: .  KSP_CONVERGED_QCG_NEG_CURVE
642: .  KSP_CONVERGED_QCG_CONSTRAINED
643: .  KSP_CONVERGED_STEP_LENGTH
644: .  KSP_DIVERGED_ITS  (required more than its to reach convergence)
645: .  KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
646: .  KSP_DIVERGED_NAN (residual norm became Not-a-number likely do to 0/0)
647: .  KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
648: -  KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
649:                                 residual. Try a different preconditioner, or a different initial guess.)
650:  

652:    Level: beginner

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

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

658: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
659: @*/
660: PetscErrorCode PETSCKSP_DLLEXPORT KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
661: {
665:   *reason = ksp->reason;
666:   return(0);
667: }