Actual source code: lsqr.c
petsc-3.15.0 2021-03-30
Report Typos and Errors

      2: /* lourens.vanzanen@shell.com contributed the standard error estimates of the solution, Jul 25, 2006 */
      3: /* Bas van't Hof contributed the preconditioned aspects Feb 10, 2010 */

      5: #define SWAP(a,b,c) { c = a; a = b; b = c; }

      7: #include <petsc/private/kspimpl.h>
      8: #include <petscdraw.h>

     10: typedef struct {
     11:   PetscInt  nwork_n,nwork_m;
     12:   Vec       *vwork_m;   /* work vectors of length m, where the system is size m x n */
     13:   Vec       *vwork_n;   /* work vectors of length n */
     14:   Vec       se;         /* Optional standard error vector */
     15:   PetscBool se_flg;     /* flag for -ksp_lsqr_set_standard_error */
     16:   PetscBool exact_norm; /* flag for -ksp_lsqr_exact_mat_norm */
     17:   PetscReal arnorm;     /* Good estimate of norm((A*inv(Pmat))'*r), where r = A*x - b, used in specific stopping criterion */
     18:   PetscReal anorm;      /* Poor estimate of norm(A*inv(Pmat),'fro') used in specific stopping criterion */
     19:   /* Backup previous convergence test */
     20:   PetscErrorCode        (*converged)(KSP,PetscInt,PetscReal,KSPConvergedReason*,void*);
     21:   PetscErrorCode        (*convergeddestroy)(void*);
     22:   void                  *cnvP;
     23: } KSP_LSQR;

     25: static PetscErrorCode  VecSquare(Vec v)
     26: {
     28:   PetscScalar    *x;
     29:   PetscInt       i, n;

     32:   VecGetLocalSize(v, &n);
     33:   VecGetArray(v, &x);
     34:   for (i = 0; i < n; i++) x[i] *= PetscConj(x[i]);
     35:   VecRestoreArray(v, &x);
     36:   return(0);
     37: }

     39: static PetscErrorCode KSPSetUp_LSQR(KSP ksp)
     40: {
     42:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;
     43:   PetscBool      nopreconditioner;

     46:   PetscObjectTypeCompare((PetscObject)ksp->pc,PCNONE,&nopreconditioner);

     48:   if (lsqr->vwork_m) {
     49:     VecDestroyVecs(lsqr->nwork_m,&lsqr->vwork_m);
     50:   }

     52:   if (lsqr->vwork_n) {
     53:     VecDestroyVecs(lsqr->nwork_n,&lsqr->vwork_n);
     54:   }

     56:   lsqr->nwork_m = 2;
     57:   if (nopreconditioner) lsqr->nwork_n = 4;
     58:   else lsqr->nwork_n = 5;
     59:   KSPCreateVecs(ksp,lsqr->nwork_n,&lsqr->vwork_n,lsqr->nwork_m,&lsqr->vwork_m);

     61:   if (lsqr->se_flg && !lsqr->se) {
     62:     VecDuplicate(lsqr->vwork_n[0],&lsqr->se);
     63:     VecSet(lsqr->se,PETSC_INFINITY);
     64:   } else if (!lsqr->se_flg) {
     65:     VecDestroy(&lsqr->se);
     66:   }
     67:   return(0);
     68: }

     70: static PetscErrorCode KSPSolve_LSQR(KSP ksp)
     71: {
     73:   PetscInt       i,size1,size2;
     74:   PetscScalar    rho,rhobar,phi,phibar,theta,c,s,tmp,tau;
     75:   PetscReal      beta,alpha,rnorm;
     76:   Vec            X,B,V,V1,U,U1,TMP,W,W2,Z = NULL;
     77:   Mat            Amat,Pmat;
     78:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;
     79:   PetscBool      diagonalscale,nopreconditioner;

     82:   PCGetDiagonalScale(ksp->pc,&diagonalscale);
     83:   if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);

     85:   PCGetOperators(ksp->pc,&Amat,&Pmat);
     86:   PetscObjectTypeCompare((PetscObject)ksp->pc,PCNONE,&nopreconditioner);

     88:   /* vectors of length m, where system size is mxn */
     89:   B  = ksp->vec_rhs;
     90:   U  = lsqr->vwork_m[0];
     91:   U1 = lsqr->vwork_m[1];

     93:   /* vectors of length n */
     94:   X  = ksp->vec_sol;
     95:   W  = lsqr->vwork_n[0];
     96:   V  = lsqr->vwork_n[1];
     97:   V1 = lsqr->vwork_n[2];
     98:   W2 = lsqr->vwork_n[3];
     99:   if (!nopreconditioner) Z = lsqr->vwork_n[4];

    101:   /* standard error vector */
    102:   if (lsqr->se) {
    103:     VecSet(lsqr->se,0.0);
    104:   }

    106:   /* Compute initial residual, temporarily use work vector u */
    107:   if (!ksp->guess_zero) {
    108:     KSP_MatMult(ksp,Amat,X,U);       /*   u <- b - Ax     */
    109:     VecAYPX(U,-1.0,B);
    110:   } else {
    111:     VecCopy(B,U);            /*   u <- b (x is 0) */
    112:   }

    114:   /* Test for nothing to do */
    115:   VecNorm(U,NORM_2,&rnorm);
    116:   KSPCheckNorm(ksp,rnorm);
    117:   PetscObjectSAWsTakeAccess((PetscObject)ksp);
    118:   ksp->its   = 0;
    119:   ksp->rnorm = rnorm;
    120:   PetscObjectSAWsGrantAccess((PetscObject)ksp);
    121:   KSPLogResidualHistory(ksp,rnorm);
    122:   KSPMonitor(ksp,0,rnorm);
    123:   (*ksp->converged)(ksp,0,rnorm,&ksp->reason,ksp->cnvP);
    124:   if (ksp->reason) return(0);

    126:   beta = rnorm;
    127:   VecScale(U,1.0/beta);
    128:   KSP_MatMultTranspose(ksp,Amat,U,V);
    129:   if (nopreconditioner) {
    130:     VecNorm(V,NORM_2,&alpha);
    131:     KSPCheckNorm(ksp,rnorm);
    132:   } else {
    133:     /* this is an application of the preconditioner for the normal equations; not the operator, see the manual page */
    134:     PCApply(ksp->pc,V,Z);
    135:     VecDotRealPart(V,Z,&alpha);
    136:     if (alpha <= 0.0) {
    137:       ksp->reason = KSP_DIVERGED_BREAKDOWN;
    138:       return(0);
    139:     }
    140:     alpha = PetscSqrtReal(alpha);
    141:     VecScale(Z,1.0/alpha);
    142:   }
    143:   VecScale(V,1.0/alpha);

    145:   if (nopreconditioner) {
    146:     VecCopy(V,W);
    147:   } else {
    148:     VecCopy(Z,W);
    149:   }

    151:   if (lsqr->exact_norm) {
    152:     MatNorm(Amat,NORM_FROBENIUS,&lsqr->anorm);
    153:   } else lsqr->anorm = 0.0;

    155:   lsqr->arnorm = alpha * beta;
    156:   phibar       = beta;
    157:   rhobar       = alpha;
    158:   i            = 0;
    159:   do {
    160:     if (nopreconditioner) {
    161:       KSP_MatMult(ksp,Amat,V,U1);
    162:     } else {
    163:       KSP_MatMult(ksp,Amat,Z,U1);
    164:     }
    165:     VecAXPY(U1,-alpha,U);
    166:     VecNorm(U1,NORM_2,&beta);
    167:     KSPCheckNorm(ksp,beta);
    168:     if (beta > 0.0) {
    169:       VecScale(U1,1.0/beta); /* beta*U1 = Amat*V - alpha*U */
    170:       if (!lsqr->exact_norm) {
    171:         lsqr->anorm = PetscSqrtScalar(PetscSqr(lsqr->anorm) + PetscSqr(alpha) + PetscSqr(beta));
    172:       }
    173:     }

    175:     KSP_MatMultTranspose(ksp,Amat,U1,V1);
    176:     VecAXPY(V1,-beta,V);
    177:     if (nopreconditioner) {
    178:       VecNorm(V1,NORM_2,&alpha);
    179:       KSPCheckNorm(ksp,alpha);
    180:     } else {
    181:       PCApply(ksp->pc,V1,Z);
    182:       VecDotRealPart(V1,Z,&alpha);
    183:       if (alpha <= 0.0) {
    184:         ksp->reason = KSP_DIVERGED_BREAKDOWN;
    185:         break;
    186:       }
    187:       alpha = PetscSqrtReal(alpha);
    188:       VecScale(Z,1.0/alpha);
    189:     }
    190:     VecScale(V1,1.0/alpha); /* alpha*V1 = Amat^T*U1 - beta*V */
    191:     rho    = PetscSqrtScalar(rhobar*rhobar + beta*beta);
    192:     c      = rhobar / rho;
    193:     s      = beta / rho;
    194:     theta  = s * alpha;
    195:     rhobar = -c * alpha;
    196:     phi    = c * phibar;
    197:     phibar = s * phibar;
    198:     tau    = s * phi;

    200:     VecAXPY(X,phi/rho,W);  /*    x <- x + (phi/rho) w   */

    202:     if (lsqr->se) {
    203:       VecCopy(W,W2);
    204:       VecSquare(W2);
    205:       VecScale(W2,1.0/(rho*rho));
    206:       VecAXPY(lsqr->se, 1.0, W2); /* lsqr->se <- lsqr->se + (w^2/rho^2) */
    207:     }
    208:     if (nopreconditioner) {
    209:       VecAYPX(W,-theta/rho,V1);  /* w <- v - (theta/rho) w */
    210:     } else {
    211:       VecAYPX(W,-theta/rho,Z);   /* w <- z - (theta/rho) w */
    212:     }

    214:     lsqr->arnorm = alpha*PetscAbsScalar(tau);
    215:     rnorm        = PetscRealPart(phibar);

    217:     PetscObjectSAWsTakeAccess((PetscObject)ksp);
    218:     ksp->its++;
    219:     ksp->rnorm = rnorm;
    220:     PetscObjectSAWsGrantAccess((PetscObject)ksp);
    221:     KSPLogResidualHistory(ksp,rnorm);
    222:     KSPMonitor(ksp,i+1,rnorm);
    223:     (*ksp->converged)(ksp,i+1,rnorm,&ksp->reason,ksp->cnvP);
    224:     if (ksp->reason) break;
    225:     SWAP(U1,U,TMP);
    226:     SWAP(V1,V,TMP);

    228:     i++;
    229:   } while (i<ksp->max_it);
    230:   if (i >= ksp->max_it && !ksp->reason) ksp->reason = KSP_DIVERGED_ITS;

    232:   /* Finish off the standard error estimates */
    233:   if (lsqr->se) {
    234:     tmp  = 1.0;
    235:     MatGetSize(Amat,&size1,&size2);
    236:     if (size1 > size2) tmp = size1 - size2;
    237:     tmp  = rnorm / PetscSqrtScalar(tmp);
    238:     VecSqrtAbs(lsqr->se);
    239:     VecScale(lsqr->se,tmp);
    240:   }
    241:   return(0);
    242: }

    245: PetscErrorCode KSPDestroy_LSQR(KSP ksp)
    246: {
    247:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;

    251:   /* Free work vectors */
    252:   if (lsqr->vwork_n) {
    253:     VecDestroyVecs(lsqr->nwork_n,&lsqr->vwork_n);
    254:   }
    255:   if (lsqr->vwork_m) {
    256:     VecDestroyVecs(lsqr->nwork_m,&lsqr->vwork_m);
    257:   }
    258:   VecDestroy(&lsqr->se);
    259:   /* Revert convergence test */
    260:   KSPSetConvergenceTest(ksp,lsqr->converged,lsqr->cnvP,lsqr->convergeddestroy);
    261:   /* Free the KSP_LSQR context */
    262:   PetscFree(ksp->data);
    263:   return(0);
    264: }

    266: /*@
    267:    KSPLSQRSetComputeStandardErrorVec - Compute vector of standard error estimates during KSPSolve_LSQR().

    269:    Not Collective

    271:    Input Parameters:
    272: +  ksp   - iterative context
    273: -  flg   - compute the vector of standard estimates or not

    275:    Developer notes:
    276:    Vaclav: I'm not sure whether this vector is useful for anything.

    278:    Level: intermediate

    280: .seealso: KSPSolve(), KSPLSQR, KSPLSQRGetStandardErrorVec()
    281: @*/
    282: PetscErrorCode  KSPLSQRSetComputeStandardErrorVec(KSP ksp, PetscBool flg)
    283: {
    284:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;

    287:   lsqr->se_flg = flg;
    288:   return(0);
    289: }

    291: /*@
    292:    KSPLSQRSetExactMatNorm - Compute exact matrix norm instead of iteratively refined estimate.

    294:    Not Collective

    296:    Input Parameters:
    297: +  ksp   - iterative context
    298: -  flg   - compute exact matrix norm or not

    300:    Notes:
    301:    By default, flg=PETSC_FALSE. This is usually preferred to avoid possibly expensive computation of the norm.
    302:    For flg=PETSC_TRUE, we call MatNorm(Amat,NORM_FROBENIUS,&lsqr->anorm) which will work only for some types of explicitly assembled matrices.
    303:    This can affect convergence rate as KSPLSQRConvergedDefault() assumes different value of ||A|| used in normal equation stopping criterion.

    305:    Level: intermediate

    307: .seealso: KSPSolve(), KSPLSQR, KSPLSQRGetNorms(), KSPLSQRConvergedDefault()
    308: @*/
    309: PetscErrorCode  KSPLSQRSetExactMatNorm(KSP ksp, PetscBool flg)
    310: {
    311:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;

    314:   lsqr->exact_norm = flg;
    315:   return(0);
    316: }

    318: /*@
    319:    KSPLSQRGetStandardErrorVec - Get vector of standard error estimates.
    320:    Only available if -ksp_lsqr_set_standard_error was set to true
    321:    or KSPLSQRSetComputeStandardErrorVec(ksp, PETSC_TRUE) was called.
    322:    Otherwise returns NULL.

    324:    Not Collective

    326:    Input Parameters:
    327: .  ksp   - iterative context

    329:    Output Parameters:
    330: .  se - vector of standard estimates

    332:    Options Database Keys:
    333: .   -ksp_lsqr_set_standard_error  - set standard error estimates of solution

    335:    Developer notes:
    336:    Vaclav: I'm not sure whether this vector is useful for anything.

    338:    Level: intermediate

    340: .seealso: KSPSolve(), KSPLSQR, KSPLSQRSetComputeStandardErrorVec()
    341: @*/
    342: PetscErrorCode  KSPLSQRGetStandardErrorVec(KSP ksp,Vec *se)
    343: {
    344:   KSP_LSQR *lsqr = (KSP_LSQR*)ksp->data;

    347:   *se = lsqr->se;
    348:   return(0);
    349: }

    351: /*@
    352:    KSPLSQRGetNorms - Get norm estimates that LSQR computes internally during KSPSolve().

    354:    Not Collective

    356:    Input Parameters:
    357: .  ksp   - iterative context

    359:    Output Parameters:
    360: +  arnorm - good estimate of norm((A*inv(Pmat))'*r), where r = A*x - b, used in specific stopping criterion
    361: -  anorm - poor estimate of norm(A*inv(Pmat),'fro') used in specific stopping criterion

    363:    Notes:
    364:    Output parameters are meaningful only after KSPSolve().
    365:    These are the same quantities as normar and norma in MATLAB's lsqr(), whose output lsvec is a vector of normar / norma for all iterations.
    366:    If -ksp_lsqr_exact_mat_norm is set or KSPLSQRSetExactMatNorm(ksp, PETSC_TRUE) called, then anorm is exact Frobenius norm.

    368:    Level: intermediate

    370: .seealso: KSPSolve(), KSPLSQR, KSPLSQRSetExactMatNorm()
    371: @*/
    372: PetscErrorCode  KSPLSQRGetNorms(KSP ksp,PetscReal *arnorm, PetscReal *anorm)
    373: {
    374:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;

    377:   if (arnorm)   *arnorm = lsqr->arnorm;
    378:   if (anorm)    *anorm = lsqr->anorm;
    379:   return(0);
    380: }

    382: /*@C
    383:   KSLSQRPMonitorResidual - Prints the residual norm, as well as the normal equation residual norm, at each iteration of an iterative solver.

    385:   Collective on ksp

    387:   Input Parameters:
    388: + ksp   - iterative context
    389: . n     - iteration number
    390: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
    391: - vf    - The viewer context

    393:   Options Database Key:
    394: . -ksp_lsqr_monitor - Activates KSPLSQRMonitorResidual()

    396:   Level: intermediate

    398: .seealso: KSPMonitorSet(), KSPMonitorResidual(),KSPMonitorTrueResidualMaxNorm()
    399: @*/
    400: PetscErrorCode KSPLSQRMonitorResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
    401: {
    402:   KSP_LSQR         *lsqr   = (KSP_LSQR*)ksp->data;
    403:   PetscViewer       viewer = vf->viewer;
    404:   PetscViewerFormat format = vf->format;
    405:   char              normtype[256];
    406:   PetscInt          tablevel;
    407:   const char       *prefix;
    408:   PetscErrorCode    ierr;

    412:   PetscObjectGetTabLevel((PetscObject) ksp, &tablevel);
    413:   PetscObjectGetOptionsPrefix((PetscObject) ksp, &prefix);
    414:   PetscStrncpy(normtype, KSPNormTypes[ksp->normtype], sizeof(normtype));
    415:   PetscStrtolower(normtype);
    416:   PetscViewerPushFormat(viewer, format);
    417:   PetscViewerASCIIAddTab(viewer, tablevel);
    418:   if (n == 0 && prefix) {PetscViewerASCIIPrintf(viewer, "  Residual norm, norm of normal equations, and matrix norm for %s solve.\n", prefix);}
    419:   if (!n) {
    420:     PetscViewerASCIIPrintf(viewer,"%3D KSP resid norm %14.12e\n",n,(double)rnorm);
    421:   } else {
    422:     PetscViewerASCIIPrintf(viewer,"%3D KSP resid norm %14.12e normal eq resid norm %14.12e matrix norm %14.12e\n",n,(double)rnorm,(double)lsqr->arnorm,(double)lsqr->anorm);
    423:   }
    424:   PetscViewerASCIISubtractTab(viewer, tablevel);
    425:   PetscViewerPopFormat(viewer);
    426:   return(0);
    427: }

    429: /*@C
    430:   KSPLSQRMonitorResidualDrawLG - Plots the true residual norm at each iteration of an iterative solver.

    432:   Collective on ksp

    434:   Input Parameters:
    435: + ksp   - iterative context
    436: . n     - iteration number
    437: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
    438: - vf    - The viewer context

    440:   Options Database Key:
    441: . -ksp_lsqr_monitor draw::draw_lg - Activates KSPMonitorTrueResidualDrawLG()

    443:   Level: intermediate

    445: .seealso: KSPMonitorSet(), KSPMonitorTrueResidual()
    446: @*/
    447: PetscErrorCode KSPLSQRMonitorResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
    448: {
    449:   KSP_LSQR          *lsqr   = (KSP_LSQR*)ksp->data;
    450:   PetscViewer        viewer = vf->viewer;
    451:   PetscViewerFormat  format = vf->format;
    452:   PetscDrawLG        lg     = vf->lg;
    453:   KSPConvergedReason reason;
    454:   PetscReal          x[2], y[2];
    455:   PetscErrorCode     ierr;

    460:   PetscViewerPushFormat(viewer, format);
    461:   if (!n) {PetscDrawLGReset(lg);}
    462:   x[0] = (PetscReal) n;
    463:   if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
    464:   else y[0] = -15.0;
    465:   x[1] = (PetscReal) n;
    466:   if (lsqr->arnorm > 0.0) y[1] = PetscLog10Real(lsqr->arnorm);
    467:   else y[1] = -15.0;
    468:   PetscDrawLGAddPoint(lg, x, y);
    469:   KSPGetConvergedReason(ksp, &reason);
    470:   if (n <= 20 || !(n % 5) || reason) {
    471:     PetscDrawLGDraw(lg);
    472:     PetscDrawLGSave(lg);
    473:   }
    474:   PetscViewerPopFormat(viewer);
    475:   return(0);
    476: }

    478: /*@C
    479:   KSPLSQRMonitorResidualDrawLGCreate - Creates the plotter for the LSQR residual and normal eqn residual.

    481:   Collective on ksp

    483:   Input Parameters:
    484: + viewer - The PetscViewer
    485: . format - The viewer format
    486: - ctx    - An optional user context

    488:   Output Parameter:
    489: . vf    - The viewer context

    491:   Level: intermediate

    493: .seealso: KSPMonitorSet(), KSPLSQRMonitorResidual()
    494: @*/
    495: PetscErrorCode KSPLSQRMonitorResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
    496: {
    497:   const char    *names[] = {"residual", "normal eqn residual"};

    501:   PetscViewerAndFormatCreate(viewer, format, vf);
    502:   (*vf)->data = ctx;
    503:   KSPMonitorLGCreate(PetscObjectComm((PetscObject) viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg);
    504:   return(0);
    505: }

    507: PetscErrorCode KSPSetFromOptions_LSQR(PetscOptionItems *PetscOptionsObject,KSP ksp)
    508: {
    510:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;

    513:   PetscOptionsHead(PetscOptionsObject,"KSP LSQR Options");
    514:   PetscOptionsBool("-ksp_lsqr_compute_standard_error","Set Standard Error Estimates of Solution","KSPLSQRSetComputeStandardErrorVec",lsqr->se_flg,&lsqr->se_flg,NULL);
    515:   PetscOptionsBool("-ksp_lsqr_exact_mat_norm","Compute exact matrix norm instead of iteratively refined estimate","KSPLSQRSetExactMatNorm",lsqr->exact_norm,&lsqr->exact_norm,NULL);
    516:   KSPMonitorSetFromOptions(ksp, "-ksp_lsqr_monitor", "lsqr_residual", NULL);
    517:   PetscOptionsTail();
    518:   return(0);
    519: }

    521: PetscErrorCode KSPView_LSQR(KSP ksp,PetscViewer viewer)
    522: {
    523:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;
    525:   PetscBool      iascii;

    528:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    529:   if (iascii) {
    530:     if (lsqr->se) {
    531:       PetscReal rnorm;
    532:       VecNorm(lsqr->se,NORM_2,&rnorm);
    533:       PetscViewerASCIIPrintf(viewer,"  norm of standard error %g, iterations %d\n",(double)rnorm,ksp->its);
    534:     } else {
    535:       PetscViewerASCIIPrintf(viewer,"  standard error not computed\n");
    536:     }
    537:     if (lsqr->exact_norm) {
    538:       PetscViewerASCIIPrintf(viewer,"  using exact matrix norm\n");
    539:     } else {
    540:       PetscViewerASCIIPrintf(viewer,"  using inexact matrix norm\n");
    541:     }
    542:   }
    543:   return(0);
    544: }

    546: /*@C
    547:    KSPLSQRConvergedDefault - Determines convergence of the LSQR Krylov method.

    549:    Collective on ksp

    551:    Input Parameters:
    552: +  ksp   - iterative context
    553: .  n     - iteration number
    554: .  rnorm - 2-norm residual value (may be estimated)
    555: -  ctx - convergence context which must be created by KSPConvergedDefaultCreate()

    557:    reason is set to:
    558: +   positive - if the iteration has converged;
    559: .   negative - if residual norm exceeds divergence threshold;
    560: -   0 - otherwise.

    562:    Notes:
    563:    KSPConvergedDefault() is called first to check for convergence in A*x=b.
    564:    If that does not determine convergence then checks convergence for the least squares problem, i.e. in min{|b-A*x|}.
    565:    Possible convergence for the least squares problem (which is based on the residual of the normal equations) are KSP_CONVERGED_RTOL_NORMAL norm and KSP_CONVERGED_ATOL_NORMAL.
    566:    KSP_CONVERGED_RTOL_NORMAL is returned if ||A'*r|| < rtol * ||A|| * ||r||.
    567:    Matrix norm ||A|| is iteratively refined estimate, see KSPLSQRGetNorms().
    568:    This criterion is now largely compatible with that in MATLAB lsqr().

    570:    Level: intermediate

    572: .seealso: KSPLSQR, KSPSetConvergenceTest(), KSPSetTolerances(), KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(),
    573:           KSPConvergedDefaultSetUIRNorm(), KSPConvergedDefaultSetUMIRNorm(), KSPConvergedDefaultCreate(), KSPConvergedDefaultDestroy(), KSPConvergedDefault(), KSPLSQRGetNorms(), KSPLSQRSetExactMatNorm()
    574: @*/
    575: PetscErrorCode  KSPLSQRConvergedDefault(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
    576: {
    578:   KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;

    581:   /* check for convergence in A*x=b */
    582:   KSPConvergedDefault(ksp,n,rnorm,reason,ctx);
    583:   if (!n || *reason) return(0);

    585:   /* check for convergence in min{|b-A*x|} */
    586:   if (lsqr->arnorm < ksp->abstol) {
    587:     PetscInfo3(ksp,"LSQR solver has converged. Normal equation residual %14.12e is less than absolute tolerance %14.12e at iteration %D\n",(double)lsqr->arnorm,(double)ksp->abstol,n);
    588:     *reason = KSP_CONVERGED_ATOL_NORMAL;
    589:   } else if (lsqr->arnorm < ksp->rtol * lsqr->anorm * rnorm) {
    590:     PetscInfo6(ksp,"LSQR solver has converged. Normal equation residual %14.12e is less than rel. tol. %14.12e times %s Frobenius norm of matrix %14.12e times residual %14.12e at iteration %D\n",(double)lsqr->arnorm,(double)ksp->rtol,lsqr->exact_norm?"exact":"approx.",(double)lsqr->anorm,(double)rnorm,n);
    591:     *reason = KSP_CONVERGED_RTOL_NORMAL;
    592:   }
    593:   return(0);
    594: }

    596: /*MC
    597:      KSPLSQR - This implements LSQR

    599:    Options Database Keys:
    600: +   -ksp_lsqr_set_standard_error  - set standard error estimates of solution, see KSPLSQRSetComputeStandardErrorVec() and KSPLSQRGetStandardErrorVec()
    601: .   -ksp_lsqr_exact_mat_norm - compute exact matrix norm instead of iteratively refined estimate, see KSPLSQRSetExactMatNorm()
    602: -   -ksp_lsqr_monitor - monitor residual norm, norm of residual of normal equations A'*A x = A' b, and estimate of matrix norm ||A||

    604:    Level: beginner

    606:    Notes:
    607:      Supports non-square (rectangular) matrices.

    609:      This varient, when applied with no preconditioning is identical to the original algorithm in exact arithematic; however, in practice, with no preconditioning
    610:      due to inexact arithematic, it can converge differently. Hence when no preconditioner is used (PCType PCNONE) it automatically reverts to the original algorithm.

    612:      With the PETSc built-in preconditioners, such as ICC, one should call KSPSetOperators(ksp,A,A'*A)) since the preconditioner needs to work
    613:      for the normal equations A'*A.

    615:      Supports only left preconditioning.

    617:      For least squares problems wit nonzero residual A*x - b, there are additional convergence tests for the residual of the normal equations, A'*(b - Ax), see KSPLSQRConvergedDefault().

    619:    References:
    620: .  1. - The original unpreconditioned algorithm can be found in Paige and Saunders, ACM Transactions on Mathematical Software, Vol 8, 1982.

    622:      In exact arithmetic the LSQR method (with no preconditioning) is identical to the KSPCG algorithm applied to the normal equations.
    623:      The preconditioned variant was implemented by Bas van't Hof and is essentially a left preconditioning for the Normal Equations. It appears the implementation with preconditioner
    624:      track the true norm of the residual and uses that in the convergence test.

    626:    Developer Notes:
    627:     How is this related to the KSPCGNE implementation? One difference is that KSPCGNE applies
    628:             the preconditioner transpose times the preconditioner,  so one does not need to pass A'*A as the third argument to KSPSetOperators().

    632: .seealso:  KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPSolve(), KSPLSQRConvergedDefault(), KSPLSQRSetComputeStandardErrorVec(), KSPLSQRGetStandardErrorVec(), KSPLSQRSetExactMatNorm()

    634: M*/
    635: PETSC_EXTERN PetscErrorCode KSPCreate_LSQR(KSP ksp)
    636: {
    637:   KSP_LSQR       *lsqr;
    638:   void           *ctx;

    642:   PetscNewLog(ksp,&lsqr);
    643:   lsqr->se     = NULL;
    644:   lsqr->se_flg = PETSC_FALSE;
    645:   lsqr->exact_norm = PETSC_FALSE;
    646:   lsqr->anorm  = -1.0;
    647:   lsqr->arnorm = -1.0;
    648:   ksp->data    = (void*)lsqr;
    649:   KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,3);

    651:   ksp->ops->setup          = KSPSetUp_LSQR;
    652:   ksp->ops->solve          = KSPSolve_LSQR;
    653:   ksp->ops->destroy        = KSPDestroy_LSQR;
    654:   ksp->ops->setfromoptions = KSPSetFromOptions_LSQR;
    655:   ksp->ops->view           = KSPView_LSQR;

    657:   /* Backup current convergence test; remove destroy routine from KSP to prevent destroying the convergence context in KSPSetConvergenceTest() */
    658:   KSPGetAndClearConvergenceTest(ksp,&lsqr->converged,&lsqr->cnvP,&lsqr->convergeddestroy);
    659:   /* Override current convergence test */
    660:   KSPConvergedDefaultCreate(&ctx);
    661:   KSPSetConvergenceTest(ksp,KSPLSQRConvergedDefault,ctx,KSPConvergedDefaultDestroy);
    662:   return(0);
    663: }