Actual source code: cheby.c

petsc-3.3-p5 2012-12-01
  2: #include <petsc-private/kspimpl.h>                    /*I "petscksp.h" I*/
  3: #include <../src/ksp/ksp/impls/cheby/chebyshevimpl.h>

  7: PetscErrorCode KSPReset_Chebyshev(KSP ksp)
  8: {
  9:   KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;

 13:   KSPReset(cheb->kspest);
 14:   return(0);
 15: }

 19: PetscErrorCode KSPSetUp_Chebyshev(KSP ksp)
 20: {
 21:   KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;

 25:   KSPDefaultGetWork(ksp,3);
 26:   if (cheb->emin == 0. || cheb->emax == 0.) { /* We need to estimate eigenvalues */
 27:     KSPChebyshevSetEstimateEigenvalues(ksp,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);
 28:   }
 29:   return(0);
 30: }

 35: {
 36:   KSP_Chebyshev *chebyshevP = (KSP_Chebyshev*)ksp->data;

 40:   if (emax <= emin) SETERRQ2(((PetscObject)ksp)->comm,PETSC_ERR_ARG_INCOMP,"Maximum eigenvalue must be larger than minimum: max %g min %G",emax,emin);
 41:   if (emax*emin <= 0.0) SETERRQ2(((PetscObject)ksp)->comm,PETSC_ERR_ARG_INCOMP,"Both eigenvalues must be of the same sign: max %G min %G",emax,emin);
 42:   chebyshevP->emax = emax;
 43:   chebyshevP->emin = emin;
 44:   KSPChebyshevSetEstimateEigenvalues(ksp,0.,0.,0.,0.); /* Destroy any estimation setup */
 45:   return(0);
 46: }

 51: {
 52:   KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;

 56:   if (a != 0.0 || b != 0.0 || c != 0.0 || d != 0.0) {
 57:     if (!cheb->kspest) {
 58:       PetscBool nonzero;

 60:       KSPCreate(((PetscObject)ksp)->comm,&cheb->kspest);
 61:       PetscObjectIncrementTabLevel((PetscObject)cheb->kspest,(PetscObject)ksp,1);

 63:       KSPGetPC(cheb->kspest,&cheb->pcnone);
 64:       PetscObjectReference((PetscObject)cheb->pcnone);
 65:       PCSetType(cheb->pcnone,PCNONE);
 66:       KSPSetPC(cheb->kspest,ksp->pc);

 68:       KSPGetInitialGuessNonzero(ksp,&nonzero);
 69:       KSPSetInitialGuessNonzero(cheb->kspest,nonzero);
 70:       KSPSetComputeSingularValues(cheb->kspest,PETSC_TRUE);

 72:       /* Estimate with a fixed number of iterations */
 73:       KSPSetConvergenceTest(cheb->kspest,KSPSkipConverged,0,0);
 74:       KSPSetNormType(cheb->kspest,KSP_NORM_NONE);
 75:       KSPSetTolerances(cheb->kspest,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,10);
 76:     }
 77:     if (a >= 0) cheb->tform[0] = a;
 78:     if (b >= 0) cheb->tform[1] = b;
 79:     if (c >= 0) cheb->tform[2] = c;
 80:     if (d >= 0) cheb->tform[3] = d;
 81:     cheb->estimate_current = PETSC_FALSE;
 82:   } else {
 83:     KSPDestroy(&cheb->kspest);
 84:     PCDestroy(&cheb->pcnone);
 85:   }
 86:   return(0);
 87: }

 92: {
 93:   KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;

 96:   cheb->estimate_current = PETSC_FALSE;
 97:   return(0);
 98: }

