Actual source code: dspep.c

slepc-3.15.0 2021-03-31
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-2021, Universitat Politecnica de Valencia, Spain

  6:    This file is part of SLEPc.
  7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
  8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  9: */

 11: #include <slepc/private/dsimpl.h>
 12: #include <slepcblaslapack.h>

 14: typedef struct {
 15:   PetscInt  d;              /* polynomial degree */
 16:   PetscReal *pbc;           /* polynomial basis coefficients */
 17: } DS_PEP;

 19: PetscErrorCode DSAllocate_PEP(DS ds,PetscInt ld)
 20: {
 22:   DS_PEP         *ctx = (DS_PEP*)ds->data;
 23:   PetscInt       i;

 26:   if (!ctx->d) SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_WRONGSTATE,"DSPEP requires specifying the polynomial degree via DSPEPSetDegree()");
 27:   DSAllocateMat_Private(ds,DS_MAT_X);
 28:   DSAllocateMat_Private(ds,DS_MAT_Y);
 29:   for (i=0;i<=ctx->d;i++) {
 30:     DSAllocateMat_Private(ds,DSMatExtra[i]);
 31:   }
 32:   PetscFree(ds->perm);
 33:   PetscMalloc1(ld*ctx->d,&ds->perm);
 34:   PetscLogObjectMemory((PetscObject)ds,ld*ctx->d*sizeof(PetscInt));
 35:   return(0);
 36: }

 38: PetscErrorCode DSView_PEP(DS ds,PetscViewer viewer)
 39: {
 40:   PetscErrorCode    ierr;
 41:   DS_PEP            *ctx = (DS_PEP*)ds->data;
 42:   PetscViewerFormat format;
 43:   PetscInt          i;

 46:   PetscViewerGetFormat(viewer,&format);
 47:   PetscViewerASCIIPrintf(viewer,"polynomial degree: %D\n",ctx->d);
 48:   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) return(0);
 49:   for (i=0;i<=ctx->d;i++) {
 50:     DSViewMat(ds,viewer,DSMatExtra[i]);
 51:   }
 52:   if (ds->state>DS_STATE_INTERMEDIATE) { DSViewMat(ds,viewer,DS_MAT_X); }
 53:   return(0);
 54: }

 56: PetscErrorCode DSVectors_PEP(DS ds,DSMatType mat,PetscInt *j,PetscReal *rnorm)
 57: {
 59:   if (rnorm) SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_SUP,"Not implemented yet");
 60:   switch (mat) {
 61:     case DS_MAT_X:
 62:       break;
 63:     case DS_MAT_Y:
 64:       break;
 65:     default:
 66:       SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
 67:   }
 68:   return(0);
 69: }

 71: PetscErrorCode DSSort_PEP(DS ds,PetscScalar *wr,PetscScalar *wi,PetscScalar *rr,PetscScalar *ri,PetscInt *kout)
 72: {
 74:   DS_PEP         *ctx = (DS_PEP*)ds->data;
 75:   PetscInt       n,i,j,k,p,*perm,told,ld;
 76:   PetscScalar    *A,*X,*Y,rtmp,rtmp2;

 79:   if (!ds->sc) return(0);
 80:   n = ds->n*ctx->d;
 81:   A  = ds->mat[DS_MAT_A];
 82:   perm = ds->perm;
 83:   for (i=0;i<n;i++) perm[i] = i;
 84:   told = ds->t;
 85:   ds->t = n;  /* force the sorting routines to consider d*n eigenvalues */
 86:   if (rr) {
 87:     DSSortEigenvalues_Private(ds,rr,ri,perm,PETSC_FALSE);
 88:   } else {
 89:     DSSortEigenvalues_Private(ds,wr,wi,perm,PETSC_FALSE);
 90:   }
 91:   ds->t = told;  /* restore value of t */
 92:   for (i=0;i<n;i++) A[i]  = wr[perm[i]];
 93:   for (i=0;i<n;i++) wr[i] = A[i];
 94:   for (i=0;i<n;i++) A[i]  = wi[perm[i]];
 95:   for (i=0;i<n;i++) wi[i] = A[i];
 96:   /* cannot use DSPermuteColumns_Private() since matrix is not square */
 97:   ld = ds->ld;
 98:   X  = ds->mat[DS_MAT_X];
 99:   Y  = ds->mat[DS_MAT_Y];
100:   for (i=0;i<n;i++) {
101:     p = perm[i];
102:     if (p != i) {
103:       j = i + 1;
104:       while (perm[j] != i) j++;
105:       perm[j] = p; perm[i] = i;
106:       /* swap columns i and j */
107:       for (k=0;k<ds->n;k++) {
108:         rtmp  = X[k+p*ld]; X[k+p*ld] = X[k+i*ld]; X[k+i*ld] = rtmp;
109:         rtmp2 = Y[k+p*ld]; Y[k+p*ld] = Y[k+i*ld]; Y[k+i*ld] = rtmp2;
110:       }
111:     }
112:   }
113:   return(0);
114: }

