Actual source code: cheby.c
petsc-3.6.0 2015-06-09
2: #include <petsc/private/kspimpl.h> /*I "petscksp.h" I*/
3: #include <../src/ksp/ksp/impls/cheby/chebyshevimpl.h>
7: static PetscErrorCode KSPReset_Chebyshev(KSP ksp)
8: {
9: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
13: KSPReset(cheb->kspest);
14: return(0);
15: }
19: static PetscErrorCode KSPSetUp_Chebyshev(KSP ksp)
20: {
21: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
25: KSPSetWorkVecs(ksp,3);
26: if (cheb->emin == 0. || cheb->emax == 0.) { /* We need to estimate eigenvalues */
27: KSPChebyshevEstEigSet(ksp,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);
28: }
29: return(0);
30: }
34: static PetscErrorCode KSPChebyshevSetEigenvalues_Chebyshev(KSP ksp,PetscReal emax,PetscReal emin)
35: {
36: KSP_Chebyshev *chebyshevP = (KSP_Chebyshev*)ksp->data;
40: if (emax <= emin) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"Maximum eigenvalue must be larger than minimum: max %g min %g",(double)emax,(double)emin);
41: if (emax*emin <= 0.0) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"Both eigenvalues must be of the same sign: max %g min %g",(double)emax,(double)emin);
42: chebyshevP->emax = emax;
43: chebyshevP->emin = emin;
45: KSPChebyshevEstEigSet(ksp,0.,0.,0.,0.); /* Destroy any estimation setup */
46: return(0);
47: }
51: static PetscErrorCode KSPChebyshevEstEigSet_Chebyshev(KSP ksp,PetscReal a,PetscReal b,PetscReal c,PetscReal d)
52: {
53: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
57: if (a != 0.0 || b != 0.0 || c != 0.0 || d != 0.0) {
58: if (!cheb->kspest) { /* should this block of code be moved to KSPSetUp_Chebyshev()? */
59: PetscBool nonzero;
61: KSPCreate(PetscObjectComm((PetscObject)ksp),&cheb->kspest);
62: PetscObjectIncrementTabLevel((PetscObject)cheb->kspest,(PetscObject)ksp,1);
63: KSPSetOptionsPrefix(cheb->kspest,((PetscObject)ksp)->prefix);
64: KSPAppendOptionsPrefix(cheb->kspest,"esteig_");
65: KSPSetSkipPCSetFromOptions(cheb->kspest,PETSC_TRUE);
67: KSPSetPC(cheb->kspest,ksp->pc);
69: KSPGetInitialGuessNonzero(ksp,&nonzero);
70: KSPSetInitialGuessNonzero(cheb->kspest,nonzero);
71: KSPSetComputeEigenvalues(cheb->kspest,PETSC_TRUE);
73: /* Estimate with a fixed number of iterations */
74: KSPSetConvergenceTest(cheb->kspest,KSPConvergedSkip,0,0);
75: KSPSetNormType(cheb->kspest,KSP_NORM_NONE);
76: KSPSetTolerances(cheb->kspest,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,cheb->eststeps);
77: }
78: if (a >= 0) cheb->tform[0] = a;
79: if (b >= 0) cheb->tform[1] = b;
80: if (c >= 0) cheb->tform[2] = c;
81: if (d >= 0) cheb->tform[3] = d;
82: cheb->amatid = 0;
83: cheb->pmatid = 0;
84: cheb->amatstate = -1;
85: cheb->pmatstate = -1;
86: } else {
87: KSPDestroy(&cheb->kspest);
88: }
89: return(0);
90: }
94: static PetscErrorCode KSPChebyshevEstEigSetRandom_Chebyshev(KSP ksp,PetscRandom random)
95: {
96: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
100: if (random) {PetscObjectReference((PetscObject)random);}
101: PetscRandomDestroy(&cheb->random);
103: cheb->random = random;
104: return(0);
105: }
109: /*@
110: KSPChebyshevSetEigenvalues - Sets estimates for the extreme eigenvalues
111: of the preconditioned problem.
113: Logically Collective on KSP
115: Input Parameters:
116: + ksp - the Krylov space context
117: - emax, emin - the eigenvalue estimates
119: Options Database:
120: . -ksp_chebyshev_eigenvalues emin,emax
122: Note: If you run with the Krylov method of KSPCG with the option -ksp_monitor_singular_value it will
123: for that given matrix and preconditioner an estimate of the extreme eigenvalues.
125: Level: intermediate
127: .keywords: KSP, Chebyshev, set, eigenvalues
128: @*/
129: PetscErrorCode KSPChebyshevSetEigenvalues(KSP ksp,PetscReal emax,PetscReal emin)
130: {
137: PetscTryMethod(ksp,"KSPChebyshevSetEigenvalues_C",(KSP,PetscReal,PetscReal),(ksp,emax,emin));
138: return(0);
139: }
143: /*@
144: KSPChebyshevEstEigSet - Automatically estimate the eigenvalues to use for Chebyshev
146: Logically Collective on KSP
148: Input Parameters:
149: + ksp - the Krylov space context
150: . a - multiple of min eigenvalue estimate to use for min Chebyshev bound (or PETSC_DECIDE)
151: . b - multiple of max eigenvalue estimate to use for min Chebyshev bound (or PETSC_DECIDE)
152: . c - multiple of min eigenvalue estimate to use for max Chebyshev bound (or PETSC_DECIDE)
153: - d - multiple of max eigenvalue estimate to use for max Chebyshev bound (or PETSC_DECIDE)
155: Options Database:
156: . -ksp_chebyshev_esteig a,b,c,d
158: Notes:
159: The Chebyshev bounds are estimated using
160: .vb
161: minbound = a*minest + b*maxest
162: maxbound = c*minest + d*maxest
163: .ve
164: The default configuration targets the upper part of the spectrum for use as a multigrid smoother, so only the maximum eigenvalue estimate is used.
165: The minimum eigenvalue estimate obtained by Krylov iteration is typically not accurate until the method has converged.
167: If 0.0 is passed for all transform arguments (a,b,c,d), eigenvalue estimation is disabled.
169: The default transform is (0,0.1; 0,1.1) which targets the "upper" part of the spectrum, as desirable for use with multigrid.
171: Level: intermediate
173: .keywords: KSP, Chebyshev, set, eigenvalues, PCMG
174: @*/
175: PetscErrorCode KSPChebyshevEstEigSet(KSP ksp,PetscReal a,PetscReal b,PetscReal c,PetscReal d)
176: {
185: PetscTryMethod(ksp,"KSPChebyshevEstEigSet_C",(KSP,PetscReal,PetscReal,PetscReal,PetscReal),(ksp,a,b,c,d));
186: return(0);
187: }
191: /*@
192: KSPChebyshevEstEigSetRandom - set random context for estimating eigenvalues
194: Logically Collective
196: Input Arguments:
197: + ksp - linear solver context
198: - random - random number context or NULL to disable randomized RHS
200: Options Database:
201: . -ksp_chebyshev_esteig_random
203: Level: intermediate
205: .seealso: KSPChebyshevEstEigSet(), PetscRandomCreate()
206: @*/
207: PetscErrorCode KSPChebyshevEstEigSetRandom(KSP ksp,PetscRandom random)
208: {
214: PetscTryMethod(ksp,"KSPChebyshevEstEigSetRandom_C",(KSP,PetscRandom),(ksp,random));
215: return(0);
216: }
220: /*@
221: KSPChebyshevEstEigGetKSP - Get the Krylov method context used to estimate eigenvalues for the Chebyshev method. If
222: a Krylov method is not being used for this purpose, NULL is returned. The reference count of the returned KSP is
223: not incremented: it should not be destroyed by the user.
225: Input Parameters:
226: . ksp - the Krylov space context
228: Output Parameters:
229: . kspest the eigenvalue estimation Krylov space context
231: Level: intermediate
233: .seealso: KSPChebyshevEstEigSet()
234: @*/
235: PetscErrorCode KSPChebyshevEstEigGetKSP(KSP ksp, KSP *kspest)
236: {
241: *kspest = NULL;
242: PetscTryMethod(ksp,"KSPChebyshevEstEigGetKSP_C",(KSP,KSP*),(ksp,kspest));
243: return(0);
244: }
248: static PetscErrorCode KSPChebyshevEstEigGetKSP_Chebyshev(KSP ksp, KSP *kspest)
249: {
250: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
253: *kspest = cheb->kspest;
254: return(0);
255: }
259: static PetscErrorCode KSPSetFromOptions_Chebyshev(PetscOptions *PetscOptionsObject,KSP ksp)
260: {
261: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
263: PetscInt neigarg = 2, nestarg = 4;
264: PetscReal eminmax[2] = {0., 0.};
265: PetscReal tform[4] = {PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE};
266: PetscBool flgeig, flgest;
269: PetscOptionsHead(PetscOptionsObject,"KSP Chebyshev Options");
270: PetscOptionsInt("-ksp_chebyshev_esteig_steps","Number of est steps in Chebyshev","",cheb->eststeps,&cheb->eststeps,NULL);
271: PetscOptionsRealArray("-ksp_chebyshev_eigenvalues","extreme eigenvalues","KSPChebyshevSetEigenvalues",eminmax,&neigarg,&flgeig);
272: if (flgeig) {
273: if (neigarg != 2) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"-ksp_chebyshev_eigenvalues: must specify 2 parameters, min and max eigenvalues");
274: KSPChebyshevSetEigenvalues(ksp, eminmax[1], eminmax[0]);
275: }
276: PetscOptionsRealArray("-ksp_chebyshev_esteig","estimate eigenvalues using a Krylov method, then use this transform for Chebyshev eigenvalue bounds","KSPChebyshevEstEigSet",tform,&nestarg,&flgest);
277: if (flgest) {
278: switch (nestarg) {
279: case 0:
280: KSPChebyshevEstEigSet(ksp,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);
281: break;
282: case 2: /* Base everything on the max eigenvalues */
283: KSPChebyshevEstEigSet(ksp,PETSC_DECIDE,tform[0],PETSC_DECIDE,tform[1]);
284: break;
285: case 4: /* Use the full 2x2 linear transformation */
286: KSPChebyshevEstEigSet(ksp,tform[0],tform[1],tform[2],tform[3]);
287: break;
288: default: SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"Must specify either 0, 2, or 4 parameters for eigenvalue estimation");
289: }
290: }
292: if (cheb->kspest) {
293: PetscBool estrand = PETSC_FALSE;
294: PetscOptionsBool("-ksp_chebyshev_esteig_random","Use Random right hand side for eigenvalue estimation","KSPChebyshevEstEigSetRandom",estrand,&estrand,NULL);
295: if (estrand) {
296: PetscRandom random;
297: PetscRandomCreate(PetscObjectComm((PetscObject)ksp),&random);
298: PetscObjectSetOptionsPrefix((PetscObject)random,((PetscObject)ksp)->prefix);
299: PetscObjectAppendOptionsPrefix((PetscObject)random,"ksp_chebyshev_esteig_");
300: PetscRandomSetFromOptions(random);
301: KSPChebyshevEstEigSetRandom(ksp,random);
302: PetscRandomDestroy(&random);
303: }
304: }
306: if (cheb->kspest) {
307: KSPSetFromOptions(cheb->kspest);
308: }
309: PetscOptionsTail();
310: return(0);
311: }
315: /*
316: * Must be passed a KSP solver that has "converged", with KSPSetComputeEigenvalues() called before the solve
317: */
318: static PetscErrorCode KSPChebyshevComputeExtremeEigenvalues_Private(KSP kspest,PetscReal *emin,PetscReal *emax)
319: {
321: PetscInt n,neig;
322: PetscReal *re,*im,min,max;
325: KSPGetIterationNumber(kspest,&n);
326: PetscMalloc2(n,&re,n,&im);
327: KSPComputeEigenvalues(kspest,n,re,im,&neig);
328: min = PETSC_MAX_REAL;
329: max = PETSC_MIN_REAL;
330: for (n=0; n<neig; n++) {
331: min = PetscMin(min,re[n]);
332: max = PetscMax(max,re[n]);
333: }
334: PetscFree2(re,im);
335: *emax = max;
336: *emin = min;
337: return(0);
338: }
342: static PetscErrorCode KSPSolve_Chebyshev(KSP ksp)
343: {
344: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
346: PetscInt k,kp1,km1,maxit,ktmp,i;
347: PetscScalar alpha,omegaprod,mu,omega,Gamma,c[3],scale;
348: PetscReal rnorm = 0.0;
349: Vec sol_orig,b,p[3],r;
350: Mat Amat,Pmat;
351: PetscBool diagonalscale;
354: PCGetDiagonalScale(ksp->pc,&diagonalscale);
355: if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);
357: PCGetOperators(ksp->pc,&Amat,&Pmat);
358: if (cheb->kspest) {
359: PetscObjectId amatid, pmatid;
360: PetscObjectState amatstate, pmatstate;
362: PetscObjectGetId((PetscObject)Amat,&amatid);
363: PetscObjectGetId((PetscObject)Pmat,&pmatid);
364: PetscObjectStateGet((PetscObject)Amat,&amatstate);
365: PetscObjectStateGet((PetscObject)Pmat,&pmatstate);
366: if (amatid != cheb->amatid || pmatid != cheb->pmatid || amatstate != cheb->amatstate || pmatstate != cheb->pmatstate) {
367: PetscReal max=0.0,min=0.0;
368: Vec X,B;
369: X = ksp->work[0];
370: if (cheb->random) {
371: B = ksp->work[1];
372: VecSetRandom(B,cheb->random);
373: } else {
374: B = ksp->vec_rhs;
375: }
376: KSPSolve(cheb->kspest,B,X);
378: if (ksp->guess_zero) {
379: VecZeroEntries(X);
380: }
381: KSPChebyshevComputeExtremeEigenvalues_Private(cheb->kspest,&min,&max);
383: cheb->emin = cheb->tform[0]*min + cheb->tform[1]*max;
384: cheb->emax = cheb->tform[2]*min + cheb->tform[3]*max;
386: cheb->amatid = amatid;
387: cheb->pmatid = pmatid;
388: cheb->amatstate = amatstate;
389: cheb->pmatstate = pmatstate;
390: }
391: }
393: ksp->its = 0;
394: maxit = ksp->max_it;
396: /* These three point to the three active solutions, we
397: rotate these three at each solution update */
398: km1 = 0; k = 1; kp1 = 2;
399: sol_orig = ksp->vec_sol; /* ksp->vec_sol will be asigned to rotating vector p[k], thus save its address */
400: b = ksp->vec_rhs;
401: p[km1] = sol_orig;
402: p[k] = ksp->work[0];
403: p[kp1] = ksp->work[1];
404: r = ksp->work[2];
406: /* use scale*B as our preconditioner */
407: scale = 2.0/(cheb->emax + cheb->emin);
409: /* -alpha <= scale*lambda(B^{-1}A) <= alpha */
410: alpha = 1.0 - scale*(cheb->emin);
411: Gamma = 1.0;
412: mu = 1.0/alpha;
413: omegaprod = 2.0/alpha;
415: c[km1] = 1.0;
416: c[k] = mu;
418: if (!ksp->guess_zero) {
419: KSP_MatMult(ksp,Amat,p[km1],r); /* r = b - A*p[km1] */
420: VecAYPX(r,-1.0,b);
421: } else {
422: VecCopy(b,r);
423: }
425: KSP_PCApply(ksp,r,p[k]); /* p[k] = scale B^{-1}r + p[km1] */
426: VecAYPX(p[k],scale,p[km1]);
428: for (i=0; i<maxit; i++) {
429: PetscObjectSAWsTakeAccess((PetscObject)ksp);
431: ksp->its++;
432: PetscObjectSAWsGrantAccess((PetscObject)ksp);
433: c[kp1] = 2.0*mu*c[k] - c[km1];
434: omega = omegaprod*c[k]/c[kp1];
436: KSP_MatMult(ksp,Amat,p[k],r); /* r = b - Ap[k] */
437: VecAYPX(r,-1.0,b);
438: KSP_PCApply(ksp,r,p[kp1]); /* p[kp1] = B^{-1}r */
439: ksp->vec_sol = p[k];
441: /* calculate residual norm if requested */
442: if (ksp->normtype != KSP_NORM_NONE || ksp->numbermonitors) {
443: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
444: VecNorm(r,NORM_2,&rnorm);
445: } else {
446: VecNorm(p[kp1],NORM_2,&rnorm);
447: }
448: PetscObjectSAWsTakeAccess((PetscObject)ksp);
449: ksp->rnorm = rnorm;
450: PetscObjectSAWsGrantAccess((PetscObject)ksp);
451: KSPLogResidualHistory(ksp,rnorm);
452: KSPMonitor(ksp,i,rnorm);
453: (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
454: if (ksp->reason) break;
455: }
457: /* y^{k+1} = omega(y^{k} - y^{k-1} + Gamma*r^{k}) + y^{k-1} */
458: VecAXPBYPCZ(p[kp1],1.0-omega,omega,omega*Gamma*scale,p[km1],p[k]);
460: ktmp = km1;
461: km1 = k;
462: k = kp1;
463: kp1 = ktmp;
464: }
465: if (!ksp->reason) {
466: if (ksp->normtype != KSP_NORM_NONE) {
467: KSP_MatMult(ksp,Amat,p[k],r); /* r = b - Ap[k] */
468: VecAYPX(r,-1.0,b);
469: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
470: VecNorm(r,NORM_2,&rnorm);
471: } else {
472: KSP_PCApply(ksp,r,p[kp1]); /* p[kp1] = B^{-1}r */
473: VecNorm(p[kp1],NORM_2,&rnorm);
474: }
475: PetscObjectSAWsTakeAccess((PetscObject)ksp);
476: ksp->rnorm = rnorm;
477: PetscObjectSAWsGrantAccess((PetscObject)ksp);
478: ksp->vec_sol = p[k];
479: KSPLogResidualHistory(ksp,rnorm);
480: KSPMonitor(ksp,i,rnorm);
481: }
482: if (ksp->its >= ksp->max_it) {
483: if (ksp->normtype != KSP_NORM_NONE) {
484: (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
485: if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS;
486: } else ksp->reason = KSP_CONVERGED_ITS;
487: }
488: }
490: /* make sure solution is in vector x */
491: ksp->vec_sol = sol_orig;
492: if (k) {
493: VecCopy(p[k],sol_orig);
494: }
495: return(0);
496: }
500: static PetscErrorCode KSPView_Chebyshev(KSP ksp,PetscViewer viewer)
501: {
502: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
504: PetscBool iascii;
507: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
508: if (iascii) {
509: PetscViewerASCIIPrintf(viewer," Chebyshev: eigenvalue estimates: min = %g, max = %g\n",(double)cheb->emin,(double)cheb->emax);
510: if (cheb->kspest) {
511: PetscViewerASCIIPrintf(viewer," Chebyshev: eigenvalues estimated using %s with translations [%g %g; %g %g]\n",((PetscObject) cheb->kspest)->type_name,(double)cheb->tform[0],(double)cheb->tform[1],(double)cheb->tform[2],(double)cheb->tform[3]);
512: PetscViewerASCIIPushTab(viewer);
513: KSPView(cheb->kspest,viewer);
514: PetscViewerASCIIPopTab(viewer);
515: if (cheb->random) {
516: PetscViewerASCIIPrintf(viewer," Chebyshev: estimating eigenvalues using random right hand side\n");
517: PetscViewerASCIIPushTab(viewer);
518: PetscRandomView(cheb->random,viewer);
519: PetscViewerASCIIPopTab(viewer);
520: }
521: }
522: }
523: return(0);
524: }
528: static PetscErrorCode KSPDestroy_Chebyshev(KSP ksp)
529: {
530: KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data;
534: KSPDestroy(&cheb->kspest);
535: PetscRandomDestroy(&cheb->random);
536: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevSetEigenvalues_C",NULL);
537: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevEstEigSet_C",NULL);
538: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevEstEigSetRandom_C",NULL);
539: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevEstEigGetKSP_C",NULL);
540: KSPDestroyDefault(ksp);
541: return(0);
542: }
544: /*MC
545: KSPCHEBYSHEV - The preconditioned Chebyshev iterative method
547: Options Database Keys:
548: + -ksp_chebyshev_eigenvalues <emin,emax> - set approximations to the smallest and largest eigenvalues
549: of the preconditioned operator. If these are accurate you will get much faster convergence.
550: . -ksp_chebyshev_esteig <a,b,c,d> - estimate eigenvalues using a Krylov method, then use this
551: transform for Chebyshev eigenvalue bounds (KSPChebyshevEstEigSet())
552: . -ksp_chebyshev_esteig_steps - number of estimation steps
553: + -ksp_chebyshev_esteig_random - use random right hand side for eigenvalue estimation (KSPChebyshevEstEigSetRandom())
556: Level: beginner
558: Notes: The Chebyshev method requires both the matrix and preconditioner to
559: be symmetric positive (semi) definite.
560: Only support for left preconditioning.
562: Chebyshev is configured as a smoother by default, targetting the "upper" part of the spectrum.
563: The user should call KSPChebyshevSetEigenvalues() if they have eigenvalue estimates.
565: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP,
566: KSPChebyshevSetEigenvalues(), KSPChebyshevEstEigSet(), KSPChebyshevEstEigSetRandom(), KSPRICHARDSON, KSPCG, PCMG
568: M*/
572: PETSC_EXTERN PetscErrorCode KSPCreate_Chebyshev(KSP ksp)
573: {
575: KSP_Chebyshev *chebyshevP;
578: PetscNewLog(ksp,&chebyshevP);
580: ksp->data = (void*)chebyshevP;
581: KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,3);
582: KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,2);
584: chebyshevP->emin = 0.;
585: chebyshevP->emax = 0.;
587: chebyshevP->tform[0] = 0.0;
588: chebyshevP->tform[1] = 0.1;
589: chebyshevP->tform[2] = 0;
590: chebyshevP->tform[3] = 1.1;
591: chebyshevP->eststeps = 10;
592:
593: ksp->ops->setup = KSPSetUp_Chebyshev;
594: ksp->ops->solve = KSPSolve_Chebyshev;
595: ksp->ops->destroy = KSPDestroy_Chebyshev;
596: ksp->ops->buildsolution = KSPBuildSolutionDefault;
597: ksp->ops->buildresidual = KSPBuildResidualDefault;
598: ksp->ops->setfromoptions = KSPSetFromOptions_Chebyshev;
599: ksp->ops->view = KSPView_Chebyshev;
600: ksp->ops->reset = KSPReset_Chebyshev;
602: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevSetEigenvalues_C",KSPChebyshevSetEigenvalues_Chebyshev);
603: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevEstEigSet_C",KSPChebyshevEstEigSet_Chebyshev);
604: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevEstEigSetRandom_C",KSPChebyshevEstEigSetRandom_Chebyshev);
605: PetscObjectComposeFunction((PetscObject)ksp,"KSPChebyshevEstEigGetKSP_C",KSPChebyshevEstEigGetKSP_Chebyshev);
606: return(0);
607: }