102: /*@
103:    KSPChebyshevSetEigenvalues - Sets estimates for the extreme eigenvalues
104:    of the preconditioned problem.

106:    Logically Collective on KSP

108:    Input Parameters:
109: +  ksp - the Krylov space context
110: -  emax, emin - the eigenvalue estimates

112:   Options Database:
113: .  -ksp_chebyshev_eigenvalues emin,emax

115:    Note: If you run with the Krylov method of KSPCG with the option -ksp_monitor_singular_value it will 
116:     for that given matrix and preconditioner an estimate of the extreme eigenvalues.

118:    Level: intermediate

120: .keywords: KSP, Chebyshev, set, eigenvalues
121: @*/
122: PetscErrorCode  KSPChebyshevSetEigenvalues(KSP ksp,PetscReal emax,PetscReal emin)
123: {

130:   PetscTryMethod(ksp,"KSPChebyshevSetEigenvalues_C",(KSP,PetscReal,PetscReal),(ksp,emax,emin));
131:   return(0);
132: }

136: /*@
137:    KSPChebyshevSetEstimateEigenvalues - Automatically estimate the eigenvalues to use for Chebyshev

139:    Logically Collective on KSP

141:    Input Parameters:
142: +  ksp - the Krylov space context
143: .  a - multiple of min eigenvalue estimate to use for min Chebyshev bound (or PETSC_DECIDE)
144: .  b - multiple of max eigenvalue estimate to use for min Chebyshev bound (or PETSC_DECIDE)
145: .  c - multiple of min eigenvalue estimate to use for max Chebyshev bound (or PETSC_DECIDE)
146: -  d - multiple of max eigenvalue estimate to use for max Chebyshev bound (or PETSC_DECIDE)

148:   Options Database:
149: .  -ksp_chebyshev_estimate_eigenvalues a,b,c,d

151:    Notes:
152:    The Chebyshev bounds are estimated using
153: .vb
154:    minbound = a*minest + b*maxest
155:    maxbound = c*minest + d*maxest
156: .ve
157:    The default configuration targets the upper part of the spectrum for use as a multigrid smoother, so only the maximum eigenvalue estimate is used.
158:    The minimum eigenvalue estimate obtained by Krylov iteration is typically not accurate until the method has converged.

160:    If 0.0 is passed for all transform arguments (a,b,c,d), eigenvalue estimation is disabled.

162:    The default transform is (0,0.1; 0,1.1) which targets the "upper" part of the spectrum, as desirable for use with multigrid.

164:    Level: intermediate

166: .keywords: KSP, Chebyshev, set, eigenvalues, PCMG
167: @*/
168: PetscErrorCode KSPChebyshevSetEstimateEigenvalues(KSP ksp,PetscReal a,PetscReal b,PetscReal c,PetscReal d)
169: {

178:   PetscTryMethod(ksp,"KSPChebyshevSetEstimateEigenvalues_C",(KSP,PetscReal,PetscReal,PetscReal,PetscReal),(ksp,a,b,c,d));
179:   return(0);
180: }

184: /*@
185:    KSPChebyshevSetNewMatrix - Indicates that the matrix has changed, causes eigenvalue estimates to be recomputed if appropriate.

187:    Logically Collective on KSP

189:    Input Parameter:
190: .  ksp - the Krylov space context

192:    Level: developer

194: .keywords: KSP, Chebyshev, set, eigenvalues

196: .seealso: KSPChebyshevSetEstimateEigenvalues()
197: @*/
198: PetscErrorCode KSPChebyshevSetNewMatrix(KSP ksp)
199: {

204:   PetscTryMethod(ksp,"KSPChebyshevSetNewMatrix_C",(KSP),(ksp));
205:   return(0);
206: }

