Actual source code: stoar.c
slepc-main 2024-11-09
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, 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: PEP_STOAR_MATSHELL *ctx;
53: PetscFunctionBegin;
54: PetscCall(MatShellGetContext(A,&ctx));
55: PetscCall(MatMult(ctx->A[0],x,y));
56: PetscCall(VecScale(y,ctx->scal[0]));
57: if (ctx->scal[1]) {
58: PetscCall(MatMult(ctx->A[1],x,ctx->t));
59: PetscCall(VecAXPY(y,ctx->scal[1],ctx->t));
60: }
61: PetscFunctionReturn(PETSC_SUCCESS);
62: }
64: static PetscErrorCode MatDestroy_STOAR(Mat A)
65: {
66: PEP_STOAR_MATSHELL *ctx;
68: PetscFunctionBegin;
69: PetscCall(MatShellGetContext(A,&ctx));
70: PetscCall(VecDestroy(&ctx->t));
71: PetscCall(PetscFree(ctx));
72: PetscFunctionReturn(PETSC_SUCCESS);
73: }
75: PetscErrorCode PEPSTOARSetUpInnerMatrix(PEP pep,Mat *B)
76: {
77: Mat pB[4],Bs[3],D[3];
78: PetscInt i,j,n,m;
79: PEP_STOAR_MATSHELL *ctxMat[3];
80: PEP_STOAR *ctx=(PEP_STOAR*)pep->data;
82: PetscFunctionBegin;
83: for (i=0;i<3;i++) {
84: PetscCall(STGetMatrixTransformed(pep->st,i,&D[i])); /* D[2] = M */
85: }
86: PetscCall(MatGetLocalSize(D[2],&m,&n));
88: for (j=0;j<3;j++) {
89: PetscCall(PetscNew(ctxMat+j));
90: PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pep),m,n,PETSC_DETERMINE,PETSC_DETERMINE,ctxMat[j],&Bs[j]));
91: PetscCall(MatShellSetOperation(Bs[j],MATOP_MULT,(void(*)(void))MatMult_STOAR));
92: PetscCall(MatShellSetOperation(Bs[j],MATOP_DESTROY,(void(*)(void))MatDestroy_STOAR));
93: }
94: for (i=0;i<4;i++) pB[i] = NULL;
95: if (ctx->alpha) {
96: ctxMat[0]->A[0] = D[0]; ctxMat[0]->scal[0] = ctx->alpha; ctxMat[0]->scal[1] = 0.0;
97: ctxMat[2]->A[0] = D[2]; ctxMat[2]->scal[0] = -ctx->alpha*pep->sfactor*pep->sfactor; ctxMat[2]->scal[1] = 0.0;
98: pB[0] = Bs[0]; pB[3] = Bs[2];
99: }
100: if (ctx->beta) {
101: i = (ctx->alpha)?1:0;
102: ctxMat[0]->scal[1] = 0.0;
103: ctxMat[0]->A[i] = D[1]; ctxMat[0]->scal[i] = -ctx->beta*pep->sfactor;
104: ctxMat[1]->A[0] = D[2]; ctxMat[1]->scal[0] = -ctx->beta*pep->sfactor*pep->sfactor; ctxMat[1]->scal[1] = 0.0;
105: pB[0] = Bs[0]; pB[1] = pB[2] = Bs[1];
106: }
107: PetscCall(BVCreateVec(pep->V,&ctxMat[0]->t));
108: PetscCall(MatCreateNest(PetscObjectComm((PetscObject)pep),2,NULL,2,NULL,pB,B));
109: for (j=0;j<3;j++) PetscCall(MatDestroy(&Bs[j]));
110: PetscFunctionReturn(PETSC_SUCCESS);
111: }
113: static PetscErrorCode PEPSetUp_STOAR(PEP pep)
114: {
115: PetscBool sinv,flg;
116: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
117: PetscInt ld,i;
118: PetscReal eta;
119: BVOrthogType otype;
120: BVOrthogBlockType obtype;
122: PetscFunctionBegin;
123: PEPCheckHermitian(pep);
124: PEPCheckQuadratic(pep);
125: PEPCheckShiftSinvert(pep);
126: /* spectrum slicing requires special treatment of default values */
127: if (pep->which==PEP_ALL) {
128: pep->ops->solve = PEPSolve_STOAR_QSlice;
129: pep->ops->extractvectors = NULL;
130: pep->ops->setdefaultst = NULL;
131: PetscCall(PEPSetUp_STOAR_QSlice(pep));
132: } else {
133: PetscCall(PEPSetDimensions_Default(pep,pep->nev,&pep->ncv,&pep->mpd));
134: PetscCheck(ctx->lock || pep->mpd>=pep->ncv,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Should not use mpd parameter in non-locking variant");
135: if (pep->max_it==PETSC_DETERMINE) pep->max_it = PetscMax(100,2*(pep->nmat-1)*pep->n/pep->ncv);
136: pep->ops->solve = PEPSolve_STOAR;
137: ld = pep->ncv+2;
138: PetscCall(DSSetType(pep->ds,DSGHIEP));
139: PetscCall(DSSetCompact(pep->ds,PETSC_TRUE));
140: PetscCall(DSSetExtraRow(pep->ds,PETSC_TRUE));
141: PetscCall(DSAllocate(pep->ds,ld));
142: PetscCall(PEPBasisCoefficients(pep,pep->pbc));
143: PetscCall(STGetTransform(pep->st,&flg));
144: if (!flg) {
145: PetscCall(PetscFree(pep->solvematcoeffs));
146: PetscCall(PetscMalloc1(pep->nmat,&pep->solvematcoeffs));
147: PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv));
148: if (sinv) PetscCall(PEPEvaluateBasis(pep,pep->target,0,pep->solvematcoeffs,NULL));
149: else {
150: for (i=0;i<pep->nmat-1;i++) pep->solvematcoeffs[i] = 0.0;
151: pep->solvematcoeffs[pep->nmat-1] = 1.0;
152: }
153: }
154: }
155: if (!pep->which) PetscCall(PEPSetWhichEigenpairs_Default(pep));
156: PEPCheckUnsupported(pep,PEP_FEATURE_NONMONOMIAL | PEP_FEATURE_REGION);
158: PetscCall(PEPAllocateSolution(pep,2));
159: PetscCall(PEPSetWorkVecs(pep,4));
160: PetscCall(BVDestroy(&ctx->V));
161: PetscCall(BVCreateTensor(pep->V,pep->nmat-1,&ctx->V));
162: PetscCall(BVGetOrthogonalization(pep->V,&otype,NULL,&eta,&obtype));
163: PetscCall(BVSetOrthogonalization(ctx->V,otype,BV_ORTHOG_REFINE_ALWAYS,eta,obtype));
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*
168: Compute a run of Lanczos iterations. dim(work)=(ctx->ld)*4
169: */
170: static PetscErrorCode PEPSTOARrun(PEP pep,PetscReal *a,PetscReal *b,PetscReal *omega,PetscInt k,PetscInt *M,PetscBool *breakdown,PetscBool *symmlost,Vec *t_)
171: {
172: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
173: PetscInt i,j,m=*M,l,lock;
174: PetscInt lds,d,ld,offq,nqt,ldds;
175: Vec v=t_[0],t=t_[1],q=t_[2];
176: PetscReal norm,sym=0.0,fro=0.0,*f;
177: PetscScalar *y,*S,*x,sigma;
178: PetscBLASInt j_,one=1;
179: PetscBool lindep,flg,sinvert=PETSC_FALSE;
180: Mat MS;
182: PetscFunctionBegin;
183: PetscCall(PetscMalloc1(*M,&y));
184: PetscCall(BVGetSizes(pep->V,NULL,NULL,&ld));
185: PetscCall(BVTensorGetDegree(ctx->V,&d));
186: PetscCall(BVGetActiveColumns(pep->V,&lock,&nqt));
187: lds = d*ld;
188: offq = ld;
189: PetscCall(DSGetLeadingDimension(pep->ds,&ldds));
190: *breakdown = PETSC_FALSE; /* ----- */
191: PetscCall(DSGetDimensions(pep->ds,NULL,&l,NULL,NULL));
192: PetscCall(BVSetActiveColumns(ctx->V,0,m));
193: PetscCall(BVSetActiveColumns(pep->V,0,nqt));
194: PetscCall(STGetTransform(pep->st,&flg));
195: if (!flg) {
196: /* spectral transformation handled by the solver */
197: PetscCall(PetscObjectTypeCompareAny((PetscObject)pep->st,&flg,STSINVERT,STSHIFT,""));
198: PetscCheck(flg,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"ST type not supported for TOAR without transforming matrices");
199: PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinvert));
200: PetscCall(STGetShift(pep->st,&sigma));
201: }
202: for (j=k;j<m;j++) {
203: /* apply operator */
204: PetscCall(BVTensorGetFactors(ctx->V,NULL,&MS));
205: PetscCall(MatDenseGetArray(MS,&S));
206: PetscCall(BVGetColumn(pep->V,nqt,&t));
207: PetscCall(BVMultVec(pep->V,1.0,0.0,v,S+j*lds));
208: if (!sinvert) {
209: PetscCall(STMatMult(pep->st,0,v,q));
210: PetscCall(BVMultVec(pep->V,1.0,0.0,v,S+offq+j*lds));
211: PetscCall(STMatMult(pep->st,1,v,t));
212: PetscCall(VecAXPY(q,pep->sfactor,t));
213: if (ctx->beta && ctx->alpha) {
214: PetscCall(STMatMult(pep->st,2,v,t));
215: PetscCall(VecAXPY(q,-pep->sfactor*pep->sfactor*ctx->beta/ctx->alpha,t));
216: }
217: PetscCall(STMatSolve(pep->st,q,t));
218: PetscCall(VecScale(t,-1.0/(pep->sfactor*pep->sfactor)));
219: } else {
220: PetscCall(STMatMult(pep->st,1,v,q));
221: PetscCall(STMatMult(pep->st,2,v,t));
222: PetscCall(VecAXPY(q,sigma*pep->sfactor,t));
223: PetscCall(VecScale(q,pep->sfactor));
224: PetscCall(BVMultVec(pep->V,1.0,0.0,v,S+offq+j*lds));
225: PetscCall(STMatMult(pep->st,2,v,t));
226: PetscCall(VecAXPY(q,pep->sfactor*pep->sfactor,t));
227: PetscCall(STMatSolve(pep->st,q,t));
228: PetscCall(VecScale(t,-1.0));
229: }
230: PetscCall(BVRestoreColumn(pep->V,nqt,&t));
232: /* orthogonalize */
233: if (!sinvert) x = S+offq+(j+1)*lds;
234: else x = S+(j+1)*lds;
235: PetscCall(BVOrthogonalizeColumn(pep->V,nqt,x,&norm,&lindep));
237: if (!lindep) {
238: if (!sinvert) *(S+offq+(j+1)*lds+nqt) = norm;
239: else *(S+(j+1)*lds+nqt) = norm;
240: PetscCall(BVScaleColumn(pep->V,nqt,1.0/norm));
241: nqt++;
242: }
243: if (!sinvert) {
244: for (i=0;i<=nqt-1;i++) *(S+(j+1)*lds+i) = *(S+offq+j*lds+i);
245: if (ctx->beta && ctx->alpha) {
246: for (i=0;i<=nqt-1;i++) *(S+(j+1)*lds+offq+i) -= *(S+(j+1)*lds+i)*ctx->beta/ctx->alpha;
247: }
248: } else for (i=0;i<nqt;i++) *(S+(j+1)*lds+offq+i) = *(S+j*lds+i)+sigma*(*(S+(j+1)*lds+i));
249: PetscCall(BVSetActiveColumns(pep->V,0,nqt));
250: PetscCall(MatDenseRestoreArray(MS,&S));
251: PetscCall(BVTensorRestoreFactors(ctx->V,NULL,&MS));
253: /* level-2 orthogonalization */
254: PetscCall(BVOrthogonalizeColumn(ctx->V,j+1,y,&norm,&lindep));
255: a[j] = PetscRealPart(y[j]);
256: omega[j+1] = (norm > 0)?1.0:-1.0;
257: PetscCall(BVScaleColumn(ctx->V,j+1,1.0/norm));
258: b[j] = PetscAbsReal(norm);
260: /* check symmetry */
261: PetscCall(DSGetArrayReal(pep->ds,DS_MAT_T,&f));
262: if (j==k) {
263: for (i=l;i<j-1;i++) y[i] = PetscAbsScalar(y[i])-PetscAbsReal(f[2*ldds+i]);
264: for (i=0;i<l;i++) y[i] = 0.0;
265: }
266: PetscCall(DSRestoreArrayReal(pep->ds,DS_MAT_T,&f));
267: if (j>0) y[j-1] = PetscAbsScalar(y[j-1])-PetscAbsReal(b[j-1]);
268: PetscCall(PetscBLASIntCast(j,&j_));
269: sym = SlepcAbs(BLASnrm2_(&j_,y,&one),sym);
270: fro = SlepcAbs(fro,SlepcAbs(a[j],b[j]));
271: if (j>0) fro = SlepcAbs(fro,b[j-1]);
272: if (sym/fro>PetscMax(PETSC_SQRT_MACHINE_EPSILON,10*pep->tol)) {
273: *symmlost = PETSC_TRUE;
274: *M=j;
275: break;
276: }
277: }
278: PetscCall(BVSetActiveColumns(pep->V,lock,nqt));
279: PetscCall(BVSetActiveColumns(ctx->V,0,*M));
280: PetscCall(PetscFree(y));
281: PetscFunctionReturn(PETSC_SUCCESS);
282: }
284: #if 0
285: static PetscErrorCode PEPSTOARpreKConvergence(PEP pep,PetscInt nv,PetscReal *norm,Vec *w)
286: {
287: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
288: PetscBLASInt n_,one=1;
289: PetscInt lds=2*ctx->ld;
290: PetscReal t1,t2;
291: PetscScalar *S=ctx->S;
293: PetscFunctionBegin;
294: PetscCall(PetscBLASIntCast(nv+2,&n_));
295: t1 = BLASnrm2_(&n_,S+nv*2*ctx->ld,&one);
296: t2 = BLASnrm2_(&n_,S+(nv*2+1)*ctx->ld,&one);
297: *norm = SlepcAbs(t1,t2);
298: PetscCall(BVSetActiveColumns(pep->V,0,nv+2));
299: PetscCall(BVMultVec(pep->V,1.0,0.0,w[1],S+nv*lds));
300: PetscCall(STMatMult(pep->st,0,w[1],w[2]));
301: PetscCall(VecNorm(w[2],NORM_2,&t1));
302: PetscCall(BVMultVec(pep->V,1.0,0.0,w[1],S+ctx->ld+nv*lds));
303: PetscCall(STMatMult(pep->st,2,w[1],w[2]));
304: PetscCall(VecNorm(w[2],NORM_2,&t2));
305: t2 *= pep->sfactor*pep->sfactor;
306: *norm = PetscMax(*norm,SlepcAbs(t1,t2));
307: PetscFunctionReturn(PETSC_SUCCESS);
308: }
309: #endif
311: PetscErrorCode PEPSolve_STOAR(PEP pep)
312: {
313: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
314: PetscInt j,k,l,nv=0,ld,ldds,t,nq=0;
315: PetscInt nconv=0,deg=pep->nmat-1;
316: PetscScalar sigma;
317: PetscReal beta,norm=1.0,*omega,*a,*b;
318: PetscBool breakdown,symmlost=PETSC_FALSE,sinv=PETSC_FALSE,falselock=PETSC_TRUE,flg;
319: Mat MQ,A,D;
320: Vec vomega;
322: PetscFunctionBegin;
323: PetscCall(PetscCitationsRegister(citation,&cited));
324: PetscCall(PEPSTOARSetUpInnerMatrix(pep,&A));
325: PetscCall(BVSetMatrix(ctx->V,A,PETSC_TRUE));
326: PetscCall(MatDestroy(&A));
327: if (ctx->lock) {
328: /* undocumented option to use a cheaper locking instead of the true locking */
329: PetscCall(PetscOptionsGetBool(NULL,NULL,"-pep_stoar_falselocking",&falselock,NULL));
330: }
331: PetscCall(BVGetSizes(pep->V,NULL,NULL,&ld));
332: PetscCall(STGetShift(pep->st,&sigma));
333: PetscCall(STGetTransform(pep->st,&flg));
334: if (pep->sfactor!=1.0) {
335: if (!flg) {
336: pep->target /= pep->sfactor;
337: PetscCall(RGPushScale(pep->rg,1.0/pep->sfactor));
338: PetscCall(STScaleShift(pep->st,1.0/pep->sfactor));
339: sigma /= pep->sfactor;
340: } else {
341: PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv));
342: pep->target = sinv?pep->target*pep->sfactor:pep->target/pep->sfactor;
343: PetscCall(RGPushScale(pep->rg,sinv?pep->sfactor:1.0/pep->sfactor));
344: PetscCall(STScaleShift(pep->st,sinv?pep->sfactor:1.0/pep->sfactor));
345: }
346: }
347: if (flg) sigma = 0.0;
349: /* Get the starting Arnoldi vector */
350: PetscCall(BVTensorBuildFirstColumn(ctx->V,pep->nini));
351: PetscCall(DSSetDimensions(pep->ds,1,PETSC_DETERMINE,PETSC_DETERMINE));
352: PetscCall(BVSetActiveColumns(ctx->V,0,1));
353: PetscCall(DSGetMatAndColumn(pep->ds,DS_MAT_D,0,&D,&vomega));
354: PetscCall(BVGetSignature(ctx->V,vomega));
355: PetscCall(DSRestoreMatAndColumn(pep->ds,DS_MAT_D,0,&D,&vomega));
357: /* Restart loop */
358: l = 0;
359: PetscCall(DSGetLeadingDimension(pep->ds,&ldds));
360: while (pep->reason == PEP_CONVERGED_ITERATING) {
361: pep->its++;
362: PetscCall(DSGetArrayReal(pep->ds,DS_MAT_T,&a));
363: b = a+ldds;
364: PetscCall(DSGetArrayReal(pep->ds,DS_MAT_D,&omega));
366: /* Compute an nv-step Lanczos factorization */
367: nv = PetscMin(pep->nconv+pep->mpd,pep->ncv);
368: PetscCall(DSSetDimensions(pep->ds,nv,pep->nconv,pep->nconv+l));
369: PetscCall(PEPSTOARrun(pep,a,b,omega,pep->nconv+l,&nv,&breakdown,&symmlost,pep->work));
370: beta = b[nv-1];
371: if (symmlost && nv==pep->nconv+l) {
372: pep->reason = PEP_DIVERGED_SYMMETRY_LOST;
373: pep->nconv = nconv;
374: if (falselock || !ctx->lock) {
375: PetscCall(BVSetActiveColumns(ctx->V,0,pep->nconv));
376: PetscCall(BVTensorCompress(ctx->V,0));
377: }
378: break;
379: }
380: PetscCall(DSRestoreArrayReal(pep->ds,DS_MAT_T,&a));
381: PetscCall(DSRestoreArrayReal(pep->ds,DS_MAT_D,&omega));
382: PetscCall(DSSetDimensions(pep->ds,nv,pep->nconv,pep->nconv+l));
383: if (l==0) PetscCall(DSSetState(pep->ds,DS_STATE_INTERMEDIATE));
384: else PetscCall(DSSetState(pep->ds,DS_STATE_RAW));
386: /* Solve projected problem */
387: PetscCall(DSSolve(pep->ds,pep->eigr,pep->eigi));
388: PetscCall(DSSort(pep->ds,pep->eigr,pep->eigi,NULL,NULL,NULL));
389: PetscCall(DSUpdateExtraRow(pep->ds));
390: PetscCall(DSSynchronize(pep->ds,pep->eigr,pep->eigi));
392: /* Check convergence */
393: /* PetscCall(PEPSTOARpreKConvergence(pep,nv,&norm,pep->work));*/
394: norm = 1.0;
395: PetscCall(DSGetDimensions(pep->ds,NULL,NULL,NULL,&t));
396: PetscCall(PEPKrylovConvergence(pep,PETSC_FALSE,pep->nconv,t-pep->nconv,PetscAbsReal(beta)*norm,&k));
397: PetscCall((*pep->stopping)(pep,pep->its,pep->max_it,k,pep->nev,&pep->reason,pep->stoppingctx));
399: /* Update l */
400: if (pep->reason != PEP_CONVERGED_ITERATING || breakdown) l = 0;
401: else {
402: l = PetscMax(1,(PetscInt)((nv-k)/2));
403: l = PetscMin(l,t);
404: PetscCall(DSGetTruncateSize(pep->ds,k,t,&l));
405: if (!breakdown) {
406: /* Prepare the Rayleigh quotient for restart */
407: PetscCall(DSTruncate(pep->ds,k+l,PETSC_FALSE));
408: }
409: }
410: nconv = k;
411: if (!ctx->lock && pep->reason == PEP_CONVERGED_ITERATING && !breakdown) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */
412: if (l) PetscCall(PetscInfo(pep,"Preparing to restart keeping l=%" PetscInt_FMT " vectors\n",l));
414: /* Update S */
415: PetscCall(DSGetMat(pep->ds,DS_MAT_Q,&MQ));
416: PetscCall(BVMultInPlace(ctx->V,MQ,pep->nconv,k+l));
417: PetscCall(DSRestoreMat(pep->ds,DS_MAT_Q,&MQ));
419: /* Copy last column of S */
420: PetscCall(BVCopyColumn(ctx->V,nv,k+l));
421: PetscCall(BVSetActiveColumns(ctx->V,0,k+l));
422: PetscCall(DSSetDimensions(pep->ds,k+l,PETSC_DETERMINE,PETSC_DETERMINE));
423: PetscCall(DSGetMatAndColumn(pep->ds,DS_MAT_D,0,&D,&vomega));
424: PetscCall(BVSetSignature(ctx->V,vomega));
425: PetscCall(DSRestoreMatAndColumn(pep->ds,DS_MAT_D,0,&D,&vomega));
427: if (breakdown && pep->reason == PEP_CONVERGED_ITERATING) {
428: /* stop if breakdown */
429: PetscCall(PetscInfo(pep,"Breakdown TOAR method (it=%" PetscInt_FMT " norm=%g)\n",pep->its,(double)beta));
430: pep->reason = PEP_DIVERGED_BREAKDOWN;
431: }
432: if (pep->reason != PEP_CONVERGED_ITERATING) l--;
433: PetscCall(BVGetActiveColumns(pep->V,NULL,&nq));
434: if (k+l+deg<=nq) {
435: PetscCall(BVSetActiveColumns(ctx->V,pep->nconv,k+l+1));
436: if (!falselock && ctx->lock) PetscCall(BVTensorCompress(ctx->V,k-pep->nconv));
437: else PetscCall(BVTensorCompress(ctx->V,0));
438: }
439: pep->nconv = k;
440: PetscCall(PEPMonitor(pep,pep->its,nconv,pep->eigr,pep->eigi,pep->errest,nv));
441: }
443: if (pep->nconv>0) {
444: PetscCall(BVSetActiveColumns(ctx->V,0,pep->nconv));
445: PetscCall(BVGetActiveColumns(pep->V,NULL,&nq));
446: PetscCall(BVSetActiveColumns(pep->V,0,nq));
447: if (nq>pep->nconv) {
448: PetscCall(BVTensorCompress(ctx->V,pep->nconv));
449: PetscCall(BVSetActiveColumns(pep->V,0,pep->nconv));
450: }
451: }
452: PetscCall(STGetTransform(pep->st,&flg));
453: if (!flg) PetscTryTypeMethod(pep,backtransform);
454: if (pep->sfactor!=1.0) {
455: for (j=0;j<pep->nconv;j++) {
456: pep->eigr[j] *= pep->sfactor;
457: pep->eigi[j] *= pep->sfactor;
458: }
459: }
460: /* restore original values */
461: if (!flg) {
462: pep->target *= pep->sfactor;
463: PetscCall(STScaleShift(pep->st,pep->sfactor));
464: } else {
465: PetscCall(STScaleShift(pep->st,sinv?1.0/pep->sfactor:pep->sfactor));
466: pep->target = (sinv)?pep->target/pep->sfactor:pep->target*pep->sfactor;
467: }
468: if (pep->sfactor!=1.0) PetscCall(RGPopScale(pep->rg));
470: PetscCall(DSTruncate(pep->ds,pep->nconv,PETSC_TRUE));
471: PetscFunctionReturn(PETSC_SUCCESS);
472: }
474: static PetscErrorCode PEPSetFromOptions_STOAR(PEP pep,PetscOptionItems *PetscOptionsObject)
475: {
476: PetscBool flg,lock,b,f1,f2,f3;
477: PetscInt i,j,k;
478: PetscReal array[2]={0,0};
479: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
481: PetscFunctionBegin;
482: PetscOptionsHeadBegin(PetscOptionsObject,"PEP STOAR Options");
484: PetscCall(PetscOptionsBool("-pep_stoar_locking","Choose between locking and non-locking variants","PEPSTOARSetLocking",PETSC_FALSE,&lock,&flg));
485: if (flg) PetscCall(PEPSTOARSetLocking(pep,lock));
487: b = ctx->detect;
488: PetscCall(PetscOptionsBool("-pep_stoar_detect_zeros","Check zeros during factorizations at interval boundaries","PEPSTOARSetDetectZeros",ctx->detect,&b,&flg));
489: if (flg) PetscCall(PEPSTOARSetDetectZeros(pep,b));
491: i = 1;
492: j = k = PETSC_DECIDE;
493: PetscCall(PetscOptionsInt("-pep_stoar_nev","Number of eigenvalues to compute in each subsolve (only for spectrum slicing)","PEPSTOARSetDimensions",20,&i,&f1));
494: PetscCall(PetscOptionsInt("-pep_stoar_ncv","Number of basis vectors in each subsolve (only for spectrum slicing)","PEPSTOARSetDimensions",40,&j,&f2));
495: PetscCall(PetscOptionsInt("-pep_stoar_mpd","Maximum dimension of projected problem in each subsolve (only for spectrum slicing)","PEPSTOARSetDimensions",40,&k,&f3));
496: if (f1 || f2 || f3) PetscCall(PEPSTOARSetDimensions(pep,i,j,k));
498: k = 2;
499: PetscCall(PetscOptionsRealArray("-pep_stoar_linearization","Parameters of the linearization","PEPSTOARSetLinearization",array,&k,&flg));
500: if (flg) PetscCall(PEPSTOARSetLinearization(pep,array[0],array[1]));
502: b = ctx->checket;
503: PetscCall(PetscOptionsBool("-pep_stoar_check_eigenvalue_type","Check eigenvalue type during spectrum slicing","PEPSTOARSetCheckEigenvalueType",ctx->checket,&b,&flg));
504: if (flg) PetscCall(PEPSTOARSetCheckEigenvalueType(pep,b));
506: PetscOptionsHeadEnd();
507: PetscFunctionReturn(PETSC_SUCCESS);
508: }
510: static PetscErrorCode PEPSTOARSetLocking_STOAR(PEP pep,PetscBool lock)
511: {
512: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
514: PetscFunctionBegin;
515: ctx->lock = lock;
516: PetscFunctionReturn(PETSC_SUCCESS);
517: }
519: /*@
520: PEPSTOARSetLocking - Choose between locking and non-locking variants of
521: the STOAR method.
523: Logically Collective
525: Input Parameters:
526: + pep - the eigenproblem solver context
527: - lock - true if the locking variant must be selected
529: Options Database Key:
530: . -pep_stoar_locking - Sets the locking flag
532: Notes:
533: The default is to lock converged eigenpairs when the method restarts.
534: This behaviour can be changed so that all directions are kept in the
535: working subspace even if already converged to working accuracy (the
536: non-locking variant).
538: Level: advanced
540: .seealso: PEPSTOARGetLocking()
541: @*/
542: PetscErrorCode PEPSTOARSetLocking(PEP pep,PetscBool lock)
543: {
544: PetscFunctionBegin;
547: PetscTryMethod(pep,"PEPSTOARSetLocking_C",(PEP,PetscBool),(pep,lock));
548: PetscFunctionReturn(PETSC_SUCCESS);
549: }
551: static PetscErrorCode PEPSTOARGetLocking_STOAR(PEP pep,PetscBool *lock)
552: {
553: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
555: PetscFunctionBegin;
556: *lock = ctx->lock;
557: PetscFunctionReturn(PETSC_SUCCESS);
558: }
560: /*@
561: PEPSTOARGetLocking - Gets the locking flag used in the STOAR method.
563: Not Collective
565: Input Parameter:
566: . pep - the eigenproblem solver context
568: Output Parameter:
569: . lock - the locking flag
571: Level: advanced
573: .seealso: PEPSTOARSetLocking()
574: @*/
575: PetscErrorCode PEPSTOARGetLocking(PEP pep,PetscBool *lock)
576: {
577: PetscFunctionBegin;
579: PetscAssertPointer(lock,2);
580: PetscUseMethod(pep,"PEPSTOARGetLocking_C",(PEP,PetscBool*),(pep,lock));
581: PetscFunctionReturn(PETSC_SUCCESS);
582: }
584: static PetscErrorCode PEPSTOARGetInertias_STOAR(PEP pep,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
585: {
586: PetscInt i,numsh;
587: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
588: PEP_SR sr = ctx->sr;
590: PetscFunctionBegin;
591: PetscCheck(pep->state,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONGSTATE,"Must call PEPSetUp() first");
592: PetscCheck(ctx->sr,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see PEPSetInterval()");
593: switch (pep->state) {
594: case PEP_STATE_INITIAL:
595: break;
596: case PEP_STATE_SETUP:
597: if (n) *n = 2;
598: if (shifts) {
599: PetscCall(PetscMalloc1(2,shifts));
600: (*shifts)[0] = pep->inta;
601: (*shifts)[1] = pep->intb;
602: }
603: if (inertias) {
604: PetscCall(PetscMalloc1(2,inertias));
605: (*inertias)[0] = (sr->dir==1)?sr->inertia0:sr->inertia1;
606: (*inertias)[1] = (sr->dir==1)?sr->inertia1:sr->inertia0;
607: }
608: break;
609: case PEP_STATE_SOLVED:
610: case PEP_STATE_EIGENVECTORS:
611: numsh = ctx->nshifts;
612: if (n) *n = numsh;
613: if (shifts) {
614: PetscCall(PetscMalloc1(numsh,shifts));
615: for (i=0;i<numsh;i++) (*shifts)[i] = ctx->shifts[i];
616: }
617: if (inertias) {
618: PetscCall(PetscMalloc1(numsh,inertias));
619: for (i=0;i<numsh;i++) (*inertias)[i] = ctx->inertias[i];
620: }
621: break;
622: }
623: PetscFunctionReturn(PETSC_SUCCESS);
624: }
626: /*@C
627: PEPSTOARGetInertias - Gets the values of the shifts and their
628: corresponding inertias in case of doing spectrum slicing for a
629: computational interval.
631: Not Collective
633: Input Parameter:
634: . pep - the eigenproblem solver context
636: Output Parameters:
637: + n - number of shifts, including the endpoints of the interval
638: . shifts - the values of the shifts used internally in the solver
639: - inertias - the values of the inertia in each shift
641: Notes:
642: If called after PEPSolve(), all shifts used internally by the solver are
643: returned (including both endpoints and any intermediate ones). If called
644: before PEPSolve() and after PEPSetUp() then only the information of the
645: endpoints of subintervals is available.
647: This function is only available for spectrum slicing runs.
649: The returned arrays should be freed by the user. Can pass NULL in any of
650: the two arrays if not required.
652: Fortran Notes:
653: The calling sequence from Fortran is
654: .vb
655: PEPSTOARGetInertias(pep,n,shifts,inertias,ierr)
656: integer n
657: double precision shifts(*)
658: integer inertias(*)
659: .ve
660: The arrays should be at least of length n. The value of n can be determined
661: by an initial call
662: .vb
663: PEPSTOARGetInertias(pep,n,PETSC_NULL_REAL,PETSC_NULL_INTEGER,ierr)
664: .ve
666: Level: advanced
668: .seealso: PEPSetInterval()
669: @*/
670: PetscErrorCode PEPSTOARGetInertias(PEP pep,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
671: {
672: PetscFunctionBegin;
674: PetscAssertPointer(n,2);
675: PetscUseMethod(pep,"PEPSTOARGetInertias_C",(PEP,PetscInt*,PetscReal**,PetscInt**),(pep,n,shifts,inertias));
676: PetscFunctionReturn(PETSC_SUCCESS);
677: }
679: static PetscErrorCode PEPSTOARSetDetectZeros_STOAR(PEP pep,PetscBool detect)
680: {
681: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
683: PetscFunctionBegin;
684: ctx->detect = detect;
685: pep->state = PEP_STATE_INITIAL;
686: PetscFunctionReturn(PETSC_SUCCESS);
687: }
689: /*@
690: PEPSTOARSetDetectZeros - Sets a flag to enforce detection of
691: zeros during the factorizations throughout the spectrum slicing computation.
693: Logically Collective
695: Input Parameters:
696: + pep - the eigenproblem solver context
697: - detect - check for zeros
699: Options Database Key:
700: . -pep_stoar_detect_zeros - Check for zeros; this takes an optional
701: bool value (0/1/no/yes/true/false)
703: Notes:
704: A zero in the factorization indicates that a shift coincides with an eigenvalue.
706: This flag is turned off by default, and may be necessary in some cases.
707: This feature currently requires an external package for factorizations
708: with support for zero detection, e.g. MUMPS.
710: Level: advanced
712: .seealso: PEPSetInterval()
713: @*/
714: PetscErrorCode PEPSTOARSetDetectZeros(PEP pep,PetscBool detect)
715: {
716: PetscFunctionBegin;
719: PetscTryMethod(pep,"PEPSTOARSetDetectZeros_C",(PEP,PetscBool),(pep,detect));
720: PetscFunctionReturn(PETSC_SUCCESS);
721: }
723: static PetscErrorCode PEPSTOARGetDetectZeros_STOAR(PEP pep,PetscBool *detect)
724: {
725: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
727: PetscFunctionBegin;
728: *detect = ctx->detect;
729: PetscFunctionReturn(PETSC_SUCCESS);
730: }
732: /*@
733: PEPSTOARGetDetectZeros - Gets the flag that enforces zero detection
734: in spectrum slicing.
736: Not Collective
738: Input Parameter:
739: . pep - the eigenproblem solver context
741: Output Parameter:
742: . detect - whether zeros detection is enforced during factorizations
744: Level: advanced
746: .seealso: PEPSTOARSetDetectZeros()
747: @*/
748: PetscErrorCode PEPSTOARGetDetectZeros(PEP pep,PetscBool *detect)
749: {
750: PetscFunctionBegin;
752: PetscAssertPointer(detect,2);
753: PetscUseMethod(pep,"PEPSTOARGetDetectZeros_C",(PEP,PetscBool*),(pep,detect));
754: PetscFunctionReturn(PETSC_SUCCESS);
755: }
757: static PetscErrorCode PEPSTOARSetLinearization_STOAR(PEP pep,PetscReal alpha,PetscReal beta)
758: {
759: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
761: PetscFunctionBegin;
762: PetscCheck(beta!=0.0 || alpha!=0.0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONG,"Parameters alpha and beta cannot be zero simultaneously");
763: ctx->alpha = alpha;
764: ctx->beta = beta;
765: PetscFunctionReturn(PETSC_SUCCESS);
766: }
768: /*@
769: PEPSTOARSetLinearization - Set the coefficients that define
770: the linearization of a quadratic eigenproblem.
772: Logically Collective
774: Input Parameters:
775: + pep - polynomial eigenvalue solver
776: . alpha - first parameter of the linearization
777: - beta - second parameter of the linearization
779: Options Database Key:
780: . -pep_stoar_linearization <alpha,beta> - Sets the coefficients
782: Notes:
783: Cannot pass zero for both alpha and beta. The default values are
784: alpha=1 and beta=0.
786: Level: advanced
788: .seealso: PEPSTOARGetLinearization()
789: @*/
790: PetscErrorCode PEPSTOARSetLinearization(PEP pep,PetscReal alpha,PetscReal beta)
791: {
792: PetscFunctionBegin;
796: PetscTryMethod(pep,"PEPSTOARSetLinearization_C",(PEP,PetscReal,PetscReal),(pep,alpha,beta));
797: PetscFunctionReturn(PETSC_SUCCESS);
798: }
800: static PetscErrorCode PEPSTOARGetLinearization_STOAR(PEP pep,PetscReal *alpha,PetscReal *beta)
801: {
802: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
804: PetscFunctionBegin;
805: if (alpha) *alpha = ctx->alpha;
806: if (beta) *beta = ctx->beta;
807: PetscFunctionReturn(PETSC_SUCCESS);
808: }
810: /*@
811: PEPSTOARGetLinearization - Returns the coefficients that define
812: the linearization of a quadratic eigenproblem.
814: Not Collective
816: Input Parameter:
817: . pep - polynomial eigenvalue solver
819: Output Parameters:
820: + alpha - the first parameter of the linearization
821: - beta - the second parameter of the linearization
823: Level: advanced
825: .seealso: PEPSTOARSetLinearization()
826: @*/
827: PetscErrorCode PEPSTOARGetLinearization(PEP pep,PetscReal *alpha,PetscReal *beta)
828: {
829: PetscFunctionBegin;
831: PetscUseMethod(pep,"PEPSTOARGetLinearization_C",(PEP,PetscReal*,PetscReal*),(pep,alpha,beta));
832: PetscFunctionReturn(PETSC_SUCCESS);
833: }
835: static PetscErrorCode PEPSTOARSetDimensions_STOAR(PEP pep,PetscInt nev,PetscInt ncv,PetscInt mpd)
836: {
837: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
839: PetscFunctionBegin;
840: if (nev != PETSC_CURRENT) {
841: PetscCheck(nev>0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of nev. Must be > 0");
842: ctx->nev = nev;
843: }
844: if (ncv == PETSC_DETERMINE) {
845: ctx->ncv = PETSC_DETERMINE;
846: } else if (ncv != PETSC_CURRENT) {
847: PetscCheck(ncv>0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
848: ctx->ncv = ncv;
849: }
850: if (mpd == PETSC_DETERMINE) {
851: ctx->mpd = PETSC_DETERMINE;
852: } else if (mpd != PETSC_CURRENT) {
853: PetscCheck(mpd>0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of mpd. Must be > 0");
854: ctx->mpd = mpd;
855: }
856: pep->state = PEP_STATE_INITIAL;
857: PetscFunctionReturn(PETSC_SUCCESS);
858: }
860: /*@
861: PEPSTOARSetDimensions - Sets the dimensions used for each subsolve
862: step in case of doing spectrum slicing for a computational interval.
863: The meaning of the parameters is the same as in PEPSetDimensions().
865: Logically Collective
867: Input Parameters:
868: + pep - the eigenproblem solver context
869: . nev - number of eigenvalues to compute
870: . ncv - the maximum dimension of the subspace to be used by the subsolve
871: - mpd - the maximum dimension allowed for the projected problem
873: Options Database Key:
874: + -pep_stoar_nev <nev> - Sets the number of eigenvalues
875: . -pep_stoar_ncv <ncv> - Sets the dimension of the subspace
876: - -pep_stoar_mpd <mpd> - Sets the maximum projected dimension
878: Level: advanced
880: .seealso: PEPSTOARGetDimensions(), PEPSetDimensions(), PEPSetInterval()
881: @*/
882: PetscErrorCode PEPSTOARSetDimensions(PEP pep,PetscInt nev,PetscInt ncv,PetscInt mpd)
883: {
884: PetscFunctionBegin;
889: PetscTryMethod(pep,"PEPSTOARSetDimensions_C",(PEP,PetscInt,PetscInt,PetscInt),(pep,nev,ncv,mpd));
890: PetscFunctionReturn(PETSC_SUCCESS);
891: }
893: static PetscErrorCode PEPSTOARGetDimensions_STOAR(PEP pep,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
894: {
895: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
897: PetscFunctionBegin;
898: if (nev) *nev = ctx->nev;
899: if (ncv) *ncv = ctx->ncv;
900: if (mpd) *mpd = ctx->mpd;
901: PetscFunctionReturn(PETSC_SUCCESS);
902: }
904: /*@
905: PEPSTOARGetDimensions - Gets the dimensions used for each subsolve
906: step in case of doing spectrum slicing for a computational interval.
908: Not Collective
910: Input Parameter:
911: . pep - the eigenproblem solver context
913: Output Parameters:
914: + nev - number of eigenvalues to compute
915: . ncv - the maximum dimension of the subspace to be used by the subsolve
916: - mpd - the maximum dimension allowed for the projected problem
918: Level: advanced
920: .seealso: PEPSTOARSetDimensions()
921: @*/
922: PetscErrorCode PEPSTOARGetDimensions(PEP pep,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
923: {
924: PetscFunctionBegin;
926: PetscUseMethod(pep,"PEPSTOARGetDimensions_C",(PEP,PetscInt*,PetscInt*,PetscInt*),(pep,nev,ncv,mpd));
927: PetscFunctionReturn(PETSC_SUCCESS);
928: }
930: static PetscErrorCode PEPSTOARSetCheckEigenvalueType_STOAR(PEP pep,PetscBool checket)
931: {
932: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
934: PetscFunctionBegin;
935: ctx->checket = checket;
936: pep->state = PEP_STATE_INITIAL;
937: PetscFunctionReturn(PETSC_SUCCESS);
938: }
940: /*@
941: PEPSTOARSetCheckEigenvalueType - Sets a flag to check that all the eigenvalues
942: obtained throughout the spectrum slicing computation have the same definite type.
944: Logically Collective
946: Input Parameters:
947: + pep - the eigenproblem solver context
948: - checket - check eigenvalue type
950: Options Database Key:
951: . -pep_stoar_check_eigenvalue_type - Check eigenvalue type; this takes an optional
952: bool value (0/1/no/yes/true/false)
954: Notes:
955: This option is relevant only for spectrum slicing computations, but it is
956: ignored if the problem type is PEP_HYPERBOLIC.
958: This flag is turned on by default, to guarantee that the computed eigenvalues
959: have the same type (otherwise the computed solution might be wrong). But since
960: the check is computationally quite expensive, the check may be turned off if
961: the user knows for sure that all eigenvalues in the requested interval have
962: the same type.
964: Level: advanced
966: .seealso: PEPSetProblemType(), PEPSetInterval()
967: @*/
968: PetscErrorCode PEPSTOARSetCheckEigenvalueType(PEP pep,PetscBool checket)
969: {
970: PetscFunctionBegin;
973: PetscTryMethod(pep,"PEPSTOARSetCheckEigenvalueType_C",(PEP,PetscBool),(pep,checket));
974: PetscFunctionReturn(PETSC_SUCCESS);
975: }
977: static PetscErrorCode PEPSTOARGetCheckEigenvalueType_STOAR(PEP pep,PetscBool *checket)
978: {
979: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
981: PetscFunctionBegin;
982: *checket = ctx->checket;
983: PetscFunctionReturn(PETSC_SUCCESS);
984: }
986: /*@
987: PEPSTOARGetCheckEigenvalueType - Gets the flag for the eigenvalue type
988: check in spectrum slicing.
990: Not Collective
992: Input Parameter:
993: . pep - the eigenproblem solver context
995: Output Parameter:
996: . checket - whether eigenvalue type must be checked during spectrum slcing
998: Level: advanced
1000: .seealso: PEPSTOARSetCheckEigenvalueType()
1001: @*/
1002: PetscErrorCode PEPSTOARGetCheckEigenvalueType(PEP pep,PetscBool *checket)
1003: {
1004: PetscFunctionBegin;
1006: PetscAssertPointer(checket,2);
1007: PetscUseMethod(pep,"PEPSTOARGetCheckEigenvalueType_C",(PEP,PetscBool*),(pep,checket));
1008: PetscFunctionReturn(PETSC_SUCCESS);
1009: }
1011: static PetscErrorCode PEPView_STOAR(PEP pep,PetscViewer viewer)
1012: {
1013: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
1014: PetscBool isascii;
1016: PetscFunctionBegin;
1017: PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1018: if (isascii) {
1019: PetscCall(PetscViewerASCIIPrintf(viewer," using the %slocking variant\n",ctx->lock?"":"non-"));
1020: PetscCall(PetscViewerASCIIPrintf(viewer," linearization parameters: alpha=%g beta=%g\n",(double)ctx->alpha,(double)ctx->beta));
1021: if (pep->which==PEP_ALL && !ctx->hyperbolic) PetscCall(PetscViewerASCIIPrintf(viewer," checking eigenvalue type: %s\n",ctx->checket?"enabled":"disabled"));
1022: }
1023: PetscFunctionReturn(PETSC_SUCCESS);
1024: }
1026: static PetscErrorCode PEPReset_STOAR(PEP pep)
1027: {
1028: PetscFunctionBegin;
1029: if (pep->which==PEP_ALL) PetscCall(PEPReset_STOAR_QSlice(pep));
1030: PetscFunctionReturn(PETSC_SUCCESS);
1031: }
1033: static PetscErrorCode PEPDestroy_STOAR(PEP pep)
1034: {
1035: PEP_STOAR *ctx = (PEP_STOAR*)pep->data;
1037: PetscFunctionBegin;
1038: PetscCall(BVDestroy(&ctx->V));
1039: PetscCall(PetscFree(pep->data));
1040: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLocking_C",NULL));
1041: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLocking_C",NULL));
1042: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDetectZeros_C",NULL));
1043: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDetectZeros_C",NULL));
1044: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetInertias_C",NULL));
1045: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDimensions_C",NULL));
1046: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDimensions_C",NULL));
1047: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLinearization_C",NULL));
1048: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLinearization_C",NULL));
1049: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetCheckEigenvalueType_C",NULL));
1050: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetCheckEigenvalueType_C",NULL));
1051: PetscFunctionReturn(PETSC_SUCCESS);
1052: }
1054: SLEPC_EXTERN PetscErrorCode PEPCreate_STOAR(PEP pep)
1055: {
1056: PEP_STOAR *ctx;
1058: PetscFunctionBegin;
1059: PetscCall(PetscNew(&ctx));
1060: pep->data = (void*)ctx;
1062: pep->lineariz = PETSC_TRUE;
1063: ctx->lock = PETSC_TRUE;
1064: ctx->nev = 1;
1065: ctx->ncv = PETSC_DETERMINE;
1066: ctx->mpd = PETSC_DETERMINE;
1067: ctx->alpha = 1.0;
1068: ctx->beta = 0.0;
1069: ctx->checket = PETSC_TRUE;
1071: pep->ops->setup = PEPSetUp_STOAR;
1072: pep->ops->setfromoptions = PEPSetFromOptions_STOAR;
1073: pep->ops->destroy = PEPDestroy_STOAR;
1074: pep->ops->view = PEPView_STOAR;
1075: pep->ops->backtransform = PEPBackTransform_Default;
1076: pep->ops->computevectors = PEPComputeVectors_Default;
1077: pep->ops->extractvectors = PEPExtractVectors_TOAR;
1078: pep->ops->reset = PEPReset_STOAR;
1080: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLocking_C",PEPSTOARSetLocking_STOAR));
1081: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLocking_C",PEPSTOARGetLocking_STOAR));
1082: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDetectZeros_C",PEPSTOARSetDetectZeros_STOAR));
1083: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDetectZeros_C",PEPSTOARGetDetectZeros_STOAR));
1084: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetInertias_C",PEPSTOARGetInertias_STOAR));
1085: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetDimensions_C",PEPSTOARGetDimensions_STOAR));
1086: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetDimensions_C",PEPSTOARSetDimensions_STOAR));
1087: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetLinearization_C",PEPSTOARSetLinearization_STOAR));
1088: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetLinearization_C",PEPSTOARGetLinearization_STOAR));
1089: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARSetCheckEigenvalueType_C",PEPSTOARSetCheckEigenvalueType_STOAR));
1090: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPSTOARGetCheckEigenvalueType_C",PEPSTOARGetCheckEigenvalueType_STOAR));
1091: PetscFunctionReturn(PETSC_SUCCESS);
1092: }