Actual source code: cr.c

  1: #define PETSCKSP_DLL

 3:  #include private/kspimpl.h

  7: static PetscErrorCode KSPSetUp_CR(KSP ksp)
  8: {

 12:   if (ksp->pc_side == PC_RIGHT) {SETERRQ(PETSC_ERR_SUP,"no right preconditioning for KSPCR");}
 13:   else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(PETSC_ERR_SUP,"no symmetric preconditioning for KSPCR");}
 14:   KSPDefaultGetWork(ksp,6);
 15:   return(0);
 16: }

 20: static PetscErrorCode  KSPSolve_CR(KSP ksp)
 21: {
 23:   PetscInt       i = 0;
 24:   MatStructure   pflag;
 25:   PetscReal      dp;
 26:   PetscScalar    ai, bi;
 27:   PetscScalar    apq,btop, bbot;
 28:   Vec            X,B,R,RT,P,AP,ART,Q;
 29:   Mat            Amat, Pmat;

 32:   X       = ksp->vec_sol;
 33:   B       = ksp->vec_rhs;
 34:   R       = ksp->work[0];
 35:   RT      = ksp->work[1];
 36:   P       = ksp->work[2];
 37:   AP      = ksp->work[3];
 38:   ART     = ksp->work[4];
 39:   Q       = ksp->work[5];

 41:   /* R is the true residual norm, RT is the preconditioned residual norm */
 42:   PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
 43:   if (!ksp->guess_zero) {
 44:     KSP_MatMult(ksp,Amat,X,R);     /*   R <- A*X           */
 45:     VecAYPX(R,-1.0,B);            /*   R <- B-R == B-A*X  */
 46:   } else {
 47:     VecCopy(B,R);                  /*   R <- B (X is 0)    */
 48:   }
 49:   KSP_PCApply(ksp,R,P);     /*   P   <- B*R         */
 50:   KSP_MatMult(ksp,Amat,P,AP);      /*   AP  <- A*P         */
 51:   VecCopy(P,RT);                   /*   RT  <- P           */
 52:   VecCopy(AP,ART);                 /*   ART <- AP          */
 53:   VecDotBegin(RT,ART,&btop);          /*   (RT,ART)           */
 54: 
 55:   if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
 56:     VecNormBegin(RT,NORM_2,&dp);        /*   dp <- RT'*RT       */
 57:     VecDotEnd   (RT,ART,&btop) ;          /*   (RT,ART)           */
 58:     VecNormEnd  (RT,NORM_2,&dp);        /*   dp <- RT'*RT       */
 59:   } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
 60:     VecNormBegin(R,NORM_2,&dp);         /*   dp <- R'*R         */
 61:     VecDotEnd   (RT,ART,&btop);          /*   (RT,ART)           */
 62:     VecNormEnd  (R,NORM_2,&dp);        /*   dp <- RT'*RT       */
 63:   } else if (ksp->normtype == KSP_NORM_NATURAL) {
 64:     VecDotEnd   (RT,ART,&btop) ;          /*   (RT,ART)           */
 65:     dp = sqrt(PetscAbsScalar(btop));                    /* dp = sqrt(R,AR)      */
 66:   }
 67:   if (PetscAbsScalar(btop) < 0.0) {
 68:     ksp->reason = KSP_DIVERGED_INDEFINITE_MAT;
 69:     PetscInfo(ksp,"diverging due to indefinite or negative definite matrix\n");
 70:     return(0);
 71:   }

 73:   ksp->its = 0;
 74:   KSPMonitor(ksp,0,dp);
 75:   PetscObjectTakeAccess(ksp);
 76:   ksp->rnorm              = dp;
 77:   PetscObjectGrantAccess(ksp);
 78:   KSPLogResidualHistory(ksp,dp);
 79:   (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
 80:   if (ksp->reason) return(0);

 82:   i = 0;
 83:   do {
 84:     KSP_PCApply(ksp,AP,Q);/*   Q <- B* AP          */

 86:     VecDot(AP,Q,&apq);
 87:     if (PetscAbsScalar(apq) <= 0.0) {
 88:       ksp->reason = KSP_DIVERGED_INDEFINITE_PC;
 89:       PetscInfo(ksp,"KSPSolve_CR:diverging due to indefinite or negative definite PC\n");
 90:       break;
 91:     }
 92:     ai = btop/apq;                                      /* ai = (RT,ART)/(AP,Q)  */

 94:     VecAXPY(X,ai,P);            /*   X   <- X + ai*P     */
 95:     VecAXPY(RT,-ai,Q);           /*   RT  <- RT - ai*Q    */
 96:     KSP_MatMult(ksp,Amat,RT,ART);/*   ART <-   A*RT       */
 97:     bbot = btop;
 98:     VecDotBegin(RT,ART,&btop);

100:     if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
101:       VecNormBegin(RT,NORM_2,&dp);      /*   dp <- || RT ||      */
102:       VecDotEnd   (RT,ART,&btop) ;
103:       VecNormEnd  (RT,NORM_2,&dp);      /*   dp <- || RT ||      */
104:     } else if (ksp->normtype == KSP_NORM_NATURAL) {
105:       VecDotEnd(RT,ART,&btop);
106:       dp = sqrt(PetscAbsScalar(btop));                  /* dp = sqrt(R,AR)       */
107:     } else if (ksp->normtype == KSP_NORM_NO) {
108:       VecDotEnd(RT,ART,&btop);
109:       dp = 0.0;
110:     } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
111:       VecAXPY(R,ai,AP);           /*   R   <- R - ai*AP    */
112:       VecNormBegin(R,NORM_2,&dp);       /*   dp <- R'*R          */
113:       VecDotEnd   (RT,ART,&btop);
114:       VecNormEnd  (R,NORM_2,&dp);       /*   dp <- R'*R          */
115:     } else {
116:       SETERRQ1(PETSC_ERR_SUP,"KSPNormType of %d not supported",(int)ksp->normtype);
117:     }
118:     if (PetscAbsScalar(btop) < 0.0) {
119:       ksp->reason = KSP_DIVERGED_INDEFINITE_MAT;
120:       PetscInfo(ksp,"diverging due to indefinite or negative definite PC\n");
121:       break;
122:     }

