Actual source code: cr.c

  1: /*$Id: cr.c,v 1.64 2001/08/07 03:03:49 balay Exp $*/

  3: /*                       
  4:            This implements Preconditioned Conjugate Residuals.       
  5: */
 6:  #include src/sles/ksp/kspimpl.h

  8: #undef __FUNCT__  
 10: static int KSPSetUp_CR(KSP ksp)
 11: {

 15:   if (ksp->pc_side == PC_RIGHT) {SETERRQ(2,"no right preconditioning for KSPCR");}
 16:   else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(2,"no symmetric preconditioning for KSPCR");}
 17:   KSPDefaultGetWork(ksp,6);
 18:   return(0);
 19: }

 21: #undef __FUNCT__  
 23: static int  KSPSolve_CR(KSP ksp,int *its)
 24: {
 25:   int          i = 0, maxit, ierr;
 26:   MatStructure pflag;
 27:   PetscReal    dp;
 28:   PetscScalar  ai, bi;
 29:   PetscScalar  apq,btop, bbot, mone = -1.0;
 30:   Vec          X,B,R,RT,P,AP,ART,Q;
 31:   Mat          Amat, Pmat;


 35:   maxit   = ksp->max_it;
 36:   X       = ksp->vec_sol;
 37:   B       = ksp->vec_rhs;
 38:   R       = ksp->work[0];
 39:   RT      = ksp->work[1];
 40:   P       = ksp->work[2];
 41:   AP      = ksp->work[3];
 42:   ART     = ksp->work[4];
 43:   Q       = ksp->work[5];

 45:   /* R is the true residual norm, RT is the preconditioned residual norm */
 46:   PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
 47:   if (!ksp->guess_zero) {
 48:     KSP_MatMult(ksp,Amat,X,R);     /*   R <- A*X           */
 49:     VecAYPX(&mone,B,R);            /*   R <- B-R == B-A*X  */
 50:   } else {
 51:     VecCopy(B,R);                  /*   R <- B (X is 0)    */
 52:   }
 53:   KSP_PCApply(ksp,ksp->B,R,P);     /*   P   <- B*R         */
 54:   KSP_MatMult(ksp,Amat,P,AP);      /*   AP  <- A*P         */
 55:   VecCopy(P,RT);                   /*   RT  <- P           */
 56:   VecCopy(AP,ART);                 /*   ART <- AP          */
 57:   ierr   = VecDot(RT,ART,&btop);          /*   (RT,ART)           */
 58:   if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
 59:     VecNorm(RT,NORM_2,&dp);        /*   dp <- RT'*RT       */
 60:   } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
 61:     VecNorm(R,NORM_2,&dp);         /*   dp <- R'*R         */
 62:   } else if (ksp->normtype == KSP_NATURAL_NORM) {
 63:     dp = sqrt(PetscAbsScalar(btop));                    /* dp = sqrt(R,AR)      */
 64:   }
 65:   (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
 66:   if (ksp->reason) {*its = 0; return(0);}
 67:   KSPMonitor(ksp,0,dp);
 68:   PetscObjectTakeAccess(ksp);
 69:   ksp->its = 0;
 70:   ksp->rnorm              = dp;
 71:   PetscObjectGrantAccess(ksp);
 72:   KSPLogResidualHistory(ksp,dp);

 74:   for ( i=0; i<maxit; i++) {
 75:     ierr   = KSP_PCApply(ksp,ksp->B,AP,Q);/*   Q <- B* AP          */
 76:                                                         /* Step 3                */

 78:     ierr   = VecDot(AP,Q,&apq);
 79:     ai = btop/apq;                                      /* ai = (RT,ART)/(AP,Q)  */

 81:     ierr   = VecAXPY(&ai,P,X);            /*   X   <- X + ai*P     */
 82:     ai     = -ai;
 83:     ierr   = VecAXPY(&ai,Q,RT);           /*   RT  <- RT - ai*Q    */
 84:     ierr   = KSP_MatMult(ksp,Amat,RT,ART);/*   ART <-   A*RT       */
 85:     bbot = btop;
 86:     ierr   = VecDot(RT,ART,&btop);

 88:     if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
 89:       VecNorm(RT,NORM_2,&dp);      /*   dp <- || RT ||      */
 90:     } else if (ksp->normtype == KSP_NATURAL_NORM) {
 91:       dp = sqrt(PetscAbsScalar(btop));                  /* dp = sqrt(R,AR)       */
 92:     } else if (ksp->normtype == KSP_NO_NORM) {
 93:       dp = 0.0;
 94:     } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
 95:       VecAXPY(&ai,AP,R);           /*   R   <- R - ai*AP    */
 96:       VecNorm(R,NORM_2,&dp);       /*   dp <- R'*R          */
 97:     } else {
 98:       SETERRQ1(1,"KSPNormType of %d not supported",(int)ksp->normtype);
 99:     }

101:     PetscObjectTakeAccess(ksp);
102:     ksp->its++;
103:     ksp->rnorm = dp;
104:     PetscObjectGrantAccess(ksp);

106:     KSPLogResidualHistory(ksp,dp);
107:     KSPMonitor(ksp,i+1,dp);
108:     (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
109:     if (ksp->reason) break;

111:     bi = btop/bbot;
112:     VecAYPX(&bi,RT,P);              /*   P <- RT + Bi P     */
113:     VecAYPX(&bi,ART,AP);            /*   AP <- ART + Bi AP  */
114:   }
115:   if (i == maxit) {
116:     ksp->reason =  KSP_DIVERGED_ITS;
117:   }
118:   *its = ksp->its;
119:   return(0);
120: }


123: EXTERN_C_BEGIN
124: #undef __FUNCT__  
126: int KSPCreate_CR(KSP ksp)
127: {
129:   ksp->pc_side                   = PC_LEFT;
130:   ksp->ops->setup                = KSPSetUp_CR;
131:   ksp->ops->solve                = KSPSolve_CR;
132:   ksp->ops->destroy              = KSPDefaultDestroy;
133:   ksp->ops->buildsolution        = KSPDefaultBuildSolution;
134:   ksp->ops->buildresidual        = KSPDefaultBuildResidual;
135:   ksp->ops->setfromoptions       = 0;
136:   ksp->ops->view                 = 0;
137:   return(0);
138: }
139: EXTERN_C_END