Actual source code: lsqr_converged.c
petsc-3.4.2 2013-07-02
1: #include <petsc-private/kspimpl.h>
2: #include <../src/ksp/ksp/impls/lsqr/lsqr.h>
3: extern PetscErrorCode KSPLSQRGetArnorm(KSP,PetscReal*,PetscReal*,PetscReal*);
5: PetscErrorCode KSPConvergedLSQR(KSP solksp,PetscInt iter,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
6: {
7: PetscReal atol; /* Absolute convergence criterium */
8: PetscReal dtol; /* Divergence criterium */
9: PetscReal rtol; /* Relative convergence criterium */
10: PetscReal stop1; /* Stop if: |r| < rtol*|b| + atol*|A|*|x| */
11: PetscReal stop2; /* Stop if: |A^t.r|/(|A|*|r|) < atol */
12: Vec x_sol; /* Current solution vector */
14: PetscReal arnorm, anorm, bnorm, xnorm; /* Norms of A*residual; matrix A; rhs; solution */
16: PetscInt mxiter; /* Maximum # of iterations */
20: *reason = KSP_CONVERGED_ITERATING;
21: if (iter == 0) return(0);
23: if (PetscIsInfOrNanScalar(rnorm)) {
24: *reason = KSP_DIVERGED_NANORINF;
25: return(0);
26: }
28: KSPGetTolerances(solksp, &rtol, &atol, &dtol, &mxiter);
29: if (iter > mxiter) {
30: *reason = KSP_DIVERGED_ITS;
31: return(0);
32: }
34: KSPGetSolution(solksp, &x_sol);
35: VecNorm(x_sol, NORM_2, &xnorm);
37: KSPLSQRGetArnorm(solksp, &arnorm, &bnorm, &anorm);
38: if (bnorm > 0.0) {
39: stop1 = rnorm / bnorm;
40: rtol = rtol + atol * anorm*xnorm/bnorm;
41: } else {
42: stop1 = 0.0;
43: rtol = 0.0;
44: }
45: stop2 = 0.0;
46: if (rnorm > 0.0) stop2 = arnorm / (anorm * rnorm);
48: /* Test for tolerances set by the user */
49: if (stop1 <= rtol) *reason = KSP_CONVERGED_RTOL;
50: if (stop2 <= atol) *reason = KSP_CONVERGED_ATOL;
52: /* Test for machine precision */
53: if (bnorm > 0) stop1 = stop1 / (1.0 + anorm*xnorm/bnorm);
54: else stop1 = 0.0;
56: stop1 = 1.0 + stop1;
57: stop2 = 1.0 + stop2;
58: if (stop1 <= 1.0) *reason = KSP_CONVERGED_RTOL;
59: if (stop2 <= 1.0) *reason = KSP_CONVERGED_ATOL;
60: return(0);
61: }