124:     PetscObjectTakeAccess(ksp);
125:     ksp->its++;
126:     ksp->rnorm = dp;
127:     PetscObjectGrantAccess(ksp);

129:     KSPLogResidualHistory(ksp,dp);
130:     KSPMonitor(ksp,i+1,dp);
131:     (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
132:     if (ksp->reason) break;

134:     bi = btop/bbot;
135:     VecAYPX(P,bi,RT);              /*   P <- RT + Bi P     */
136:     VecAYPX(AP,bi,ART);            /*   AP <- ART + Bi AP  */
137:     i++;
138:   } while (i<ksp->max_it);
139:   if (i >= ksp->max_it) {
140:     ksp->reason =  KSP_DIVERGED_ITS;
141:   }
142:   return(0);
143: }


146: /*MC
147:      KSPCR - This code implements the (preconditioned) conjugate residuals method

149:    Options Database Keys:
150: .   see KSPSolve()

152:    Level: beginner

154:    Notes: The operator and the preconditioner must be symmetric for this method. The 
155:           preconditioner must be POSITIVE-DEFINITE and the operator POSITIVE-SEMIDEFINITE


158:    References:
159:    Methods of Conjugate Gradients for Solving Linear Systems, Magnus R. Hestenes and Eduard Stiefel,
160:    Journal of Research of the National Bureau of Standards Vol. 49, No. 6, December 1952 Research Paper 2379
161:    pp. 409--436.


164: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPCG
165: M*/
169: PetscErrorCode  KSPCreate_CR(KSP ksp)
170: {
172:   ksp->pc_side                   = PC_LEFT;
173:   ksp->ops->setup                = KSPSetUp_CR;
174:   ksp->ops->solve                = KSPSolve_CR;
175:   ksp->ops->destroy              = KSPDefaultDestroy;
176:   ksp->ops->buildsolution        = KSPDefaultBuildSolution;
177:   ksp->ops->buildresidual        = KSPDefaultBuildResidual;
178:   ksp->ops->setfromoptions       = 0;
179:   ksp->ops->view                 = 0;
180:   return(0);
181: }