Actual source code: cheby.c

  1: /*$Id: cheby.c,v 1.94 2001/08/07 03:03:53 balay Exp $*/
  2: /*
  3:     This is a first attempt at a Chebychev routine, it is not 
  4:     necessarily well optimized.
  5: */
 6:  #include src/sles/ksp/kspimpl.h
 7:  #include src/sles/ksp/impls/cheby/chebctx.h

  9: int KSPSetUp_Chebychev(KSP ksp)
 10: {

 14:   if (ksp->pc_side == PC_SYMMETRIC) SETERRQ(2,"no symmetric preconditioning for KSPCHEBYCHEV");
 15:   KSPDefaultGetWork(ksp,3);
 16:   return(0);
 17: }

 19: EXTERN_C_BEGIN
 20: int KSPChebychevSetEigenvalues_Chebychev(KSP ksp,PetscReal emax,PetscReal emin)
 21: {
 22:   KSP_Chebychev *chebychevP = (KSP_Chebychev*)ksp->data;

 25:   chebychevP->emax = emax;
 26:   chebychevP->emin = emin;
 27:   return(0);
 28: }
 29: EXTERN_C_END

 31: /*@
 32:    KSPChebychevSetEigenvalues - Sets estimates for the extreme eigenvalues
 33:    of the preconditioned problem.

 35:    Collective on KSP

 37:    Input Parameters:
 38: +  ksp - the Krylov space context
 39: -  emax, emin - the eigenvalue estimates

 41:    Level: intermediate

 43: .keywords: KSP, Chebyshev, set, eigenvalues
 44: @*/
 45: int KSPChebychevSetEigenvalues(KSP ksp,PetscReal emax,PetscReal emin)
 46: {
 47:   int ierr,(*f)(KSP,PetscReal,PetscReal);

 51:   PetscObjectQueryFunction((PetscObject)ksp,"KSPChebychevSetEigenvalues_C",(void (**)(void))&f);
 52:   if (f) {
 53:     (*f)(ksp,emax,emin);
 54:   }
 55:   return(0);
 56: }

 58: int KSPSolve_Chebychev(KSP ksp,int *its)
 59: {
 60:   int              k,kp1,km1,maxit,ktmp,i,ierr;
 61:   PetscScalar      alpha,omegaprod,mu,omega,Gamma,c[3],scale,mone = -1.0,tmp;
 62:   PetscReal        rnorm;
 63:   Vec              x,b,p[3],r;
 64:   KSP_Chebychev    *chebychevP = (KSP_Chebychev*)ksp->data;
 65:   Mat              Amat,Pmat;
 66:   MatStructure     pflag;
 67:   PetscTruth       diagonalscale;

 70:   ierr    = PCDiagonalScale(ksp->B,&diagonalscale);
 71:   if (diagonalscale) SETERRQ1(1,"Krylov method %s does not support diagonal scaling",ksp->type_name);

 73:   ksp->its = 0;
 74:   ierr     = PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
 75:   maxit    = ksp->max_it;

 77:   /* These three point to the three active solutions, we
 78:      rotate these three at each solution update */
 79:   km1    = 0; k = 1; kp1 = 2;
 80:   x      = ksp->vec_sol;
 81:   b      = ksp->vec_rhs;
 82:   p[km1] = x;
 83:   p[k]   = ksp->work[0];
 84:   p[kp1] = ksp->work[1];
 85:   r      = ksp->work[2];

 87:   /* use scale*B as our preconditioner */
 88:   scale  = 2.0/(chebychevP->emax + chebychevP->emin);

 90:   /*   -alpha <=  scale*lambda(B^{-1}A) <= alpha   */
 91:   alpha  = 1.0 - scale*(chebychevP->emin); ;
 92:   Gamma  = 1.0;
 93:   mu     = 1.0/alpha;
 94:   omegaprod = 2.0/alpha;

 96:   c[km1] = 1.0;
 97:   c[k]   = mu;

 99:   if (!ksp->guess_zero) {
100:     KSP_MatMult(ksp,Amat,x,r);     /*  r = b - Ax     */
101:     VecAYPX(&mone,b,r);
102:   } else {
103:     VecCopy(b,r);
104:   }
105: 
106:   KSP_PCApply(ksp,ksp->B,r,p[k]);  /* p[k] = scale B^{-1}r + x */
107:   VecAYPX(&scale,x,p[k]);

109:   for (i=0; i<maxit; i++) {
110:     PetscObjectTakeAccess(ksp);
111:     ksp->its++;
112:     PetscObjectGrantAccess(ksp);
113:     c[kp1] = 2.0*mu*c[k] - c[km1];
114:     omega = omegaprod*c[k]/c[kp1];

116:     KSP_MatMult(ksp,Amat,p[k],r);                 /*  r = b - Ap[k]    */
117:     VecAYPX(&mone,b,r);
118:     KSP_PCApply(ksp,ksp->B,r,p[kp1]);             /*  p[kp1] = B^{-1}z  */

120:     /* calculate residual norm if requested */
121:     if (ksp->normtype != KSP_NO_NORM) {
122:       if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {VecNorm(r,NORM_2,&rnorm);}
123:       else {VecNorm(p[kp1],NORM_2,&rnorm);}
124:       PetscObjectTakeAccess(ksp);
125:       ksp->rnorm                              = rnorm;
126:       PetscObjectGrantAccess(ksp);
127:       ksp->vec_sol = p[k];
128:       KSPLogResidualHistory(ksp,rnorm);
129:       KSPMonitor(ksp,i,rnorm);
130:       (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
131:       if (ksp->reason) break;
132:     }

134:     /* y^{k+1} = omega(y^{k} - y^{k-1} + Gamma*r^{k}) + y^{k-1} */
135:     tmp  = omega*Gamma*scale;
136:     VecScale(&tmp,p[kp1]);
137:     tmp  = 1.0-omega; VecAXPY(&tmp,p[km1],p[kp1]);
138:     VecAXPY(&omega,p[k],p[kp1]);

140:     ktmp = km1;
141:     km1  = k;
142:     k    = kp1;
143:     kp1  = ktmp;
144:   }
145:   if (!ksp->reason && ksp->normtype != KSP_NO_NORM) {
146:     ksp->reason = KSP_DIVERGED_ITS;
147:     KSP_MatMult(ksp,Amat,p[k],r);       /*  r = b - Ap[k]    */
148:     VecAYPX(&mone,b,r);
149:     if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {VecNorm(r,NORM_2,&rnorm);}
150:     else {
151:       KSP_PCApply(ksp,ksp->B,r,p[kp1]); /* p[kp1] = B^{-1}z */
152:       VecNorm(p[kp1],NORM_2,&rnorm);
153:     }
154:     PetscObjectTakeAccess(ksp);
155:     ksp->rnorm                              = rnorm;
156:     PetscObjectGrantAccess(ksp);
157:     ksp->vec_sol = p[k];
158:     KSPLogResidualHistory(ksp,rnorm);
159:     KSPMonitor(ksp,i,rnorm);
160:   }

162:   /* make sure solution is in vector x */
163:   ksp->vec_sol = x;
164:   if (k) {
165:     VecCopy(p[k],x);
166:   }
167:   *its = ksp->its;
168:   return(0);
169: }

171: int KSPView_Chebychev(KSP ksp,PetscViewer viewer)
172: {
173:   KSP_Chebychev *cheb = (KSP_Chebychev*)ksp->data;
174:   int           ierr;
175:   PetscTruth    isascii;

178:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
179:   if (isascii) {
180:     PetscViewerASCIIPrintf(viewer,"  Chebychev: eigenvalue estimates:  min = %g, max = %gn",cheb->emin,cheb->emax);
181:   } else {
182:     SETERRQ1(1,"Viewer type %s not supported for KSP Chebychev",((PetscObject)viewer)->type_name);
183:   }
184:   return(0);
185: }

187: EXTERN_C_BEGIN
188: int KSPCreate_Chebychev(KSP ksp)
189: {
190:   int           ierr;
191:   KSP_Chebychev *chebychevP;

194:   PetscNew(KSP_Chebychev,&chebychevP);
195:   PetscLogObjectMemory(ksp,sizeof(KSP_Chebychev));

197:   ksp->data                      = (void*)chebychevP;
198:   ksp->pc_side                   = PC_LEFT;

200:   chebychevP->emin               = 1.e-2;
201:   chebychevP->emax               = 1.e+2;

203:   ksp->ops->setup                = KSPSetUp_Chebychev;
204:   ksp->ops->solve                = KSPSolve_Chebychev;
205:   ksp->ops->destroy              = KSPDefaultDestroy;
206:   ksp->ops->buildsolution        = KSPDefaultBuildSolution;
207:   ksp->ops->buildresidual        = KSPDefaultBuildResidual;
208:   ksp->ops->setfromoptions       = 0;
209:   ksp->ops->view                 = KSPView_Chebychev;

211:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebychevSetEigenvalues_C",
212:                                     "KSPChebychevSetEigenvalues_Chebychev",
213:                                     KSPChebychevSetEigenvalues_Chebychev);
214:   return(0);
215: }
216: EXTERN_C_END