210: PetscErrorCode KSPSetFromOptions_Chebyshev(KSP ksp)
211: {
212:   KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
214:   PetscInt       two = 2,four = 4;
215:   PetscReal      tform[4] = {PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE};
216:   PetscBool      flg;

219:   PetscOptionsHead("KSP Chebyshev Options");
220:   PetscOptionsRealArray("-ksp_chebyshev_eigenvalues","extreme eigenvalues","KSPChebyshevSetEigenvalues",&cheb->emin,&two,0);
221:   PetscOptionsRealArray("-ksp_chebyshev_estimate_eigenvalues","estimate eigenvalues using a Krylov method, then use this transform for Chebyshev eigenvalue bounds","KSPChebyshevSetEstimateEigenvalues",tform,&four,&flg);
222:   if (flg) {
223:     switch (four) {
224:     case 0:
225:       KSPChebyshevSetEstimateEigenvalues(ksp,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);
226:       break;
227:     case 2:                     /* Base everything on the max eigenvalues */
228:       KSPChebyshevSetEstimateEigenvalues(ksp,PETSC_DECIDE,tform[0],PETSC_DECIDE,tform[1]);
229:       break;
230:     case 4:                     /* Use the full 2x2 linear transformation */
231:       KSPChebyshevSetEstimateEigenvalues(ksp,tform[0],tform[1],tform[2],tform[3]);
232:       break;
233:     default: SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_ARG_INCOMP,"Must specify either 0, 2, or 4 parameters for eigenvalue estimation");
234:     }
235:   }

237:   /* 
238:    Use hybrid Chebyshev. 
239:    Ref: "A hybrid Chebyshev Krylov-subspace algorithm for solving nonsymmetric systems of linear equations", 
240:          Howard Elman and Y. Saad and P. E. Saylor, SIAM Journal on Scientific and Statistical Computing, 1986.
241:    */
242:   PetscOptionsBool("-ksp_chebyshev_hybrid","Use hybrid Chebyshev","",cheb->hybrid,&cheb->hybrid,PETSC_NULL);
243:   PetscOptionsInt("-ksp_chebyshev_hybrid_chebysteps","Number of Chebyshev steps in hybrid Chebyshev","",cheb->chebysteps,&cheb->chebysteps,PETSC_NULL);
244:   PetscOptionsInt("-ksp_chebyshev_hybrid_purification","Use purification in hybrid Chebyshev","",cheb->purification,&cheb->purification,PETSC_NULL);

246:   if (cheb->kspest) {
247:     /* Mask the PC so that PCSetFromOptions does not do anything */
248:     KSPSetPC(cheb->kspest,cheb->pcnone);
249:     KSPSetOptionsPrefix(cheb->kspest,((PetscObject)ksp)->prefix);
250:     KSPAppendOptionsPrefix(cheb->kspest,"est_");
251:     if (!((PetscObject)cheb->kspest)->type_name) {
252:       KSPSetType(cheb->kspest,KSPGMRES);
253:     }
254:     KSPSetFromOptions(cheb->kspest);
255:     KSPSetPC(cheb->kspest,ksp->pc);
256:   }
257:   PetscOptionsTail();
258:   return(0);
259: }

