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

      1: /*
      2:     This file implements CGLS, the Conjugate Gradient method for Least-Squares problems.
      3: */
      4: #include <petsc/private/kspimpl.h>

      6: typedef struct {
      7:   PetscInt  nwork_n,nwork_m;
      8:   Vec       *vwork_m;   /* work vectors of length m, where the system is size m x n */
      9:   Vec       *vwork_n;   /* work vectors of length n */
     10: } KSP_CGLS;

     12: static PetscErrorCode KSPSetUp_CGLS(KSP ksp)
     13: {
     15:   KSP_CGLS       *cgls = (KSP_CGLS*)ksp->data;

     18:   cgls->nwork_m = 2;
     19:   if (cgls->vwork_m) {
     20:     VecDestroyVecs(cgls->nwork_m,&cgls->vwork_m);
     21:   }

     23:   cgls->nwork_n = 2;
     24:   if (cgls->vwork_n) {
     25:     VecDestroyVecs(cgls->nwork_n,&cgls->vwork_n);
     26:   }
     27:   KSPCreateVecs(ksp,cgls->nwork_n,&cgls->vwork_n,cgls->nwork_m,&cgls->vwork_m);
     28:   return(0);
     29: }

     31: static PetscErrorCode KSPSolve_CGLS(KSP ksp)
     32: {
     34:   KSP_CGLS       *cgls = (KSP_CGLS*)ksp->data;
     35:   Mat            A;
     36:   Vec            x,b,r,p,q,ss;
     37:   PetscScalar    beta;
     38:   PetscReal      alpha,gamma,oldgamma;

     41:   KSPGetOperators(ksp,&A,NULL); /* Matrix of the system */

     43:   /* vectors of length n, where system size is mxn */
     44:   x  = ksp->vec_sol; /* Solution vector */
     45:   p  = cgls->vwork_n[0];
     46:   ss  = cgls->vwork_n[1];

     48:   /* vectors of length m, where system size is mxn */
     49:   b  = ksp->vec_rhs; /* Right-hand side vector */
     50:   r  = cgls->vwork_m[0];
     51:   q  = cgls->vwork_m[1];

     53:   /* Minimization with the CGLS method */
     54:   ksp->its = 0;
     55:   ksp->rnorm = 0;
     56:   MatMult(A,x,r);
     57:   VecAYPX(r,-1,b);         /* r_0 = b - A * x_0  */
     58:   MatMultTranspose(A,r,p); /* p_0 = A^T * r_0    */
     59:   VecCopy(p,ss);           /* s_0 = p_0          */
     60:   VecNorm(ss,NORM_2,&gamma);
     61:   KSPCheckNorm(ksp,gamma);
     62:   if (ksp->normtype != KSP_NORM_NONE) ksp->rnorm = gamma;
     63:   (*ksp->converged)(ksp,ksp->its,ksp->rnorm,&ksp->reason,ksp->cnvP);
     64:   if (ksp->reason) return(0);
     65:   gamma = gamma*gamma;                          /* gamma = norm2(s)^2 */

     67:   do {
     68:     MatMult(A,p,q);           /* q = A * p               */
     69:     VecNorm(q,NORM_2,&alpha);
     70:     KSPCheckNorm(ksp,alpha);
     71:     alpha = alpha*alpha;                           /* alpha = norm2(q)^2      */
     72:     alpha = gamma / alpha;                         /* alpha = gamma / alpha   */
     73:     VecAXPY(x,alpha,p);       /* x += alpha * p          */
     74:     VecAXPY(r,-alpha,q);      /* r -= alpha * q          */
     75:     MatMultTranspose(A,r,ss); /* ss = A^T * r            */
     76:     oldgamma = gamma;                              /* oldgamma = gamma        */
     77:     VecNorm(ss,NORM_2,&gamma);
     78:     KSPCheckNorm(ksp,gamma);
     79:     ksp->its++;
     80:     if (ksp->normtype != KSP_NORM_NONE) ksp->rnorm = gamma;
     81:     KSPMonitor(ksp,ksp->its,ksp->rnorm);
     82:     (*ksp->converged)(ksp,ksp->its,ksp->rnorm,&ksp->reason,ksp->cnvP);
     83:     if (ksp->reason) return(0);
     84:     gamma = gamma*gamma;                           /* gamma = norm2(s)^2      */
     85:     beta = gamma/oldgamma;                         /* beta = gamma / oldgamma */
     86:     VecAYPX(p,beta,ss);       /* p = s + beta * p        */
     87:   } while (ksp->its<ksp->max_it);

     89:   if (ksp->its >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS;
     90:   return(0);
     91: }

     93: static PetscErrorCode KSPDestroy_CGLS(KSP ksp)
     94: {
     95:   KSP_CGLS       *cgls = (KSP_CGLS*)ksp->data;

     99:   /* Free work vectors */
    100:   if (cgls->vwork_n) {
    101:     VecDestroyVecs(cgls->nwork_n,&cgls->vwork_n);
    102:   }
    103:   if (cgls->vwork_m) {
    104:     VecDestroyVecs(cgls->nwork_m,&cgls->vwork_m);
    105:   }
    106:   PetscFree(ksp->data);
    107:   return(0);
    108: }

    110: /*MC
    111:      KSPCGLS - Conjugate Gradient method for Least-Squares problems

    113:    Level: beginner

    115:    Supports non-square (rectangular) matrices.

    117:    Notes:
    118:     This does not use the preconditioner, so one should probably use KSPLSQR instead.

    120: .seealso:  KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP,
    121:            KSPCGSetType(), KSPCGUseSingleReduction(), KSPPIPECG, KSPGROPPCG

    123: M*/
    124: PETSC_EXTERN PetscErrorCode KSPCreate_CGLS(KSP ksp)
    125: {
    127:   KSP_CGLS       *cgls;

    130:   PetscNewLog(ksp,&cgls);
    131:   ksp->data                = (void*)cgls;
    132:   KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,3);
    133:   KSPSetSupportedNorm(ksp,KSP_NORM_NONE,PC_LEFT,1);
    134:   ksp->ops->setup          = KSPSetUp_CGLS;
    135:   ksp->ops->solve          = KSPSolve_CGLS;
    136:   ksp->ops->destroy        = KSPDestroy_CGLS;
    137:   ksp->ops->buildsolution  = KSPBuildSolutionDefault;
    138:   ksp->ops->buildresidual  = KSPBuildResidualDefault;
    139:   ksp->ops->setfromoptions = NULL;
    140:   ksp->ops->view           = NULL;
    141: #if defined(PETSC_USE_COMPLEX)
    142:   SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"This is not supported for complex numbers");
    143: #else
    144:   return(0);
    145: #endif
    146: }