Actual source code: bicg.c

  1: #define PETSCKSP_DLL

 3:  #include private/kspimpl.h

  7: PetscErrorCode KSPSetUp_BiCG(KSP ksp)
  8: {

 12:   /* check user parameters and functions */
 13:   if (ksp->pc_side == PC_RIGHT) {
 14:     SETERRQ(PETSC_ERR_SUP,"no right preconditioning for KSPBiCG");
 15:   } else if (ksp->pc_side == PC_SYMMETRIC) {
 16:     SETERRQ(PETSC_ERR_SUP,"no symmetric preconditioning for KSPBiCG");
 17:   }

 19:   /* get work vectors from user code */
 20:   KSPDefaultGetWork(ksp,6);
 21:   return(0);
 22: }

 26: PetscErrorCode  KSPSolve_BiCG(KSP ksp)
 27: {
 29:   PetscInt       i;
 30:   PetscTruth     diagonalscale;
 31:   PetscScalar    dpi,a=1.0,beta,betaold=1.0,b,ma;
 32:   PetscReal      dp;
 33:   Vec            X,B,Zl,Zr,Rl,Rr,Pl,Pr;
 34:   Mat            Amat,Pmat;
 35:   MatStructure   pflag;

 38:   if (ksp->normtype == KSP_NORM_NATURAL) SETERRQ(PETSC_ERR_SUP,"Cannot use natural residual norm with KSPIBCGS");

 40:   PCDiagonalScale(ksp->pc,&diagonalscale);
 41:   if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);

 43:   X       = ksp->vec_sol;
 44:   B       = ksp->vec_rhs;
 45:   Rl      = ksp->work[0];
 46:   Zl      = ksp->work[1];
 47:   Pl      = ksp->work[2];
 48:   Rr      = ksp->work[3];
 49:   Zr      = ksp->work[4];
 50:   Pr      = ksp->work[5];

 52:   PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);

 54:   if (!ksp->guess_zero) {
 55:     KSP_MatMult(ksp,Amat,X,Rr);      /*   r <- b - Ax       */
 56:     VecAYPX(Rr,-1.0,B);
 57:   } else {
 58:     VecCopy(B,Rr);           /*     r <- b (x is 0) */
 59:   }
 60:   VecCopy(Rr,Rl);
 61:   KSP_PCApply(ksp,Rr,Zr);     /*     z <- Br         */
 62:   VecConjugate(Rl);
 63:   KSP_PCApplyTranspose(ksp,Rl,Zl);
 64:   VecConjugate(Rl);
 65:   VecConjugate(Zl);
 66:   if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
 67:     VecNorm(Zr,NORM_2,&dp);  /*    dp <- z'*z       */
 68:   } else {
 69:     VecNorm(Rr,NORM_2,&dp);  /*    dp <- r'*r       */
 70:   }
 71:   KSPMonitor(ksp,0,dp);
 72:   PetscObjectTakeAccess(ksp);
 73:   ksp->its   = 0;
 74:   ksp->rnorm = dp;
 75:   PetscObjectGrantAccess(ksp);
 76:   KSPLogResidualHistory(ksp,dp);
 77:   (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
 78:   if (ksp->reason) return(0);

 80:   i = 0;
 81:   do {
 82:      VecDot(Zr,Rl,&beta);       /*     beta <- r'z     */
 83:      if (!i) {
 84:        if (beta == 0.0) {
 85:          ksp->reason = KSP_DIVERGED_BREAKDOWN_BICG;
 86:          return(0);
 87:        }
 88:        VecCopy(Zr,Pr);       /*     p <- z          */
 89:        VecCopy(Zl,Pl);
 90:      } else {
 91:        b = beta/betaold;
 92:        VecAYPX(Pr,b,Zr);  /*     p <- z + b* p   */
 93:        b = PetscConj(b);
 94:        VecAYPX(Pl,b,Zl);
 95:      }
 96:      betaold = beta;
 97:      KSP_MatMult(ksp,Amat,Pr,Zr);    /*     z <- Kp         */
 98:      VecConjugate(Pl);
 99:      KSP_MatMultTranspose(ksp,Amat,Pl,Zl);
100:      VecConjugate(Pl);
101:      VecConjugate(Zl);
102:      VecDot(Zr,Pl,&dpi);               /*     dpi <- z'p      */
103:      a = beta/dpi;                                 /*     a = beta/p'z    */
104:      VecAXPY(X,a,Pr);       /*     x <- x + ap     */
105:      ma = -a;
106:      VecAXPY(Rr,ma,Zr);CHKERRQ(ierr)
107:      ma = PetscConj(ma);
108:      VecAXPY(Rl,ma,Zl);
109:      if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
110:        KSP_PCApply(ksp,Rr,Zr);  /*     z <- Br         */
111:        VecConjugate(Rl);
112:        KSP_PCApplyTranspose(ksp,Rl,Zl);
113:        VecConjugate(Rl);
114:        VecConjugate(Zl);
115:        VecNorm(Zr,NORM_2,&dp);  /*    dp <- z'*z       */
116:      } else {
117:        VecNorm(Rr,NORM_2,&dp);  /*    dp <- r'*r       */
118:      }
119:      PetscObjectTakeAccess(ksp);
120:      ksp->its   = i+1;
121:      ksp->rnorm = dp;
122:      PetscObjectGrantAccess(ksp);
123:      KSPLogResidualHistory(ksp,dp);
124:      KSPMonitor(ksp,i+1,dp);
125:      (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
126:      if (ksp->reason) break;
127:      if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
128:        KSP_PCApply(ksp,Rr,Zr);  /* z <- Br  */
129:        VecConjugate(Rl);
130:        KSP_PCApplyTranspose(ksp,Rl,Zl);
131:        VecConjugate(Rl);
132:        VecConjugate(Zl);
133:      }
134:      i++;
135:   } while (i<ksp->max_it);
136:   if (i >= ksp->max_it) {
137:     ksp->reason = KSP_DIVERGED_ITS;
138:   }
139:   return(0);
140: }

144: PetscErrorCode KSPDestroy_BiCG(KSP ksp)
145: {

149:   KSPDefaultFreeWork(ksp);
150:   return(0);
151: }

153: /*MC
154:      KSPBICG - Implements the Biconjugate gradient method (similar to running the conjugate
155:          gradient on the normal equations).

157:    Options Database Keys:
158: .   see KSPSolve()

160:    Level: beginner

162:    Note: this method requires that one be apply to apply the transpose of the preconditioner and operator
163:          as well as the operator and preconditioner.

165:          See KSPCGNE for code that EXACTLY runs the preconditioned conjugate gradient method on the 
166:          normal equations

168: .seealso:  KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPBCGS, KSPCGNE

170: M*/
174: PetscErrorCode  KSPCreate_BiCG(KSP ksp)
175: {
177:   ksp->data                      = (void*)0;
178:   ksp->pc_side                   = PC_LEFT;
179:   ksp->ops->setup                = KSPSetUp_BiCG;
180:   ksp->ops->solve                = KSPSolve_BiCG;
181:   ksp->ops->destroy              = KSPDestroy_BiCG;
182:   ksp->ops->view                 = 0;
183:   ksp->ops->setfromoptions       = 0;
184:   ksp->ops->buildsolution        = KSPDefaultBuildSolution;
185:   ksp->ops->buildresidual        = KSPDefaultBuildResidual;

187:   return(0);
188: }