Actual source code: stoar.c
slepc-3.14.2 2021-02-01
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2020, 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: */
10: /*
11: SLEPc polynomial eigensolver: "stoar"
13: Method: S-TOAR
15: Algorithm:
17: Symmetric Two-Level Orthogonal Arnoldi.
19: References:
21: [1] C. Campos and J.E. Roman, "Restarted Q-Arnoldi-type methods
22: exploiting symmetry in quadratic eigenvalue problems", BIT
23: Numer. Math. 56(4):1213-1236, 2016.
24: */
26: #include <slepc/private/pepimpl.h>
27: #include "../src/pep/impls/krylov/pepkrylov.h"
28: #include <slepcblaslapack.h>
30: static PetscBool cited = PETSC_FALSE;
31: static const char citation[] =
32: "@Article{slepc-stoar,\n"
33: " author = \"C. Campos and J. E. Roman\",\n"
34: " title = \"Restarted {Q-Arnoldi-type} methods exploiting symmetry in quadratic eigenvalue problems\",\n"
35: " journal = \"{BIT} Numer. Math.\",\n"
36: " volume = \"56\",\n"
37: " number = \"4\",\n"
38: " pages = \"1213--1236\",\n"
39: " year = \"2016,\"\n"
40: " doi = \"https://doi.org/10.1007/s10543-016-0601-5\"\n"
41: "}\n";
43: typedef struct {
44: PetscReal scal[2];
45: Mat A[2];
46: Vec t;
47: } PEP_STOAR_MATSHELL;
49: static PetscErrorCode MatMult_STOAR(Mat A,Vec x,Vec y)
50: {
51: PetscErrorCode ierr;
52: PEP_STOAR_MATSHELL *ctx;
55: MatShellGetContext(A,&ctx);
56: MatMult(ctx->A[0],x,y);
57: VecScale(y,ctx->scal[0]);
58: if (ctx->scal[1]) {
59: MatMult(ctx->A[1],x,ctx->t);
60: VecAXPY(y,ctx->scal[1],ctx->t);
61: }
62: return(0);
63: }
65: static PetscErrorCode MatDestroy_STOAR(Mat A)
66: {
67: PEP_STOAR_MATSHELL *ctx;
68: PetscErrorCode ierr;
71: MatShellGetContext(A,(void**)&ctx);
72: VecDestroy(&ctx->t);
73: PetscFree(ctx);
74: return(0);
75: }
77: PetscErrorCode PEPSTOARSetUpInnerMatrix(PEP pep,Mat *B)
78: {
79: Mat pB[4],Bs[3],D[3];
80: PetscInt i,j,n,m;
81: PEP_STOAR_MATSHELL *ctxMat[3];
82: PEP_STOAR *ctx=(PEP_STOAR*)pep->data;
83: PetscErrorCode ierr;
86: for (i=0;i<3;i++) {
87: STGetMatrixTransformed(pep->st,i,&D[i]); /* D[2] = M */
88: }
89: MatGetLocalSize(D[2],&m,&n);
91: for (j=0;j<3;j++) {
92: PetscNew(ctxMat+j);
93: MatCreateShell(PetscObjectComm((PetscObject)pep),m,n,PETSC_DETERMINE,PETSC_DETERMINE,ctxMat[j],&Bs[j]);
94: MatShellSetOperation(Bs[j],MATOP_MULT,(void(*)(void))MatMult_STOAR);
95: MatShellSetOperation(Bs[j],MATOP_DESTROY,(void(*)(void))MatDestroy_STOAR);
96: }
97: for (i=0;i<4;i++) pB[i] = NULL;
98: if (ctx->alpha) {
99: ctxMat[0]->A[0] = D[0]; ctxMat[0]->scal[0] = ctx->alpha; ctxMat[0]->scal[1] = 0.0;
100: ctxMat[2]->A[0] = D[2]; ctxMat[2]->scal[0] = -ctx->alpha*pep->sfactor*pep->sfactor; ctxMat[2]->scal[1] = 0.0;
101: pB[0] = Bs[0]; pB[3] = Bs[2];
102: }
103: if (ctx->beta) {
104: i = (ctx->alpha)?1:0;
105: ctxMat[0]->scal[1] = 0.0;
106: ctxMat[0]->A[i] = D[1]; ctxMat[0]->scal[i] = -ctx->beta*pep->sfactor;
107: ctxMat[1]->A[0] = D[2]; ctxMat[1]->scal[0] = -ctx->beta*pep->sfactor*pep->sfactor; ctxMat[1]->scal[1] = 0.0;
108: pB[0] = Bs[0]; pB[1] = pB[2] = Bs[1];
109: }
110: BVCreateVec(pep->V,&ctxMat[0]->t);
111: MatCreateNest(PetscObjectComm((PetscObject)pep),2,NULL,2,NULL,pB,B);
112: for (j=0;j<3;j++) { MatDestroy(&Bs[j]); }
113: return(0);
114: }
116: PetscErrorCode PEPSetUp_STOAR(PEP pep)
117: {
118: PetscErrorCode ierr;
119: PetscBool sinv,flg;
120: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
121: PetscInt ld,i;
122: PetscReal eta;
123: BVOrthogType otype;
124: BVOrthogBlockType obtype;
127: PEPCheckHermitian(pep);
128: PEPCheckQuadratic(pep);
129: PEPCheckShiftSinvert(pep);
130: /* spectrum slicing requires special treatment of default values */
131: if (pep->which==PEP_ALL) {
132: pep->ops->solve = PEPSolve_STOAR_QSlice;
133: pep->ops->extractvectors = NULL;
134: pep->ops->setdefaultst = NULL;
135: PEPSetUp_STOAR_QSlice(pep);
136: } else {
137: PEPSetDimensions_Default(pep,pep->nev,&pep->ncv,&pep->mpd);
138: if (!ctx->lock && pep->mpd<pep->ncv) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Should not use mpd parameter in non-locking variant");
139: if (pep->max_it==PETSC_DEFAULT) pep->max_it = PetscMax(100,2*(pep->nmat-1)*pep->n/pep->ncv);
140: pep->ops->solve = PEPSolve_STOAR;
141: ld = pep->ncv+2;
142: DSSetType(pep->ds,DSGHIEP);
143: DSSetCompact(pep->ds,PETSC_TRUE);
144: DSAllocate(pep->ds,ld);
145: PEPBasisCoefficients(pep,pep->pbc);
146: STGetTransform(pep->st,&flg);
147: if (!flg) {
148: PetscFree(pep->solvematcoeffs);
149: PetscMalloc1(pep->nmat,&pep->solvematcoeffs);
150: PetscLogObjectMemory((PetscObject)pep,pep->nmat*sizeof(PetscScalar));
151: PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv);
152: if (sinv) {
153: PEPEvaluateBasis(pep,pep->target,0,pep->solvematcoeffs,NULL);
154: } else {
155: for (i=0;i<pep->nmat-1;i++) pep->solvematcoeffs[i] = 0.0;
156: pep->solvematcoeffs[pep->nmat-1] = 1.0;
157: }
158: }
159: }
160: if (!pep->which) { PEPSetWhichEigenpairs_Default(pep); }
161: PEPCheckUnsupported(pep,PEP_FEATURE_NONMONOMIAL | PEP_FEATURE_REGION);
163: PEPAllocateSolution(pep,2);
164: PEPSetWorkVecs(pep,4);
165: BVDestroy(&ctx->V);
166: BVCreateTensor(pep->V,pep->nmat-1,&ctx->V);
167: BVGetOrthogonalization(pep->V,&otype,NULL,&eta,&obtype);
168: BVSetOrthogonalization(ctx->V,otype,BV_ORTHOG_REFINE_ALWAYS,eta,obtype);
169: return(0);
170: }
172: /*
173: Compute a run of Lanczos iterations. dim(work)=(ctx->ld)*4
174: */
175: static PetscErrorCode PEPSTOARrun(PEP pep,PetscReal *a,PetscReal *b,PetscReal *omega,PetscInt k,PetscInt *M,PetscBool *breakdown,PetscBool *symmlost,Vec *t_)
176: {
178: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
179: PetscInt i,j,m=*M,l,lock;
180: PetscInt lds,d,ld,offq,nqt,ldds;
181: Vec v=t_[0],t=t_[1],q=t_[2];
182: PetscReal norm,sym=0.0,fro=0.0,*f;
183: PetscScalar *y,*S,*x,sigma;
184: PetscBLASInt j_,one=1;
185: PetscBool lindep,flg,sinvert=PETSC_FALSE;
186: Mat MS;
189: PetscMalloc1(*M,&y);
190: BVGetSizes(pep->V,NULL,NULL,&ld);
191: BVTensorGetDegree(ctx->V,&d);
192: BVGetActiveColumns(pep->V,&lock,&nqt);
193: lds = d*ld;
194: offq = ld;
195: DSGetLeadingDimension(pep->ds,&ldds);
196: *breakdown = PETSC_FALSE; /* ----- */
197: DSGetDimensions(pep->ds,NULL,NULL,&l,NULL,NULL);
198: BVSetActiveColumns(ctx->V,0,m);
199: BVSetActiveColumns(pep->V,0,nqt);
200: STGetTransform(pep->st,&flg);
201: if (!flg) {
202: /* spectral transformation handled by the solver */
203: PetscObjectTypeCompareAny((PetscObject)pep->st,&flg,STSINVERT,STSHIFT,"");
204: if (!flg) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"ST type not supported for TOAR without transforming matrices");
205: PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinvert);
206: STGetShift(pep->st,&sigma);
207: }
208: for (j=k;j<m;j++) {
209: /* apply operator */
210: BVTensorGetFactors(ctx->V,NULL,&MS);
211: MatDenseGetArray(MS,&S);
212: BVGetColumn(pep->V,nqt,&t);
213: BVMultVec(pep->V,1.0,0.0,v,S+j*lds);
214: if (!sinvert) {
215: STMatMult(pep->st,0,v,q);
216: BVMultVec(pep->V,1.0,0.0,v,S+offq+j*lds);
217: STMatMult(pep->st,1,v,t);
218: VecAXPY(q,pep->sfactor,t);
219: if (ctx->beta && ctx->alpha) {
220: STMatMult(pep->st,2,v,t);
221: VecAXPY(q,-pep->sfactor*pep->sfactor*ctx->beta/ctx->alpha,t);
222: }
223: STMatSolve(pep->st,q,t);
224: VecScale(t,-1.0/(pep->sfactor*pep->sfactor));
225: } else {
226: STMatMult(pep->st,1,v,q);
227: STMatMult(pep->st,2,v,t);
228: VecAXPY(q,sigma*pep->sfactor,t);
229: VecScale(q,pep->sfactor);
230: BVMultVec(pep->V,1.0,0.0,v,S+offq+j*lds);
231: STMatMult(pep->st,2,v,t);
232: VecAXPY(q,pep->sfactor*pep->sfactor,t);
233: STMatSolve(pep->st,q,t);
234: VecScale(t,-1.0);
235: }
236: BVRestoreColumn(pep->V,nqt,&t);
238: /* orthogonalize */
239: if (!sinvert) x = S+offq+(j+1)*lds;
240: else x = S+(j+1)*lds;
241: BVOrthogonalizeColumn(pep->V,nqt,x,&norm,&lindep);
243: if (!lindep) {
244: if (!sinvert) *(S+offq+(j+1)*lds+nqt) = norm;
245: else *(S+(j+1)*lds+nqt) = norm;
246: BVScaleColumn(pep->V,nqt,1.0/norm);
247: nqt++;
248: }
249: if (!sinvert) {
250: for (i=0;i<=nqt-1;i++) *(S+(j+1)*lds+i) = *(S+offq+j*lds+i);
251: if (ctx->beta && ctx->alpha) {
252: for (i=0;i<=nqt-1;i++) *(S+(j+1)*lds+offq+i) -= *(S+(j+1)*lds+i)*ctx->beta/ctx->alpha;
253: }
254: } else for (i=0;i<nqt;i++) *(S+(j+1)*lds+offq+i) = *(S+j*lds+i)+sigma*(*(S+(j+1)*lds+i));
255: BVSetActiveColumns(pep->V,0,nqt);
256: MatDenseRestoreArray(MS,&S);
257: BVTensorRestoreFactors(ctx->V,NULL,&MS);
259: /* level-2 orthogonalization */
260: BVOrthogonalizeColumn(ctx->V,j+1,y,&norm,&lindep);
261: a[j] = PetscRealPart(y[j]);
262: omega[j+1] = (norm > 0)?1.0:-1.0;
263: BVScaleColumn(ctx->V,j+1,1.0/norm);
264: b[j] = PetscAbsReal(norm);
266: /* check symmetry */
267: DSGetArrayReal(pep->ds,DS_MAT_T,&f);
268: if (j==k) {
269: for (i=l;i<j-1;i++) y[i] = PetscAbsScalar(y[i])-PetscAbsReal(f[2*ldds+i]);
270: for (i=0;i<l;i++) y[i] = 0.0;
271: }
272: DSRestoreArrayReal(pep->ds,DS_MAT_T,&f);
273: if (j>0) y[j-1] = PetscAbsScalar(y[j-1])-PetscAbsReal(b[j-1]);
274: PetscBLASIntCast(j,&j_);
275: sym = SlepcAbs(BLASnrm2_(&j_,y,&one),sym);
276: fro = SlepcAbs(fro,SlepcAbs(a[j],b[j]));
277: if (j>0) fro = SlepcAbs(fro,b[j-1]);
278: if (sym/fro>PetscMax(PETSC_SQRT_MACHINE_EPSILON,10*pep->tol)) {
279: *symmlost = PETSC_TRUE;
280: *M=j;
281: break;
282: }
283: }
284: BVSetActiveColumns(pep->V,lock,nqt);
285: BVSetActiveColumns(ctx->V,0,*M);
286: PetscFree(y);
287: return(0);
288: }
290: #if 0
291: static PetscErrorCode PEPSTOARpreKConvergence(PEP pep,PetscInt nv,PetscReal *norm,Vec *w)
292: {
294: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
295: PetscBLASInt n_,one=1;
296: PetscInt lds=2*ctx->ld;
297: PetscReal t1,t2;
298: PetscScalar *S=ctx->S;
301: PetscBLASIntCast(nv+2,&n_);
302: t1 = BLASnrm2_(&n_,S+nv*2*ctx->ld,&one);
303: t2 = BLASnrm2_(&n_,S+(nv*2+1)*ctx->ld,&one);
304: *norm = SlepcAbs(t1,t2);
305: BVSetActiveColumns(pep->V,0,nv+2);
306: BVMultVec(pep->V,1.0,0.0,w[1],S+nv*lds);
307: STMatMult(pep->st,0,w[1],w[2]);
308: VecNorm(w[2],NORM_2,&t1);
309: BVMultVec(pep->V,1.0,0.0,w[1],S+ctx->ld+nv*lds);
310: STMatMult(pep->st,2,w[1],w[2]);
311: VecNorm(w[2],NORM_2,&t2);
312: t2 *= pep->sfactor*pep->sfactor;
313: *norm = PetscMax(*norm,SlepcAbs(t1,t2));
314: return(0);
315: }
316: #endif
318: PetscErrorCode PEPSolve_STOAR(PEP pep)
319: {
321: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
322: PetscInt j,k,l,nv=0,ld,ldds,t,nq=0;
323: PetscInt nconv=0,deg=pep->nmat-1;
324: PetscScalar *Q,*om,sigma;
325: PetscReal beta,norm=1.0,*omega,*a,*b,*r;
326: PetscBool breakdown,symmlost=PETSC_FALSE,sinv=PETSC_FALSE,falselock=PETSC_TRUE,flg;
327: Mat MQ,A;
328: Vec vomega;
331: PetscCitationsRegister(citation,&cited);
332: PEPSTOARSetUpInnerMatrix(pep,&A);
333: BVSetMatrix(ctx->V,A,PETSC_TRUE);
334: MatDestroy(&A);
335: if (ctx->lock) {
336: /* undocumented option to use a cheaper locking instead of the true locking */
337: PetscOptionsGetBool(NULL,NULL,"-pep_stoar_falselocking",&falselock,NULL);
338: }
339: BVGetSizes(pep->V,NULL,NULL,&ld);
340: STGetShift(pep->st,&sigma);
341: STGetTransform(pep->st,&flg);
342: if (pep->sfactor!=1.0) {
343: if (!flg) {
344: pep->target /= pep->sfactor;
345: RGPushScale(pep->rg,1.0/pep->sfactor);
346: STScaleShift(pep->st,1.0/pep->sfactor);
347: sigma /= pep->sfactor;
348: } else {
349: PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv);
350: pep->target = sinv?pep->target*pep->sfactor:pep->target/pep->sfactor;
351: RGPushScale(pep->rg,sinv?pep->sfactor:1.0/pep->sfactor);
352: STScaleShift(pep->st,sinv?pep->sfactor:1.0/pep->sfactor);
353: }
354: }
355: if (flg) sigma = 0.0;
357: /* Get the starting Arnoldi vector */
358: BVTensorBuildFirstColumn(ctx->V,pep->nini);
359: DSGetArrayReal(pep->ds,DS_MAT_D,&omega);
360: VecCreateSeq(PETSC_COMM_SELF,1,&vomega);
361: BVSetActiveColumns(ctx->V,0,1);
362: BVGetSignature(ctx->V,vomega);
363: VecGetArray(vomega,&om);
364: omega[0] = PetscRealPart(om[0]);
365: VecRestoreArray(vomega,&om);
366: DSRestoreArrayReal(pep->ds,DS_MAT_D,&omega);
367: VecDestroy(&vomega);
369: /* Restart loop */
370: l = 0;
371: DSGetLeadingDimension(pep->ds,&ldds);
372: while (pep->reason == PEP_CONVERGED_ITERATING) {
373: pep->its++;
374: DSGetArrayReal(pep->ds,DS_MAT_T,&a);
375: b = a+ldds;
376: DSGetArrayReal(pep->ds,DS_MAT_D,&omega);
378: /* Compute an nv-step Lanczos factorization */
379: nv = PetscMin(pep->nconv+pep->mpd,pep->ncv);
380: PEPSTOARrun(pep,a,b,omega,pep->nconv+l,&nv,&breakdown,&symmlost,pep->work);
381: beta = b[nv-1];
382: if (symmlost && nv==pep->nconv+l) {
383: pep->reason = PEP_DIVERGED_SYMMETRY_LOST;
384: pep->nconv = nconv;
385: if (falselock || !ctx->lock) {
386: BVSetActiveColumns(ctx->V,0,pep->nconv);
387: BVTensorCompress(ctx->V,0);
388: }
389: break;
390: }
391: DSRestoreArrayReal(pep->ds,DS_MAT_T,&a);
392: DSRestoreArrayReal(pep->ds,DS_MAT_D,&omega);
393: DSSetDimensions(pep->ds,nv,0,pep->nconv,pep->nconv+l);
394: if (l==0) {
395: DSSetState(pep->ds,DS_STATE_INTERMEDIATE);
396: } else {
397: DSSetState(pep->ds,DS_STATE_RAW);
398: }
400: /* Solve projected problem */
401: DSSolve(pep->ds,pep->eigr,pep->eigi);
402: DSSort(pep->ds,pep->eigr,pep->eigi,NULL,NULL,NULL);
403: DSSynchronize(pep->ds,pep->eigr,pep->eigi);
405: /* Check convergence */
406: /* PEPSTOARpreKConvergence(pep,nv,&norm,pep->work);*/
407: norm = 1.0;
408: DSGetDimensions(pep->ds,NULL,NULL,NULL,NULL,&t);
409: PEPKrylovConvergence(pep,PETSC_FALSE,pep->nconv,t-pep->nconv,PetscAbsReal(beta)*norm,&k);
410: (*pep->stopping)(pep,pep->its,pep->max_it,k,pep->nev,&pep->reason,pep->stoppingctx);
412: /* Update l */
413: if (pep->reason != PEP_CONVERGED_ITERATING || breakdown) l = 0;
414: else {
415: l = PetscMax(1,(PetscInt)((nv-k)/2));
416: l = PetscMin(l,t);
417: if (!breakdown) {
418: DSGetArrayReal(pep->ds,DS_MAT_T,&a);
419: if (*(a+ldds+k+l-1)!=0) {
420: if (k+l<nv-1) l = l+1;
421: else l = l-1;
422: }
423: /* Prepare the Rayleigh quotient for restart */
424: DSGetArray(pep->ds,DS_MAT_Q,&Q);
425: DSGetArrayReal(pep->ds,DS_MAT_D,&omega);
426: r = a + 2*ldds;
427: for (j=k;j<k+l;j++) {
428: r[j] = PetscRealPart(Q[nv-1+j*ldds]*beta);
429: }
430: b = a+ldds;
431: b[k+l-1] = r[k+l-1];
432: omega[k+l] = omega[nv];
433: DSRestoreArray(pep->ds,DS_MAT_Q,&Q);
434: DSRestoreArrayReal(pep->ds,DS_MAT_T,&a);
435: DSRestoreArrayReal(pep->ds,DS_MAT_D,&omega);
436: }
437: }
438: nconv = k;
439: if (!ctx->lock && pep->reason == PEP_CONVERGED_ITERATING && !breakdown) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */
441: /* Update S */
442: DSGetMat(pep->ds,DS_MAT_Q,&MQ);
443: BVMultInPlace(ctx->V,MQ,pep->nconv,k+l);
444: MatDestroy(&MQ);
446: /* Copy last column of S */
447: BVCopyColumn(ctx->V,nv,k+l);
448: DSGetArrayReal(pep->ds,DS_MAT_D,&omega);
449: VecCreateSeq(PETSC_COMM_SELF,k+l,&vomega);
450: VecGetArray(vomega,&om);
451: for (j=0;j<k+l;j++) om[j] = omega[j];
452: VecRestoreArray(vomega,&om);
453: BVSetActiveColumns(ctx->V,0,k+l);
454: BVSetSignature(ctx->V,vomega);
455: VecDestroy(&vomega);
456: DSRestoreArrayReal(pep->ds,DS_MAT_D,&omega);
458: if (breakdown && pep->reason == PEP_CONVERGED_ITERATING) {
459: /* stop if breakdown */
460: PetscInfo2(pep,"Breakdown TOAR method (it=%D norm=%g)\n",pep->its,(double)beta);
461: pep->reason = PEP_DIVERGED_BREAKDOWN;
462: }
463: if (pep->reason != PEP_CONVERGED_ITERATING) l--;
464: BVGetActiveColumns(pep->V,NULL,&nq);
465: if (k+l+deg<=nq) {
466: BVSetActiveColumns(ctx->V,pep->nconv,k+l+1);
467: if (!falselock && ctx->lock) {
468: BVTensorCompress(ctx->V,k-pep->nconv);
469: } else {
470: BVTensorCompress(ctx->V,0);
471: }
472: }
473: pep->nconv = k;
474: PEPMonitor(pep,pep->its,nconv,pep->eigr,pep->eigi,pep->errest,nv);
475: }
477: if (pep->nconv>0) {
478: BVSetActiveColumns(ctx->V,0,pep->nconv);
479: BVGetActiveColumns(pep->V,NULL,&nq);
480: BVSetActiveColumns(pep->V,0,nq);
481: if (nq>pep->nconv) {
482: BVTensorCompress(ctx->V,pep->nconv);
483: BVSetActiveColumns(pep->V,0,pep->nconv);
484: }
485: }
486: STGetTransform(pep->st,&flg);
487: if (!flg && pep->ops->backtransform) {
488: (*pep->ops->backtransform)(pep);
489: }
490: if (pep->sfactor!=1.0) {
491: for (j=0;j<pep->nconv;j++) {
492: pep->eigr[j] *= pep->sfactor;
493: pep->eigi[j] *= pep->sfactor;
494: }
495: }
496: /* restore original values */
497: if (!flg) {
498: pep->target *= pep->sfactor;
499: STScaleShift(pep->st,pep->sfactor);
500: } else {
501: STScaleShift(pep->st,sinv?1.0/pep->sfactor:pep->sfactor);
502: pep->target = (sinv)?pep->target/pep->sfactor:pep->target*pep->sfactor;
503: }
504: if (pep->sfactor!=1.0) { RGPopScale(pep->rg); }
506: /* truncate Schur decomposition and change the state to raw so that
507: DSVectors() computes eigenvectors from scratch */
508: DSSetDimensions(pep->ds,pep->nconv,0,0,0);
509: DSSetState(pep->ds,DS_STATE_RAW);
510: return(0);
511: }
513: PetscErrorCode PEPSetFromOptions_STOAR(PetscOptionItems *PetscOptionsObject,PEP pep)
514: {
516: PetscBool flg,lock,b,f1,f2,f3;
517: PetscInt i,j,k;
518: PetscReal array[2]={0,0};
519: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
522: PetscOptionsHead(PetscOptionsObject,"PEP STOAR Options");
524: PetscOptionsBool("-pep_stoar_locking","Choose between locking and non-locking variants","PEPSTOARSetLocking",PETSC_FALSE,&lock,&flg);
525: if (flg) { PEPSTOARSetLocking(pep,lock); }
527: b = ctx->detect;
528: PetscOptionsBool("-pep_stoar_detect_zeros","Check zeros during factorizations at interval boundaries","PEPSTOARSetDetectZeros",ctx->detect,&b,&flg);
529: if (flg) { PEPSTOARSetDetectZeros(pep,b); }
531: i = 1;
532: j = k = PETSC_DECIDE;
533: PetscOptionsInt("-pep_stoar_nev","Number of eigenvalues to compute in each subsolve (only for spectrum slicing)","PEPSTOARSetDimensions",20,&i,&f1);
534: PetscOptionsInt("-pep_stoar_ncv","Number of basis vectors in each subsolve (only for spectrum slicing)","PEPSTOARSetDimensions",40,&j,&f2);
535: PetscOptionsInt("-pep_stoar_mpd","Maximum dimension of projected problem in each subsolve (only for spectrum slicing)","PEPSTOARSetDimensions",40,&k,&f3);
536: if (f1 || f2 || f3) { PEPSTOARSetDimensions(pep,i,j,k); }
538: k = 2;
539: PetscOptionsRealArray("-pep_stoar_linearization","Parameters of the linearization","PEPSTOARSetLinearization",array,&k,&flg);
540: if (flg) {
541: PEPSTOARSetLinearization(pep,array[0],array[1]);
542: }
544: b = ctx->checket;
545: PetscOptionsBool("-pep_stoar_check_eigenvalue_type","Check eigenvalue type during spectrum slicing","PEPSTOARSetCheckEigenvalueType",ctx->checket,&b,&flg);
546: if (flg) { PEPSTOARSetCheckEigenvalueType(pep,b); }
548: PetscOptionsTail();
549: return(0);
550: }
552: static PetscErrorCode PEPSTOARSetLocking_STOAR(PEP pep,PetscBool lock)
553: {
554: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
557: ctx->lock = lock;
558: return(0);
559: }
561: /*@
562: PEPSTOARSetLocking - Choose between locking and non-locking variants of
563: the STOAR method.
565: Logically Collective on pep
567: Input Parameters:
568: + pep - the eigenproblem solver context
569: - lock - true if the locking variant must be selected
571: Options Database Key:
572: . -pep_stoar_locking - Sets the locking flag
574: Notes:
575: The default is to lock converged eigenpairs when the method restarts.
576: This behaviour can be changed so that all directions are kept in the
577: working subspace even if already converged to working accuracy (the
578: non-locking variant).
580: Level: advanced
582: .seealso: PEPSTOARGetLocking()
583: @*/
584: PetscErrorCode PEPSTOARSetLocking(PEP pep,PetscBool lock)
585: {
591: PetscTryMethod(pep,"PEPSTOARSetLocking_C",(PEP,PetscBool),(pep,lock));
592: return(0);
593: }
595: static PetscErrorCode PEPSTOARGetLocking_STOAR(PEP pep,PetscBool *lock)
596: {
597: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
600: *lock = ctx->lock;
601: return(0);
602: }
604: /*@
605: PEPSTOARGetLocking - Gets the locking flag used in the STOAR method.
607: Not Collective
609: Input Parameter:
610: . pep - the eigenproblem solver context
612: Output Parameter:
613: . lock - the locking flag
615: Level: advanced
617: .seealso: PEPSTOARSetLocking()
618: @*/
619: PetscErrorCode PEPSTOARGetLocking(PEP pep,PetscBool *lock)
620: {
626: PetscUseMethod(pep,"PEPSTOARGetLocking_C",(PEP,PetscBool*),(pep,lock));
627: return(0);
628: }
630: static PetscErrorCode PEPSTOARGetInertias_STOAR(PEP pep,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
631: {
633: PetscInt i,numsh;
634: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
635: PEP_SR sr = ctx->sr;
638: if (!pep->state) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONGSTATE,"Must call PEPSetUp() first");
639: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see PEPSetInterval()");
640: switch (pep->state) {
641: case PEP_STATE_INITIAL:
642: break;
643: case PEP_STATE_SETUP:
644: if (n) *n = 2;
645: if (shifts) {
646: PetscMalloc1(2,shifts);
647: (*shifts)[0] = pep->inta;
648: (*shifts)[1] = pep->intb;
649: }
650: if (inertias) {
651: PetscMalloc1(2,inertias);
652: (*inertias)[0] = (sr->dir==1)?sr->inertia0:sr->inertia1;
653: (*inertias)[1] = (sr->dir==1)?sr->inertia1:sr->inertia0;
654: }
655: break;
656: case PEP_STATE_SOLVED:
657: case PEP_STATE_EIGENVECTORS:
658: numsh = ctx->nshifts;
659: if (n) *n = numsh;
660: if (shifts) {
661: PetscMalloc1(numsh,shifts);
662: for (i=0;i<numsh;i++) (*shifts)[i] = ctx->shifts[i];
663: }
664: if (inertias) {
665: PetscMalloc1(numsh,inertias);
666: for (i=0;i<numsh;i++) (*inertias)[i] = ctx->inertias[i];
667: }
668: break;
669: }
670: return(0);
671: }
673: /*@C
674: PEPSTOARGetInertias - Gets the values of the shifts and their
675: corresponding inertias in case of doing spectrum slicing for a
676: computational interval.
678: Not Collective
680: Input Parameter:
681: . pep - the eigenproblem solver context
683: Output Parameters:
684: + n - number of shifts, including the endpoints of the interval
685: . shifts - the values of the shifts used internally in the solver
686: - inertias - the values of the inertia in each shift
688: Notes:
689: If called after PEPSolve(), all shifts used internally by the solver are
690: returned (including both endpoints and any intermediate ones). If called
691: before PEPSolve() and after PEPSetUp() then only the information of the
692: endpoints of subintervals is available.
694: This function is only available for spectrum slicing runs.
696: The returned arrays should be freed by the user. Can pass NULL in any of
697: the two arrays if not required.
699: Fortran Notes:
700: The calling sequence from Fortran is
701: .vb
702: PEPSTOARGetInertias(pep,n,shifts,inertias,ierr)
703: integer n
704: double precision shifts(*)
705: integer inertias(*)
706: .ve
707: The arrays should be at least of length n. The value of n can be determined
708: by an initial call
709: .vb
710: PEPSTOARGetInertias(pep,n,PETSC_NULL_REAL,PETSC_NULL_INTEGER,ierr)
711: .ve
713: Level: advanced
715: .seealso: PEPSetInterval()
716: @*/
717: PetscErrorCode PEPSTOARGetInertias(PEP pep,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
718: {
724: PetscUseMethod(pep,"PEPSTOARGetInertias_C",(PEP,PetscInt*,PetscReal**,PetscInt**),(pep,n,shifts,inertias));
725: return(0);
726: }
728: static PetscErrorCode PEPSTOARSetDetectZeros_STOAR(PEP pep,PetscBool detect)
729: {
730: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
733: ctx->detect = detect;
734: pep->state = PEP_STATE_INITIAL;
735: return(0);
736: }
738: /*@
739: PEPSTOARSetDetectZeros - Sets a flag to enforce detection of
740: zeros during the factorizations throughout the spectrum slicing computation.
742: Logically Collective on pep
744: Input Parameters:
745: + pep - the eigenproblem solver context
746: - detect - check for zeros
748: Options Database Key:
749: . -pep_stoar_detect_zeros - Check for zeros; this takes an optional
750: bool value (0/1/no/yes/true/false)
752: Notes:
753: A zero in the factorization indicates that a shift coincides with an eigenvalue.
755: This flag is turned off by default, and may be necessary in some cases.
756: This feature currently requires an external package for factorizations
757: with support for zero detection, e.g. MUMPS.
759: Level: advanced
761: .seealso: PEPSetInterval()
762: @*/
763: PetscErrorCode PEPSTOARSetDetectZeros(PEP pep,PetscBool detect)
764: {
770: PetscTryMethod(pep,"PEPSTOARSetDetectZeros_C",(PEP,PetscBool),(pep,detect));
771: return(0);
772: }
774: static PetscErrorCode PEPSTOARGetDetectZeros_STOAR(PEP pep,PetscBool *detect)
775: {
776: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
779: *detect = ctx->detect;
780: return(0);
781: }
783: /*@
784: PEPSTOARGetDetectZeros - Gets the flag that enforces zero detection
785: in spectrum slicing.
787: Not Collective
789: Input Parameter:
790: . pep - the eigenproblem solver context
792: Output Parameter:
793: . detect - whether zeros detection is enforced during factorizations
795: Level: advanced
797: .seealso: PEPSTOARSetDetectZeros()
798: @*/
799: PetscErrorCode PEPSTOARGetDetectZeros(PEP pep,PetscBool *detect)
800: {
806: PetscUseMethod(pep,"PEPSTOARGetDetectZeros_C",(PEP,PetscBool*),(pep,detect));
807: return(0);
808: }
810: static PetscErrorCode PEPSTOARSetLinearization_STOAR(PEP pep,PetscReal alpha,PetscReal beta)
811: {
812: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
815: if (beta==0.0 && alpha==0.0) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONG,"Parameters alpha and beta cannot be zero simultaneously");
816: ctx->alpha = alpha;
817: ctx->beta = beta;
818: return(0);
819: }
821: /*@
822: PEPSTOARSetLinearization - Set the coefficients that define
823: the linearization of a quadratic eigenproblem.
825: Logically Collective on pep
827: Input Parameters:
828: + pep - polynomial eigenvalue solver
829: . alpha - first parameter of the linearization
830: - beta - second parameter of the linearization
832: Options Database Key:
833: . -pep_stoar_linearization <alpha,beta> - Sets the coefficients
835: Notes:
836: Cannot pass zero for both alpha and beta. The default values are
837: alpha=1 and beta=0.
839: Level: advanced
841: .seealso: PEPSTOARGetLinearization()
842: @*/
843: PetscErrorCode PEPSTOARSetLinearization(PEP pep,PetscReal alpha,PetscReal beta)
844: {
851: PetscTryMethod(pep,"PEPSTOARSetLinearization_C",(PEP,PetscReal,PetscReal),(pep,alpha,beta));
852: return(0);
853: }
855: static PetscErrorCode PEPSTOARGetLinearization_STOAR(PEP pep,PetscReal *alpha,PetscReal *beta)
856: {
857: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
860: if (alpha) *alpha = ctx->alpha;
861: if (beta) *beta = ctx->beta;
862: return(0);
863: }
865: /*@
866: PEPSTOARGetLinearization - Returns the coefficients that define
867: the linearization of a quadratic eigenproblem.
869: Not Collective
871: Input Parameter:
872: . pep - polynomial eigenvalue solver
874: Output Parameters:
875: + alpha - the first parameter of the linearization
876: - beta - the second parameter of the linearization
878: Level: advanced
880: .seealso: PEPSTOARSetLinearization()
881: @*/
882: PetscErrorCode PEPSTOARGetLinearization(PEP pep,PetscReal *alpha,PetscReal *beta)
883: {
888: PetscUseMethod(pep,"PEPSTOARGetLinearization_C",(PEP,PetscReal*,PetscReal*),(pep,alpha,beta));
889: return(0);
890: }
892: static PetscErrorCode PEPSTOARSetDimensions_STOAR(PEP pep,PetscInt nev,PetscInt ncv,PetscInt mpd)
893: {
894: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
897: if (nev<1) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of nev. Must be > 0");
898: ctx->nev = nev;
899: if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
900: ctx->ncv = PETSC_DEFAULT;
901: } else {
902: if (ncv<1) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
903: ctx->ncv = ncv;
904: }
905: if (mpd == PETSC_DECIDE || mpd == PETSC_DEFAULT) {
906: ctx->mpd = PETSC_DEFAULT;
907: } else {
908: if (mpd<1) SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of mpd. Must be > 0");
909: ctx->mpd = mpd;
910: }
911: pep->state = PEP_STATE_INITIAL;
912: return(0);
913: }
915: /*@
916: PEPSTOARSetDimensions - Sets the dimensions used for each subsolve
917: step in case of doing spectrum slicing for a computational interval.
918: The meaning of the parameters is the same as in PEPSetDimensions().
920: Logically Collective on pep
922: Input Parameters:
923: + pep - the eigenproblem solver context
924: . nev - number of eigenvalues to compute
925: . ncv - the maximum dimension of the subspace to be used by the subsolve
926: - mpd - the maximum dimension allowed for the projected problem
928: Options Database Key:
929: + -eps_stoar_nev <nev> - Sets the number of eigenvalues
930: . -eps_stoar_ncv <ncv> - Sets the dimension of the subspace
931: - -eps_stoar_mpd <mpd> - Sets the maximum projected dimension
933: Level: advanced
935: .seealso: PEPSTOARGetDimensions(), PEPSetDimensions(), PEPSetInterval()
936: @*/
937: PetscErrorCode PEPSTOARSetDimensions(PEP pep,PetscInt nev,PetscInt ncv,PetscInt mpd)
938: {
946: PetscTryMethod(pep,"PEPSTOARSetDimensions_C",(PEP,PetscInt,PetscInt,PetscInt),(pep,nev,ncv,mpd));
947: return(0);
948: }
950: static PetscErrorCode PEPSTOARGetDimensions_STOAR(PEP pep,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
951: {
952: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
955: if (nev) *nev = ctx->nev;
956: if (ncv) *ncv = ctx->ncv;
957: if (mpd) *mpd = ctx->mpd;
958: return(0);
959: }
961: /*@
962: PEPSTOARGetDimensions - Gets the dimensions used for each subsolve
963: step in case of doing spectrum slicing for a computational interval.
965: Not Collective
967: Input Parameter:
968: . pep - the eigenproblem solver context
970: Output Parameters:
971: + nev - number of eigenvalues to compute
972: . ncv - the maximum dimension of the subspace to be used by the subsolve
973: - mpd - the maximum dimension allowed for the projected problem
975: Level: advanced
977: .seealso: PEPSTOARSetDimensions()
978: @*/
979: PetscErrorCode PEPSTOARGetDimensions(PEP pep,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
980: {
985: PetscUseMethod(pep,"PEPSTOARGetDimensions_C",(PEP,PetscInt*,PetscInt*,PetscInt*),(pep,nev,ncv,mpd));
986: return(0);
987: }
989: static PetscErrorCode PEPSTOARSetCheckEigenvalueType_STOAR(PEP pep,PetscBool checket)
990: {
991: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
994: ctx->checket = checket;
995: pep->state = PEP_STATE_INITIAL;
996: return(0);
997: }
999: /*@
1000: PEPSTOARSetCheckEigenvalueType - Sets a flag to check that all the eigenvalues
1001: obtained throughout the spectrum slicing computation have the same definite type.
1003: Logically Collective on pep
1005: Input Parameters:
1006: + pep - the eigenproblem solver context
1007: - checket - check eigenvalue type
1009: Options Database Key:
1010: . -pep_stoar_check_eigenvalue_type - Check eigenvalue type; this takes an optional
1011: bool value (0/1/no/yes/true/false)
1013: Notes:
1014: This option is relevant only for spectrum slicing computations, but it is
1015: ignored if the problem type is PEP_HYPERBOLIC.
1017: This flag is turned on by default, to guarantee that the computed eigenvalues
1018: have the same type (otherwise the computed solution might be wrong). But since
1019: the check is computationally quite expensive, the check may be turned off if
1020: the user knows for sure that all eigenvalues in the requested interval have
1021: the same type.
1023: Level: advanced
1025: .seealso: PEPSetProblemType(), PEPSetInterval()
1026: @*/
1027: PetscErrorCode PEPSTOARSetCheckEigenvalueType(PEP pep,PetscBool checket)
1028: {
1034: PetscTryMethod(pep,"PEPSTOARSetCheckEigenvalueType_C",(PEP,PetscBool),(pep,checket));
1035: return(0);
1036: }
1038: static PetscErrorCode PEPSTOARGetCheckEigenvalueType_STOAR(PEP pep,PetscBool *checket)
1039: {
1040: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
1043: *checket = ctx->checket;
1044: return(0);
1045: }
1047: /*@
1048: PEPSTOARGetCheckEigenvalueType - Gets the flag for the eigenvalue type
1049: check in spectrum slicing.
1051: Not Collective
1053: Input Parameter:
1054: . pep - the eigenproblem solver context
1056: Output Parameter:
1057: . checket - whether eigenvalue type must be checked during spectrum slcing
1059: Level: advanced
1061: .seealso: PEPSTOARSetCheckEigenvalueType()
1062: @*/
1063: PetscErrorCode PEPSTOARGetCheckEigenvalueType(PEP pep,PetscBool *checket)
1064: {
1070: PetscUseMethod(pep,"PEPSTOARGetCheckEigenvalueType_C",(PEP,PetscBool*),(pep,checket));
1071: return(0);
1072: }
1074: PetscErrorCode PEPView_STOAR(PEP pep,PetscViewer viewer)
1075: {
1077: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
1078: PetscBool isascii;
1081: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
1082: if (isascii) {
1083: PetscViewerASCIIPrintf(viewer," using the %slocking variant\n",ctx->lock?"":"non-");
1084: PetscViewerASCIIPrintf(viewer," linearization parameters: alpha=%g beta=%g\n",(double)ctx->alpha,(double)ctx->beta);
1085: if (pep->which==PEP_ALL && !ctx->hyperbolic) {
1086: PetscViewerASCIIPrintf(viewer," checking eigenvalue type: %s\n",ctx->checket?"enabled":"disabled");
1087: }
1088: }
1089: return(0);
1090: }
1092: PetscErrorCode PEPReset_STOAR(PEP pep)
1093: {
1097: if (pep->which==PEP_ALL) {
1098: PEPReset_STOAR_QSlice(pep);
1099: }
1100: return(0);
1101: }
1103: PetscErrorCode PEPDestroy_STOAR(PEP pep)
1104: {
1106: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
1109: BVDestroy(&ctx->V);
1110: PetscFree(pep->data);
1111: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLocking_C",NULL);
1112: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLocking_C",NULL);
1113: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDetectZeros_C",NULL);
1114: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDetectZeros_C",NULL);
1115: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetInertias_C",NULL);
1116: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDimensions_C",NULL);
1117: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDimensions_C",NULL);
1118: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLinearization_C",NULL);
1119: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLinearization_C",NULL);
1120: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetCheckEigenvalueType_C",NULL);
1121: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetCheckEigenvalueType_C",NULL);
1122: return(0);
1123: }
1125: SLEPC_EXTERN PetscErrorCode PEPCreate_STOAR(PEP pep)
1126: {
1128: PEP_STOAR *ctx;
1131: PetscNewLog(pep,&ctx);
1132: pep->data = (void*)ctx;
1134: pep->lineariz = PETSC_TRUE;
1135: ctx->lock = PETSC_TRUE;
1136: ctx->nev = 1;
1137: ctx->ncv = PETSC_DEFAULT;
1138: ctx->mpd = PETSC_DEFAULT;
1139: ctx->alpha = 1.0;
1140: ctx->beta = 0.0;
1141: ctx->checket = PETSC_TRUE;
1143: pep->ops->setup = PEPSetUp_STOAR;
1144: pep->ops->setfromoptions = PEPSetFromOptions_STOAR;
1145: pep->ops->destroy = PEPDestroy_STOAR;
1146: pep->ops->view = PEPView_STOAR;
1147: pep->ops->backtransform = PEPBackTransform_Default;
1148: pep->ops->computevectors = PEPComputeVectors_Default;
1149: pep->ops->extractvectors = PEPExtractVectors_TOAR;
1150: pep->ops->reset = PEPReset_STOAR;
1152: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLocking_C",PEPSTOARSetLocking_STOAR);
1153: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLocking_C",PEPSTOARGetLocking_STOAR);
1154: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDetectZeros_C",PEPSTOARSetDetectZeros_STOAR);
1155: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDetectZeros_C",PEPSTOARGetDetectZeros_STOAR);
1156: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetInertias_C",PEPSTOARGetInertias_STOAR);
1157: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDimensions_C",PEPSTOARGetDimensions_STOAR);
1158: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDimensions_C",PEPSTOARSetDimensions_STOAR);
1159: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLinearization_C",PEPSTOARSetLinearization_STOAR);
1160: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLinearization_C",PEPSTOARGetLinearization_STOAR);
1161: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetCheckEigenvalueType_C",PEPSTOARSetCheckEigenvalueType_STOAR);
1162: PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetCheckEigenvalueType_C",PEPSTOARGetCheckEigenvalueType_STOAR);
1163: return(0);
1164: }