Actual source code: cheby.c

  1: /*$Id: cheby.c,v 1.93 2001/04/10 19:36:33 bsmith 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"                    /*I "petscksp.h" I*/
  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 (**)())&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:   Scalar           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       pres,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;
 76:   pres     = ksp->use_pres;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

198:   ksp->data                      = (void*)chebychevP;
199:   ksp->pc_side                   = PC_LEFT;
200:   ksp->calc_res                  = PETSC_TRUE;

202:   chebychevP->emin               = 1.e-2;
203:   chebychevP->emax               = 1.e+2;

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

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