263: PetscErrorCode KSPSolve_Chebyshev(KSP ksp)
264: {
265:   KSP_Chebyshev  *cheb = (KSP_Chebyshev*)ksp->data;
267:   PetscInt       k,kp1,km1,maxit,ktmp,i;
268:   PetscScalar    alpha,omegaprod,mu,omega,Gamma,c[3],scale;
269:   PetscReal      rnorm = 0.0;
270:   Vec            sol_orig,b,p[3],r;
271:   Mat            Amat,Pmat;
272:   MatStructure   pflag;
273:   PetscBool      diagonalscale,hybrid=cheb->hybrid;
274:   PetscInt       purification=cheb->purification;

277:   PCGetDiagonalScale(ksp->pc,&diagonalscale);
278:   if (diagonalscale) SETERRQ1(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);

280:   if (cheb->kspest && !cheb->estimate_current) {
281:     PetscReal max,min;
282:     Vec       X;
283: 
284:     if (hybrid && purification){
285:       X = ksp->vec_sol;
286:     } else {
287:       X = ksp->work[0];
288:     }
289:     KSPSolve(cheb->kspest,ksp->vec_rhs,X);
290:     if (hybrid){
291:       cheb->its = 0; /* initialize Chebyshev iteration associated to kspest */
292:       KSPSetInitialGuessNonzero(cheb->kspest,PETSC_TRUE);
293:     } else {
294:       if (ksp->guess_zero) {
295:         VecZeroEntries(X);
296:       }
297:     }
298:     KSPComputeExtremeSingularValues(cheb->kspest,&max,&min);
299:     cheb->emin = cheb->tform[0]*min + cheb->tform[1]*max;
300:     cheb->emax = cheb->tform[2]*min + cheb->tform[3]*max;
301:     cheb->estimate_current = PETSC_TRUE;
302:   }

304:   ksp->its = 0;
305:   PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
306:   maxit    = ksp->max_it;

308:   /* These three point to the three active solutions, we
309:      rotate these three at each solution update */
310:   km1 = 0; k = 1; kp1 = 2;
311:   sol_orig = ksp->vec_sol; /* ksp->vec_sol will be asigned to rotating vector p[k], thus save its address */
312:   b       = ksp->vec_rhs;
313:   p[km1]  = sol_orig;
314:   p[k]    = ksp->work[0];
315:   p[kp1]  = ksp->work[1];
316:   r       = ksp->work[2];

318:   /* use scale*B as our preconditioner */
319:   scale  = 2.0/(cheb->emax + cheb->emin);

321:   /*   -alpha <=  scale*lambda(B^{-1}A) <= alpha   */
322:   alpha  = 1.0 - scale*(cheb->emin);
323:   Gamma  = 1.0;
324:   mu     = 1.0/alpha;
325:   omegaprod = 2.0/alpha;

327:   c[km1] = 1.0;
328:   c[k]   = mu;

330:   if (!ksp->guess_zero || (hybrid && cheb->its== 0)) {
331:     KSP_MatMult(ksp,Amat,p[km1],r);     /*  r = b - A*p[km1] */
332:     VecAYPX(r,-1.0,b);
333:   } else {
334:     VecCopy(b,r);
335:   }
336: 
337:   KSP_PCApply(ksp,r,p[k]);  /* p[k] = scale B^{-1}r + p[km1] */
338:   VecAYPX(p[k],scale,p[km1]);

340:   for (i=0; i<maxit; i++) {
341:     PetscObjectTakeAccess(ksp);
342:     if (hybrid && cheb->its && (cheb->its%cheb->chebysteps==0)){
343:       /* Adaptive step: update eigenvalue estimate - does not seem to improve convergence */
344:       PetscReal max,min;
345:       Vec       X = ksp->vec_sol; /* = previous p[k] */
346: 
347:       if (purification <= 1){ /* no purification here */
348:         X = p[km1]; /* a tmp vector, != ksp->vec_sol */
349:       }

351:       VecCopy(p[k],X); /* p[k] = previous p[kp1] */
352:       KSPSolve(cheb->kspest,ksp->vec_rhs,X);
353:       KSPComputeExtremeSingularValues(cheb->kspest,&max,&min);
354:       cheb->emin = cheb->tform[0]*min + cheb->tform[1]*max;
355:       cheb->emax = cheb->tform[2]*min + cheb->tform[3]*max;
356:       cheb->estimate_current = PETSC_TRUE;
357:       if (purification <= 1){ /* no purification here */
358:         X    = ksp->vec_sol;
359:         VecCopy(p[k],X);
360:       }

362:       b      = ksp->vec_rhs;
363:       p[km1] = X;
364:       scale  = 2.0/(cheb->emax + cheb->emin);
365:       alpha  = 1.0 - scale*(cheb->emin);
366:       mu     = 1.0/alpha;
367:       omegaprod = 2.0/alpha;
368: 
369:       c[km1] = 1.0;
370:       c[k]   = mu;
371:       KSP_MatMult(ksp,Amat,p[km1],r);     /*  r = b - A*p[km1]    */
372:       VecAYPX(r,-1.0,b);

374:       KSP_PCApply(ksp,r,p[k]);  /* p[k] = scale B^{-1}r + p[km1] */
375:       VecAYPX(p[k],scale,p[km1]);
376:     }

378:     ksp->its++;
379:     cheb->its++;
380:     PetscObjectGrantAccess(ksp);
381:     c[kp1] = 2.0*mu*c[k] - c[km1];
382:     omega = omegaprod*c[k]/c[kp1];

384:     KSP_MatMult(ksp,Amat,p[k],r);                 /*  r = b - Ap[k]    */
385:     VecAYPX(r,-1.0,b);
386:     KSP_PCApply(ksp,r,p[kp1]);             /*  p[kp1] = B^{-1}r  */

388:     /* calculate residual norm if requested */
389:     if (ksp->normtype != KSP_NORM_NONE || ksp->numbermonitors) {
390:       if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {VecNorm(r,NORM_2,&rnorm);}
391:       else {VecNorm(p[kp1],NORM_2,&rnorm);}
392:       PetscObjectTakeAccess(ksp);
393:       ksp->rnorm                              = rnorm;
394:       PetscObjectGrantAccess(ksp);
395:       ksp->vec_sol = p[k];
396:       KSPLogResidualHistory(ksp,rnorm);
397:       KSPMonitor(ksp,i,rnorm);
398:       (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
399:       if (ksp->reason) break;
400:     }

402:     /* y^{k+1} = omega(y^{k} - y^{k-1} + Gamma*r^{k}) + y^{k-1} */
403:     VecScale(p[kp1],omega*Gamma*scale);
404:     VecAXPY(p[kp1],1.0-omega,p[km1]);
405:     VecAXPY(p[kp1],omega,p[k]);

407:     ktmp = km1;
408:     km1  = k;
409:     k    = kp1;
410:     kp1  = ktmp;
411:   }
412:   if (!ksp->reason) {
413:     if (ksp->normtype != KSP_NORM_NONE) {
414:       KSP_MatMult(ksp,Amat,p[k],r);       /*  r = b - Ap[k]    */
415:       VecAYPX(r,-1.0,b);
416:       if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
417:         VecNorm(r,NORM_2,&rnorm);
418:       } else {
419:         KSP_PCApply(ksp,r,p[kp1]); /* p[kp1] = B^{-1}r */
420:         VecNorm(p[kp1],NORM_2,&rnorm);
421:       }
422:       PetscObjectTakeAccess(ksp);
423:       ksp->rnorm = rnorm;
424:       PetscObjectGrantAccess(ksp);
425:       ksp->vec_sol = p[k];
426:       KSPLogResidualHistory(ksp,rnorm);
427:       KSPMonitor(ksp,i,rnorm);
428:     }
429:     if (ksp->its >= ksp->max_it) {
430:       if (ksp->normtype != KSP_NORM_NONE) {
431:         (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
432:         if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS;
433:       } else {
434:         ksp->reason = KSP_CONVERGED_ITS;
435:       }
436:     }
437:   }

439:   /* make sure solution is in vector x */
440:   ksp->vec_sol = sol_orig;
441:   if (k) {
442:     VecCopy(p[k],sol_orig);
443:   }
444:   return(0);
445: }

449: PetscErrorCode KSPView_Chebyshev(KSP ksp,PetscViewer viewer)
450: {
451:   KSP_Chebyshev  *cheb = (KSP_Chebyshev*)ksp->data;
453:   PetscBool      iascii;

456:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
457:   if (iascii) {
458:     PetscViewerASCIIPrintf(viewer,"  Chebyshev: eigenvalue estimates:  min = %G, max = %G\n",cheb->emin,cheb->emax);
459:     if (cheb->kspest) {
460:       PetscViewerASCIIPrintf(viewer,"  Chebyshev: estimated using:  [%G %G; %G %G]\n",cheb->tform[0],cheb->tform[1],cheb->tform[2],cheb->tform[3]);
461:       if (cheb->hybrid){ /* display info about hybrid options being used */
462:         PetscViewerASCIIPrintf(viewer,"  Chebyshev: hybrid is used, chebysteps %D, purification %D\n",cheb->chebysteps,cheb->purification);
463:       }
464:       PetscViewerASCIIPushTab(viewer);
465:       KSPView(cheb->kspest,viewer);
466:       PetscViewerASCIIPopTab(viewer);
467:     }
468:   } else {
469:     SETERRQ1(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for KSP Chebyshev",((PetscObject)viewer)->type_name);
470:   }
471:   return(0);
472: }

476: PetscErrorCode KSPDestroy_Chebyshev(KSP ksp)
477: {
478:   KSP_Chebyshev  *cheb = (KSP_Chebyshev*)ksp->data;

482:   KSPDestroy(&cheb->kspest);
483:   PCDestroy(&cheb->pcnone);
484:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebyshevSetEigenvalues_C","",PETSC_NULL);
485:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebyshevSetEstimateEigenvalues_C","",PETSC_NULL);
486:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebyshevSetNewMatrix_C","",PETSC_NULL);
487:   KSPDefaultDestroy(ksp);
488:   return(0);
489: }

491: /*MC
492:      KSPCHEBYSHEV - The preconditioned Chebyshev iterative method

494:    Options Database Keys:
495: +   -ksp_chebyshev_eigenvalues <emin,emax> - set approximations to the smallest and largest eigenvalues
496:                   of the preconditioned operator. If these are accurate you will get much faster convergence.
497: -   -ksp_chebyshev_estimate_eigenvalues <a,b,c,d> - estimate eigenvalues using a Krylov method, then use this
498:                   transform for Chebyshev eigenvalue bounds (KSPChebyshevSetEstimateEigenvalues)


501:    Level: beginner

503:    Notes: The Chebyshev method requires both the matrix and preconditioner to 
504:           be symmetric positive (semi) definite.
505:           Only support for left preconditioning.

507:           Chebyshev is configured as a smoother by default, targetting the "upper" part of the spectrum.
508:           The user should call KSPChebyshevSetEigenvalues() if they have eigenvalue estimates.

510: .seealso:  KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP,
511:            KSPChebyshevSetEigenvalues(), KSPChebyshevSetEstimateEigenvalues(), KSPRICHARDSON, KSPCG, PCMG

513: M*/

518: {
520:   KSP_Chebyshev  *chebyshevP;

523:   PetscNewLog(ksp,KSP_Chebyshev,&chebyshevP);

525:   ksp->data                      = (void*)chebyshevP;
526:   KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);
527:   KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,1);

529:   chebyshevP->emin               = 0.;
530:   chebyshevP->emax               = 0.;

532:   chebyshevP->tform[0]           = 0.0;
533:   chebyshevP->tform[1]           = 0.1;
534:   chebyshevP->tform[2]           = 0;
535:   chebyshevP->tform[3]           = 1.1;

537:   chebyshevP->hybrid             = PETSC_FALSE;
538:   chebyshevP->chebysteps         = 20000;
539:   chebyshevP->its                = 0;
540:   chebyshevP->purification       = 0; /* no purification */

542:   ksp->ops->setup                = KSPSetUp_Chebyshev;
543:   ksp->ops->solve                = KSPSolve_Chebyshev;
544:   ksp->ops->destroy              = KSPDestroy_Chebyshev;
545:   ksp->ops->buildsolution        = KSPDefaultBuildSolution;
546:   ksp->ops->buildresidual        = KSPDefaultBuildResidual;
547:   ksp->ops->setfromoptions       = KSPSetFromOptions_Chebyshev;
548:   ksp->ops->view                 = KSPView_Chebyshev;
549:   ksp->ops->reset                = KSPReset_Chebyshev;

551:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebyshevSetEigenvalues_C",
552:                                     "KSPChebyshevSetEigenvalues_Chebyshev",
553:                                     KSPChebyshevSetEigenvalues_Chebyshev);
554:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebyshevSetEstimateEigenvalues_C",
555:                                     "KSPChebyshevSetEstimateEigenvalues_Chebyshev",
556:                                     KSPChebyshevSetEstimateEigenvalues_Chebyshev);
557:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPChebyshevSetNewMatrix_C",
558:                                     "KSPChebyshevSetNewMatrix_Chebyshev",
559:                                     KSPChebyshevSetNewMatrix_Chebyshev);
560:   return(0);
561: }