116: PetscErrorCode DSSolve_PEP_QZ(DS ds,PetscScalar *wr,PetscScalar *wi)
117: {
119:   DS_PEP         *ctx = (DS_PEP*)ds->data;
120:   PetscInt       i,j,k,off;
121:   PetscScalar    *A,*B,*W,*X,*U,*Y,*E,*work,*beta;
122:   PetscReal      *ca,*cb,*cg,norm,done=1.0;
123:   PetscBLASInt   info,n,ld,ldd,nd,lrwork=0,lwork,one=1,zero=0,cols;
124: #if defined(PETSC_USE_COMPLEX)
125:   PetscReal      *rwork;
126: #endif

129:   if (!ds->mat[DS_MAT_A]) {
130:     DSAllocateMat_Private(ds,DS_MAT_A);
131:   }
132:   if (!ds->mat[DS_MAT_B]) {
133:     DSAllocateMat_Private(ds,DS_MAT_B);
134:   }
135:   if (!ds->mat[DS_MAT_W]) {
136:     DSAllocateMat_Private(ds,DS_MAT_W);
137:   }
138:   if (!ds->mat[DS_MAT_U]) {
139:     DSAllocateMat_Private(ds,DS_MAT_U);
140:   }
141:   PetscBLASIntCast(ds->n*ctx->d,&nd);
142:   PetscBLASIntCast(ds->n,&n);
143:   PetscBLASIntCast(ds->ld,&ld);
144:   PetscBLASIntCast(ds->ld*ctx->d,&ldd);
145: #if defined(PETSC_USE_COMPLEX)
146:   PetscBLASIntCast(nd+2*nd,&lwork);
147:   PetscBLASIntCast(8*nd,&lrwork);
148: #else
149:   PetscBLASIntCast(nd+8*nd,&lwork);
150: #endif
151:   DSAllocateWork_Private(ds,lwork,lrwork,0);
152:   beta = ds->work;
153:   work = ds->work + nd;
154:   lwork -= nd;
155:   A = ds->mat[DS_MAT_A];
156:   B = ds->mat[DS_MAT_B];
157:   W = ds->mat[DS_MAT_W];
158:   U = ds->mat[DS_MAT_U];
159:   X = ds->mat[DS_MAT_X];
160:   Y = ds->mat[DS_MAT_Y];
161:   E = ds->mat[DSMatExtra[ctx->d]];

163:   /* build matrices A and B of the linearization */
164:   PetscArrayzero(A,ldd*ldd);
165:   if (!ctx->pbc) { /* monomial basis */
166:     for (i=0;i<nd-ds->n;i++) A[i+(i+ds->n)*ldd] = 1.0;
167:     for (i=0;i<ctx->d;i++) {
168:       off = i*ds->n*ldd+(ctx->d-1)*ds->n;
169:       for (j=0;j<ds->n;j++) {
170:         PetscArraycpy(A+off+j*ldd,ds->mat[DSMatExtra[i]]+j*ds->ld,ds->n);
171:       }
172:     }
173:   } else {
174:     ca = ctx->pbc;
175:     cb = ca+ctx->d+1;
176:     cg = cb+ctx->d+1;
177:     for (i=0;i<ds->n;i++) {
178:       A[i+(i+ds->n)*ldd] = ca[0];
179:       A[i+i*ldd] = cb[0];
180:     }
181:     for (;i<nd-ds->n;i++) {
182:       j = i/ds->n;
183:       A[i+(i+ds->n)*ldd] = ca[j];
184:       A[i+i*ldd] = cb[j];
185:       A[i+(i-ds->n)*ldd] = cg[j];
186:     }
187:     for (i=0;i<ctx->d-2;i++) {
188:       off = i*ds->n*ldd+(ctx->d-1)*ds->n;
189:       for (j=0;j<ds->n;j++)
190:         for (k=0;k<ds->n;k++)
191:           *(A+off+j*ldd+k) = *(ds->mat[DSMatExtra[i]]+j*ds->ld+k)*ca[ctx->d-1];
192:     }
193:     off = i*ds->n*ldd+(ctx->d-1)*ds->n;
194:     for (j=0;j<ds->n;j++)
195:       for (k=0;k<ds->n;k++)
196:         *(A+off+j*ldd+k) = *(ds->mat[DSMatExtra[i]]+j*ds->ld+k)*ca[ctx->d-1]-E[j*ds->ld+k]*cg[ctx->d-1];
197:     off = (++i)*ds->n*ldd+(ctx->d-1)*ds->n;
198:     for (j=0;j<ds->n;j++)
199:       for (k=0;k<ds->n;k++)
200:         *(A+off+j*ldd+k) = *(ds->mat[DSMatExtra[i]]+j*ds->ld+k)*ca[ctx->d-1]-E[j*ds->ld+k]*cb[ctx->d-1];
201:   }
202:   PetscArrayzero(B,ldd*ldd);
203:   for (i=0;i<nd-ds->n;i++) B[i+i*ldd] = 1.0;
204:   off = (ctx->d-1)*ds->n*(ldd+1);
205:   for (j=0;j<ds->n;j++) {
206:     for (i=0;i<ds->n;i++) B[off+i+j*ldd] = -E[i+j*ds->ld];
207:   }

209:   /* solve generalized eigenproblem */
210: #if defined(PETSC_USE_COMPLEX)
211:   rwork = ds->rwork;
212:   PetscStackCallBLAS("LAPACKggev",LAPACKggev_("V","V",&nd,A,&ldd,B,&ldd,wr,beta,U,&ldd,W,&ldd,work,&lwork,rwork,&info));
213: #else
214:   PetscStackCallBLAS("LAPACKggev",LAPACKggev_("V","V",&nd,A,&ldd,B,&ldd,wr,wi,beta,U,&ldd,W,&ldd,work,&lwork,&info));
215: #endif
216:   SlepcCheckLapackInfo("ggev",info);

218:   /* copy eigenvalues */
219:   for (i=0;i<nd;i++) {
220:     if (beta[i]==0.0) wr[i] = (PetscRealPart(wr[i])>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
221:     else wr[i] /= beta[i];
222: #if !defined(PETSC_USE_COMPLEX)
223:     if (beta[i]==0.0) wi[i] = 0.0;
224:     else wi[i] /= beta[i];
225: #else
226:     if (wi) wi[i] = 0.0;
227: #endif
228:   }

230:   /* copy and normalize eigenvectors */
231:   for (j=0;j<nd;j++) {
232:     PetscArraycpy(X+j*ds->ld,W+j*ldd,ds->n);
233:     PetscArraycpy(Y+j*ds->ld,U+ds->n*(ctx->d-1)+j*ldd,ds->n);
234:   }
235:   for (j=0;j<nd;j++) {
236:     cols = 1;
237:     norm = BLASnrm2_(&n,X+j*ds->ld,&one);
238: #if !defined(PETSC_USE_COMPLEX)
239:     if (wi[j] != 0.0) {
240:       norm = SlepcAbsEigenvalue(norm,BLASnrm2_(&n,X+(j+1)*ds->ld,&one));
241:       cols = 2;
242:     }
243: #endif
244:     PetscStackCallBLAS("LAPACKlascl",LAPACKlascl_("G",&zero,&zero,&norm,&done,&n,&cols,X+j*ds->ld,&ld,&info));
245:     SlepcCheckLapackInfo("lascl",info);
246:     norm = BLASnrm2_(&n,Y+j*ds->ld,&one);
247: #if !defined(PETSC_USE_COMPLEX)
248:     if (wi[j] != 0.0) norm = SlepcAbsEigenvalue(norm,BLASnrm2_(&n,Y+(j+1)*ds->ld,&one));
249: #endif
250:     PetscStackCallBLAS("LAPACKlascl",LAPACKlascl_("G",&zero,&zero,&norm,&done,&n,&cols,Y+j*ds->ld,&ld,&info));
251:     SlepcCheckLapackInfo("lascl",info);
252: #if !defined(PETSC_USE_COMPLEX)
253:     if (wi[j] != 0.0) j++;
254: #endif
255:   }
256:   return(0);
257: }

259: PetscErrorCode DSSynchronize_PEP(DS ds,PetscScalar eigr[],PetscScalar eigi[])
260: {
262:   DS_PEP         *ctx = (DS_PEP*)ds->data;
263:   PetscInt       ld=ds->ld,k=0;
264:   PetscMPIInt    ldnd,rank,off=0,size,dn;

267:   if (ds->state>=DS_STATE_CONDENSED) k += 2*ctx->d*ds->n*ld;
268:   if (eigr) k += ctx->d*ds->n;
269:   if (eigi) k += ctx->d*ds->n;
270:   DSAllocateWork_Private(ds,k,0,0);
271:   PetscMPIIntCast(k*sizeof(PetscScalar),&size);
272:   PetscMPIIntCast(ds->n*ctx->d*ld,&ldnd);
273:   PetscMPIIntCast(ctx->d*ds->n,&dn);
274:   MPI_Comm_rank(PetscObjectComm((PetscObject)ds),&rank);CHKERRMPI(ierr);
275:   if (!rank) {
276:     if (ds->state>=DS_STATE_CONDENSED) {
277:       MPI_Pack(ds->mat[DS_MAT_X],ldnd,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
278:       MPI_Pack(ds->mat[DS_MAT_Y],ldnd,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
279:     }
280:     if (eigr) {
281:       MPI_Pack(eigr,dn,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
282:     }
283:     if (eigi) {
284:       MPI_Pack(eigi,dn,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
285:     }
286:   }
287:   MPI_Bcast(ds->work,size,MPI_BYTE,0,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
288:   if (rank) {
289:     if (ds->state>=DS_STATE_CONDENSED) {
290:       MPI_Unpack(ds->work,size,&off,ds->mat[DS_MAT_X],ldnd,MPIU_SCALAR,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
291:       MPI_Unpack(ds->work,size,&off,ds->mat[DS_MAT_Y],ldnd,MPIU_SCALAR,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
292:     }
293:     if (eigr) {
294:       MPI_Unpack(ds->work,size,&off,eigr,dn,MPIU_SCALAR,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
295:     }
296:     if (eigi) {
297:       MPI_Unpack(ds->work,size,&off,eigi,dn,MPIU_SCALAR,PetscObjectComm((PetscObject)ds));CHKERRMPI(ierr);
298:     }
299:   }
300:   return(0);
301: }

303: static PetscErrorCode DSPEPSetDegree_PEP(DS ds,PetscInt d)
304: {
305:   DS_PEP *ctx = (DS_PEP*)ds->data;

308:   if (d<0) SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"The degree must be a non-negative integer");
309:   if (d>=DS_NUM_EXTRA) SETERRQ1(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"Only implemented for polynomials of degree at most %D",DS_NUM_EXTRA-1);
310:   ctx->d = d;
311:   return(0);
312: }

314: /*@
315:    DSPEPSetDegree - Sets the polynomial degree for a DSPEP.

317:    Logically Collective on ds

319:    Input Parameters:
320: +  ds - the direct solver context
321: -  d  - the degree

323:    Level: intermediate

325: .seealso: DSPEPGetDegree()
326: @*/
327: PetscErrorCode DSPEPSetDegree(DS ds,PetscInt d)
328: {

334:   PetscTryMethod(ds,"DSPEPSetDegree_C",(DS,PetscInt),(ds,d));
335:   return(0);
336: }

338: static PetscErrorCode DSPEPGetDegree_PEP(DS ds,PetscInt *d)
339: {
340:   DS_PEP *ctx = (DS_PEP*)ds->data;

343:   *d = ctx->d;
344:   return(0);
345: }

347: /*@
348:    DSPEPGetDegree - Returns the polynomial degree for a DSPEP.

350:    Not collective

352:    Input Parameter:
353: .  ds - the direct solver context

355:    Output Parameters:
356: .  d - the degree

358:    Level: intermediate

360: .seealso: DSPEPSetDegree()
361: @*/
362: PetscErrorCode DSPEPGetDegree(DS ds,PetscInt *d)
363: {

369:   PetscUseMethod(ds,"DSPEPGetDegree_C",(DS,PetscInt*),(ds,d));
370:   return(0);
371: }

373: static PetscErrorCode DSPEPSetCoefficients_PEP(DS ds,PetscReal *pbc)
374: {
376:   DS_PEP         *ctx = (DS_PEP*)ds->data;
377:   PetscInt       i;

380:   if (!ctx->d) SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_WRONGSTATE,"Must first specify the polynomial degree via DSPEPSetDegree()");
381:   if (ctx->pbc) { PetscFree(ctx->pbc); }
382:   PetscMalloc1(3*(ctx->d+1),&ctx->pbc);
383:   for (i=0;i<3*(ctx->d+1);i++) ctx->pbc[i] = pbc[i];
384:   ds->state = DS_STATE_RAW;
385:   return(0);
386: }

388: /*@C
389:    DSPEPSetCoefficients - Sets the polynomial basis coefficients for a DSPEP.

391:    Logically Collective on ds

393:    Input Parameters:
394: +  ds  - the direct solver context
395: -  pbc - the polynomial basis coefficients

397:    Notes:
398:    This function is required only in the case of a polynomial specified in a
399:    non-monomial basis, to provide the coefficients that will be used
400:    during the linearization, multiplying the identity blocks on the three main
401:    diagonal blocks. Depending on the polynomial basis (Chebyshev, Legendre, ...)
402:    the coefficients must be different.

404:    There must be a total of 3*(d+1) coefficients, where d is the degree of the
405:    polynomial. The coefficients are arranged in three groups: alpha, beta, and
406:    gamma, according to the definition of the three-term recurrence. In the case
407:    of the monomial basis, alpha=1 and beta=gamma=0, in which case it is not
408:    necessary to invoke this function.

410:    Level: advanced

412: .seealso: DSPEPGetCoefficients(), DSPEPSetDegree()
413: @*/
414: PetscErrorCode DSPEPSetCoefficients(DS ds,PetscReal *pbc)
415: {

420:   PetscTryMethod(ds,"DSPEPSetCoefficients_C",(DS,PetscReal*),(ds,pbc));
421:   return(0);
422: }

424: static PetscErrorCode DSPEPGetCoefficients_PEP(DS ds,PetscReal **pbc)
425: {
427:   DS_PEP         *ctx = (DS_PEP*)ds->data;
428:   PetscInt       i;

431:   if (!ctx->d) SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_WRONGSTATE,"Must first specify the polynomial degree via DSPEPSetDegree()");
432:   PetscCalloc1(3*(ctx->d+1),pbc);
433:   if (ctx->pbc) for (i=0;i<3*(ctx->d+1);i++) (*pbc)[i] = ctx->pbc[i];
434:   else for (i=0;i<ctx->d+1;i++) (*pbc)[i] = 1.0;
435:   return(0);
436: }

438: /*@C
439:    DSPEPGetCoefficients - Returns the polynomial basis coefficients for a DSPEP.

441:    Not collective

443:    Input Parameter:
444: .  ds - the direct solver context

446:    Output Parameters:
447: .  pbc - the polynomial basis coefficients

449:    Note:
450:    The returned array has length 3*(d+1) and should be freed by the user.

452:    Fortran Note:
453:    The calling sequence from Fortran is
454: .vb
455:    DSPEPGetCoefficients(eps,pbc,ierr)
456:    double precision pbc(d+1) output
457: .ve

459:    Level: advanced

461: .seealso: DSPEPSetCoefficients()
462: @*/
463: PetscErrorCode DSPEPGetCoefficients(DS ds,PetscReal **pbc)
464: {

470:   PetscUseMethod(ds,"DSPEPGetCoefficients_C",(DS,PetscReal**),(ds,pbc));
471:   return(0);
472: }

474: PetscErrorCode DSDestroy_PEP(DS ds)
475: {
477:   DS_PEP         *ctx = (DS_PEP*)ds->data;

480:   if (ctx->pbc) { PetscFree(ctx->pbc); }
481:   PetscFree(ds->data);
482:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPSetDegree_C",NULL);
483:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPGetDegree_C",NULL);
484:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPSetCoefficients_C",NULL);
485:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPGetCoefficients_C",NULL);
486:   return(0);
487: }

489: PetscErrorCode DSMatGetSize_PEP(DS ds,DSMatType t,PetscInt *rows,PetscInt *cols)
490: {
491:   DS_PEP *ctx = (DS_PEP*)ds->data;

494:   if (!ctx->d) SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_WRONGSTATE,"DSPEP requires specifying the polynomial degree via DSPEPSetDegree()");
495:   *rows = ds->n;
496:   if (t==DS_MAT_A || t==DS_MAT_B || t==DS_MAT_W || t==DS_MAT_U) *rows *= ctx->d;
497:   *cols = ds->n;
498:   if (t==DS_MAT_A || t==DS_MAT_B || t==DS_MAT_W || t==DS_MAT_U || t==DS_MAT_X || t==DS_MAT_Y) *cols *= ctx->d;
499:   return(0);
500: }

502: SLEPC_EXTERN PetscErrorCode DSCreate_PEP(DS ds)
503: {
504:   DS_PEP         *ctx;

508:   PetscNewLog(ds,&ctx);
509:   ds->data = (void*)ctx;

511:   ds->ops->allocate      = DSAllocate_PEP;
512:   ds->ops->view          = DSView_PEP;
513:   ds->ops->vectors       = DSVectors_PEP;
514:   ds->ops->solve[0]      = DSSolve_PEP_QZ;
515:   ds->ops->sort          = DSSort_PEP;
516:   ds->ops->synchronize   = DSSynchronize_PEP;
517:   ds->ops->destroy       = DSDestroy_PEP;
518:   ds->ops->matgetsize    = DSMatGetSize_PEP;
519:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPSetDegree_C",DSPEPSetDegree_PEP);
520:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPGetDegree_C",DSPEPGetDegree_PEP);
521:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPSetCoefficients_C",DSPEPSetCoefficients_PEP);
522:   PetscObjectComposeFunction((PetscObject)ds,"DSPEPGetCoefficients_C",DSPEPGetCoefficients_PEP);
523:   return(0);
524: }