Actual source code: linear.c
slepc-main 2024-12-17
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: Explicit linearization for polynomial eigenproblems
12: */
14: #include <slepc/private/pepimpl.h>
15: #include "linear.h"
17: static PetscErrorCode MatMult_Linear_Shift(Mat M,Vec x,Vec y)
18: {
19: PEP_LINEAR *ctx;
20: PEP pep;
21: const PetscScalar *px;
22: PetscScalar *py,a,sigma=0.0;
23: PetscInt nmat,deg,i,m;
24: Vec x1,x2,x3,y1,aux;
25: PetscReal *ca,*cb,*cg;
26: PetscBool flg;
28: PetscFunctionBegin;
29: PetscCall(MatShellGetContext(M,&ctx));
30: pep = ctx->pep;
31: PetscCall(STGetTransform(pep->st,&flg));
32: if (!flg) PetscCall(STGetShift(pep->st,&sigma));
33: nmat = pep->nmat;
34: deg = nmat-1;
35: m = pep->nloc;
36: ca = pep->pbc;
37: cb = pep->pbc+nmat;
38: cg = pep->pbc+2*nmat;
39: x1=ctx->w[0];x2=ctx->w[1];x3=ctx->w[2];y1=ctx->w[3];aux=ctx->w[4];
41: PetscCall(VecSet(y,0.0));
42: PetscCall(VecGetArrayRead(x,&px));
43: PetscCall(VecGetArray(y,&py));
44: a = 1.0;
46: /* first block */
47: PetscCall(VecPlaceArray(x2,px));
48: PetscCall(VecPlaceArray(x3,px+m));
49: PetscCall(VecPlaceArray(y1,py));
50: PetscCall(VecAXPY(y1,cb[0]-sigma,x2));
51: PetscCall(VecAXPY(y1,ca[0],x3));
52: PetscCall(VecResetArray(x2));
53: PetscCall(VecResetArray(x3));
54: PetscCall(VecResetArray(y1));
56: /* inner blocks */
57: for (i=1;i<deg-1;i++) {
58: PetscCall(VecPlaceArray(x1,px+(i-1)*m));
59: PetscCall(VecPlaceArray(x2,px+i*m));
60: PetscCall(VecPlaceArray(x3,px+(i+1)*m));
61: PetscCall(VecPlaceArray(y1,py+i*m));
62: PetscCall(VecAXPY(y1,cg[i],x1));
63: PetscCall(VecAXPY(y1,cb[i]-sigma,x2));
64: PetscCall(VecAXPY(y1,ca[i],x3));
65: PetscCall(VecResetArray(x1));
66: PetscCall(VecResetArray(x2));
67: PetscCall(VecResetArray(x3));
68: PetscCall(VecResetArray(y1));
69: }
71: /* last block */
72: PetscCall(VecPlaceArray(y1,py+(deg-1)*m));
73: for (i=0;i<deg;i++) {
74: PetscCall(VecPlaceArray(x1,px+i*m));
75: PetscCall(STMatMult(pep->st,i,x1,aux));
76: PetscCall(VecAXPY(y1,a,aux));
77: PetscCall(VecResetArray(x1));
78: a *= pep->sfactor;
79: }
80: PetscCall(VecCopy(y1,aux));
81: PetscCall(STMatSolve(pep->st,aux,y1));
82: PetscCall(VecScale(y1,-ca[deg-1]/a));
83: PetscCall(VecPlaceArray(x1,px+(deg-2)*m));
84: PetscCall(VecPlaceArray(x2,px+(deg-1)*m));
85: PetscCall(VecAXPY(y1,cg[deg-1],x1));
86: PetscCall(VecAXPY(y1,cb[deg-1]-sigma,x2));
87: PetscCall(VecResetArray(x1));
88: PetscCall(VecResetArray(x2));
89: PetscCall(VecResetArray(y1));
91: PetscCall(VecRestoreArrayRead(x,&px));
92: PetscCall(VecRestoreArray(y,&py));
93: PetscFunctionReturn(PETSC_SUCCESS);
94: }
96: static PetscErrorCode MatMult_Linear_Sinvert(Mat M,Vec x,Vec y)
97: {
98: PEP_LINEAR *ctx;
99: PEP pep;
100: const PetscScalar *px;
101: PetscScalar *py,a,sigma,t=1.0,tp=0.0,tt;
102: PetscInt nmat,deg,i,m;
103: Vec x1,y1,y2,y3,aux,aux2;
104: PetscReal *ca,*cb,*cg;
106: PetscFunctionBegin;
107: PetscCall(MatShellGetContext(M,&ctx));
108: pep = ctx->pep;
109: nmat = pep->nmat;
110: deg = nmat-1;
111: m = pep->nloc;
112: ca = pep->pbc;
113: cb = pep->pbc+nmat;
114: cg = pep->pbc+2*nmat;
115: x1=ctx->w[0];y1=ctx->w[1];y2=ctx->w[2];y3=ctx->w[3];aux=ctx->w[4];aux2=ctx->w[5];
116: PetscCall(EPSGetTarget(ctx->eps,&sigma));
117: PetscCall(VecSet(y,0.0));
118: PetscCall(VecGetArrayRead(x,&px));
119: PetscCall(VecGetArray(y,&py));
120: a = pep->sfactor;
122: /* first block */
123: PetscCall(VecPlaceArray(x1,px));
124: PetscCall(VecPlaceArray(y1,py+m));
125: PetscCall(VecCopy(x1,y1));
126: PetscCall(VecScale(y1,1.0/ca[0]));
127: PetscCall(VecResetArray(x1));
128: PetscCall(VecResetArray(y1));
130: /* second block */
131: if (deg>2) {
132: PetscCall(VecPlaceArray(x1,px+m));
133: PetscCall(VecPlaceArray(y1,py+m));
134: PetscCall(VecPlaceArray(y2,py+2*m));
135: PetscCall(VecCopy(x1,y2));
136: PetscCall(VecAXPY(y2,sigma-cb[1],y1));
137: PetscCall(VecScale(y2,1.0/ca[1]));
138: PetscCall(VecResetArray(x1));
139: PetscCall(VecResetArray(y1));
140: PetscCall(VecResetArray(y2));
141: }
143: /* inner blocks */
144: for (i=2;i<deg-1;i++) {
145: PetscCall(VecPlaceArray(x1,px+i*m));
146: PetscCall(VecPlaceArray(y1,py+(i-1)*m));
147: PetscCall(VecPlaceArray(y2,py+i*m));
148: PetscCall(VecPlaceArray(y3,py+(i+1)*m));
149: PetscCall(VecCopy(x1,y3));
150: PetscCall(VecAXPY(y3,sigma-cb[i],y2));
151: PetscCall(VecAXPY(y3,-cg[i],y1));
152: PetscCall(VecScale(y3,1.0/ca[i]));
153: PetscCall(VecResetArray(x1));
154: PetscCall(VecResetArray(y1));
155: PetscCall(VecResetArray(y2));
156: PetscCall(VecResetArray(y3));
157: }
159: /* last block */
160: PetscCall(VecPlaceArray(y1,py));
161: for (i=0;i<deg-2;i++) {
162: PetscCall(VecPlaceArray(y2,py+(i+1)*m));
163: PetscCall(STMatMult(pep->st,i+1,y2,aux));
164: PetscCall(VecAXPY(y1,a,aux));
165: PetscCall(VecResetArray(y2));
166: a *= pep->sfactor;
167: }
168: i = deg-2;
169: PetscCall(VecPlaceArray(y2,py+(i+1)*m));
170: PetscCall(VecPlaceArray(y3,py+i*m));
171: PetscCall(VecCopy(y2,aux2));
172: PetscCall(VecAXPY(aux2,cg[i+1]/ca[i+1],y3));
173: PetscCall(STMatMult(pep->st,i+1,aux2,aux));
174: PetscCall(VecAXPY(y1,a,aux));
175: PetscCall(VecResetArray(y2));
176: PetscCall(VecResetArray(y3));
177: a *= pep->sfactor;
178: i = deg-1;
179: PetscCall(VecPlaceArray(x1,px+i*m));
180: PetscCall(VecPlaceArray(y3,py+i*m));
181: PetscCall(VecCopy(x1,aux2));
182: PetscCall(VecAXPY(aux2,sigma-cb[i],y3));
183: PetscCall(VecScale(aux2,1.0/ca[i]));
184: PetscCall(STMatMult(pep->st,i+1,aux2,aux));
185: PetscCall(VecAXPY(y1,a,aux));
186: PetscCall(VecResetArray(x1));
187: PetscCall(VecResetArray(y3));
189: PetscCall(VecCopy(y1,aux));
190: PetscCall(STMatSolve(pep->st,aux,y1));
191: PetscCall(VecScale(y1,-1.0));
193: /* final update */
194: for (i=1;i<deg;i++) {
195: PetscCall(VecPlaceArray(y2,py+i*m));
196: tt = t;
197: t = ((sigma-cb[i-1])*t-cg[i-1]*tp)/ca[i-1]; /* i-th basis polynomial */
198: tp = tt;
199: PetscCall(VecAXPY(y2,t,y1));
200: PetscCall(VecResetArray(y2));
201: }
202: PetscCall(VecResetArray(y1));
204: PetscCall(VecRestoreArrayRead(x,&px));
205: PetscCall(VecRestoreArray(y,&py));
206: PetscFunctionReturn(PETSC_SUCCESS);
207: }
209: static PetscErrorCode BackTransform_Linear(ST st,PetscInt n,PetscScalar *eigr,PetscScalar *eigi)
210: {
211: PEP_LINEAR *ctx;
212: ST stctx;
214: PetscFunctionBegin;
215: PetscCall(STShellGetContext(st,&ctx));
216: PetscCall(PEPGetST(ctx->pep,&stctx));
217: PetscCall(STBackTransform(stctx,n,eigr,eigi));
218: PetscFunctionReturn(PETSC_SUCCESS);
219: }
221: /*
222: Dummy backtransform operation
223: */
224: static PetscErrorCode BackTransform_Skip(ST st,PetscInt n,PetscScalar *eigr,PetscScalar *eigi)
225: {
226: PetscFunctionBegin;
227: PetscFunctionReturn(PETSC_SUCCESS);
228: }
230: static PetscErrorCode Apply_Linear(ST st,Vec x,Vec y)
231: {
232: PEP_LINEAR *ctx;
234: PetscFunctionBegin;
235: PetscCall(STShellGetContext(st,&ctx));
236: PetscCall(MatMult(ctx->A,x,y));
237: PetscFunctionReturn(PETSC_SUCCESS);
238: }
240: static PetscErrorCode PEPSetUp_Linear(PEP pep)
241: {
242: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
243: ST st;
244: PetscInt i=0,deg=pep->nmat-1;
245: EPSWhich which = EPS_LARGEST_MAGNITUDE;
246: EPSProblemType ptype;
247: PetscBool trackall,istrivial,transf,sinv,ks;
248: PetscScalar sigma,*epsarray,*peparray;
249: Vec veps,w=NULL;
250: /* function tables */
251: PetscErrorCode (*fcreate[][2])(MPI_Comm,PEP_LINEAR*,Mat*) = {
252: { MatCreateExplicit_Linear_NA, MatCreateExplicit_Linear_NB },
253: { MatCreateExplicit_Linear_SA, MatCreateExplicit_Linear_SB },
254: { MatCreateExplicit_Linear_HA, MatCreateExplicit_Linear_HB },
255: };
257: PetscFunctionBegin;
258: PEPCheckShiftSinvert(pep);
259: PEPCheckUnsupported(pep,PEP_FEATURE_STOPPING);
260: PEPCheckIgnored(pep,PEP_FEATURE_CONVERGENCE);
261: PetscCall(STGetTransform(pep->st,&transf));
262: PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv));
263: if (!pep->which) PetscCall(PEPSetWhichEigenpairs_Default(pep));
264: PetscCheck(pep->which!=PEP_ALL,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"This solver does not support computing all eigenvalues");
265: PetscCall(STSetUp(pep->st));
266: if (!ctx->eps) PetscCall(PEPLinearGetEPS(pep,&ctx->eps));
267: PetscCall(EPSGetST(ctx->eps,&st));
268: if (!transf && !ctx->usereps) PetscCall(EPSSetTarget(ctx->eps,pep->target));
269: if (sinv && !transf && !ctx->usereps) PetscCall(STSetDefaultShift(st,pep->target));
270: /* compute scale factor if not set by user */
271: PetscCall(PEPComputeScaleFactor(pep));
273: if (ctx->explicitmatrix) {
274: PEPCheckQuadraticCondition(pep,PETSC_TRUE," (with explicit matrix)");
275: PEPCheckUnsupportedCondition(pep,PEP_FEATURE_NONMONOMIAL,PETSC_TRUE," (with explicit matrix)");
276: PetscCheck(!transf,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Explicit matrix option is not implemented with st-transform flag active");
277: PetscCheck(pep->scale!=PEP_SCALE_DIAGONAL && pep->scale!=PEP_SCALE_BOTH,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Diagonal scaling not allowed in PEPLINEAR with explicit matrices");
278: if (sinv && !transf) PetscCall(STSetType(st,STSINVERT));
279: PetscCall(RGPushScale(pep->rg,1.0/pep->sfactor));
280: PetscCall(STGetMatrixTransformed(pep->st,0,&ctx->K));
281: PetscCall(STGetMatrixTransformed(pep->st,1,&ctx->C));
282: PetscCall(STGetMatrixTransformed(pep->st,2,&ctx->M));
283: ctx->sfactor = pep->sfactor;
284: ctx->dsfactor = pep->dsfactor;
286: PetscCall(MatDestroy(&ctx->A));
287: PetscCall(MatDestroy(&ctx->B));
288: PetscCall(VecDestroy(&ctx->w[0]));
289: PetscCall(VecDestroy(&ctx->w[1]));
290: PetscCall(VecDestroy(&ctx->w[2]));
291: PetscCall(VecDestroy(&ctx->w[3]));
293: switch (pep->problem_type) {
294: case PEP_GENERAL: i = 0; break;
295: case PEP_HERMITIAN:
296: case PEP_HYPERBOLIC: i = 1; break;
297: case PEP_GYROSCOPIC: i = 2; break;
298: }
300: PetscCall((*fcreate[i][0])(PetscObjectComm((PetscObject)pep),ctx,&ctx->A));
301: PetscCall((*fcreate[i][1])(PetscObjectComm((PetscObject)pep),ctx,&ctx->B));
303: } else { /* implicit matrix */
304: PetscCheck(pep->problem_type==PEP_GENERAL,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Must use the explicit matrix option if problem type is not general");
305: if (!((PetscObject)ctx->eps)->type_name) PetscCall(EPSSetType(ctx->eps,EPSKRYLOVSCHUR));
306: else {
307: PetscCall(PetscObjectTypeCompare((PetscObject)ctx->eps,EPSKRYLOVSCHUR,&ks));
308: PetscCheck(ks,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Implicit matrix option only implemented for Krylov-Schur");
309: }
310: PetscCheck(ctx->alpha==1.0 && ctx->beta==0.0,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Implicit matrix option does not support setting alpha,beta parameters of the linearization");
311: PetscCall(STSetType(st,STSHELL));
312: PetscCall(STShellSetContext(st,ctx));
313: if (!transf) PetscCall(STShellSetBackTransform(st,BackTransform_Linear));
314: else PetscCall(STShellSetBackTransform(st,BackTransform_Skip));
315: PetscCall(MatCreateVecsEmpty(pep->A[0],&ctx->w[0],&ctx->w[1]));
316: PetscCall(MatCreateVecsEmpty(pep->A[0],&ctx->w[2],&ctx->w[3]));
317: PetscCall(MatCreateVecs(pep->A[0],&ctx->w[4],&ctx->w[5]));
318: PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pep),deg*pep->nloc,deg*pep->nloc,deg*pep->n,deg*pep->n,ctx,&ctx->A));
319: if (sinv && !transf) PetscCall(MatShellSetOperation(ctx->A,MATOP_MULT,(void(*)(void))MatMult_Linear_Sinvert));
320: else PetscCall(MatShellSetOperation(ctx->A,MATOP_MULT,(void(*)(void))MatMult_Linear_Shift));
321: PetscCall(STShellSetApply(st,Apply_Linear));
322: ctx->pep = pep;
324: PetscCall(PEPBasisCoefficients(pep,pep->pbc));
325: if (!transf) {
326: PetscCall(PetscMalloc1(pep->nmat,&pep->solvematcoeffs));
327: if (sinv) PetscCall(PEPEvaluateBasis(pep,pep->target,0,pep->solvematcoeffs,NULL));
328: else {
329: for (i=0;i<deg;i++) pep->solvematcoeffs[i] = 0.0;
330: pep->solvematcoeffs[deg] = 1.0;
331: }
332: PetscCall(STScaleShift(pep->st,1.0/pep->sfactor));
333: PetscCall(RGPushScale(pep->rg,1.0/pep->sfactor));
334: }
335: if (pep->sfactor!=1.0) {
336: for (i=0;i<pep->nmat;i++) {
337: pep->pbc[pep->nmat+i] /= pep->sfactor;
338: pep->pbc[2*pep->nmat+i] /= pep->sfactor*pep->sfactor;
339: }
340: }
341: }
343: PetscCall(EPSSetOperators(ctx->eps,ctx->A,ctx->B));
344: PetscCall(EPSGetProblemType(ctx->eps,&ptype));
345: if (!ptype) {
346: if (ctx->explicitmatrix) PetscCall(EPSSetProblemType(ctx->eps,EPS_GNHEP));
347: else PetscCall(EPSSetProblemType(ctx->eps,EPS_NHEP));
348: }
349: if (!ctx->usereps) {
350: if (transf) which = EPS_LARGEST_MAGNITUDE;
351: else {
352: switch (pep->which) {
353: case PEP_LARGEST_MAGNITUDE: which = EPS_LARGEST_MAGNITUDE; break;
354: case PEP_SMALLEST_MAGNITUDE: which = EPS_SMALLEST_MAGNITUDE; break;
355: case PEP_LARGEST_REAL: which = EPS_LARGEST_REAL; break;
356: case PEP_SMALLEST_REAL: which = EPS_SMALLEST_REAL; break;
357: case PEP_LARGEST_IMAGINARY: which = EPS_LARGEST_IMAGINARY; break;
358: case PEP_SMALLEST_IMAGINARY: which = EPS_SMALLEST_IMAGINARY; break;
359: case PEP_TARGET_MAGNITUDE: which = EPS_TARGET_MAGNITUDE; break;
360: case PEP_TARGET_REAL: which = EPS_TARGET_REAL; break;
361: case PEP_TARGET_IMAGINARY: which = EPS_TARGET_IMAGINARY; break;
362: case PEP_ALL: which = EPS_ALL; break;
363: case PEP_WHICH_USER: which = EPS_WHICH_USER;
364: PetscCall(EPSSetEigenvalueComparison(ctx->eps,pep->sc->comparison,pep->sc->comparisonctx));
365: break;
366: }
367: }
368: PetscCall(EPSSetWhichEigenpairs(ctx->eps,which));
370: PetscCall(EPSSetDimensions(ctx->eps,pep->nev,pep->ncv,pep->mpd));
371: PetscCall(EPSSetTolerances(ctx->eps,SlepcDefaultTol(pep->tol),pep->max_it));
372: }
373: PetscCall(RGIsTrivial(pep->rg,&istrivial));
374: if (!istrivial) {
375: PetscCheck(!transf,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"PEPLINEAR does not support a nontrivial region with st-transform");
376: PetscCall(EPSSetRG(ctx->eps,pep->rg));
377: }
378: /* Transfer the trackall option from pep to eps */
379: PetscCall(PEPGetTrackAll(pep,&trackall));
380: PetscCall(EPSSetTrackAll(ctx->eps,trackall));
382: /* temporary change of target */
383: if (pep->sfactor!=1.0) {
384: PetscCall(EPSGetTarget(ctx->eps,&sigma));
385: PetscCall(EPSSetTarget(ctx->eps,sigma/pep->sfactor));
386: }
388: /* process initial vector */
389: if (pep->nini<0) {
390: PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)ctx->eps),deg*pep->nloc,deg*pep->n,&veps));
391: PetscCall(VecGetArray(veps,&epsarray));
392: for (i=0;i<deg;i++) {
393: if (i<-pep->nini) {
394: PetscCall(VecGetArray(pep->IS[i],&peparray));
395: PetscCall(PetscArraycpy(epsarray+i*pep->nloc,peparray,pep->nloc));
396: PetscCall(VecRestoreArray(pep->IS[i],&peparray));
397: } else {
398: if (!w) PetscCall(VecDuplicate(pep->IS[0],&w));
399: PetscCall(VecSetRandom(w,NULL));
400: PetscCall(VecGetArray(w,&peparray));
401: PetscCall(PetscArraycpy(epsarray+i*pep->nloc,peparray,pep->nloc));
402: PetscCall(VecRestoreArray(w,&peparray));
403: }
404: }
405: PetscCall(VecRestoreArray(veps,&epsarray));
406: PetscCall(EPSSetInitialSpace(ctx->eps,1,&veps));
407: PetscCall(VecDestroy(&veps));
408: PetscCall(VecDestroy(&w));
409: PetscCall(SlepcBasisDestroy_Private(&pep->nini,&pep->IS));
410: }
412: PetscCall(EPSSetUp(ctx->eps));
413: PetscCall(EPSGetDimensions(ctx->eps,NULL,&pep->ncv,&pep->mpd));
414: PetscCall(EPSGetTolerances(ctx->eps,NULL,&pep->max_it));
415: PetscCall(PEPAllocateSolution(pep,0));
416: PetscFunctionReturn(PETSC_SUCCESS);
417: }
419: /*
420: PEPLinearExtract_Residual - Auxiliary routine that copies the solution of the
421: linear eigenproblem to the PEP object. The eigenvector of the generalized
422: problem is supposed to be
423: z = [ x ]
424: [ l*x ]
425: The eigenvector is taken from z(1:n) or z(n+1:2*n) depending on the explicitly
426: computed residual norm.
427: Finally, x is normalized so that ||x||_2 = 1.
428: */
429: static PetscErrorCode PEPLinearExtract_Residual(PEP pep,EPS eps)
430: {
431: PetscInt i,k;
432: const PetscScalar *px;
433: PetscScalar *er=pep->eigr,*ei=pep->eigi;
434: PetscReal rn1,rn2;
435: Vec xr,xi=NULL,wr;
436: Mat A;
437: #if !defined(PETSC_USE_COMPLEX)
438: Vec wi;
439: const PetscScalar *py;
440: #endif
442: PetscFunctionBegin;
443: #if defined(PETSC_USE_COMPLEX)
444: PetscCall(PEPSetWorkVecs(pep,2));
445: #else
446: PetscCall(PEPSetWorkVecs(pep,4));
447: #endif
448: PetscCall(EPSGetOperators(eps,&A,NULL));
449: PetscCall(MatCreateVecs(A,&xr,NULL));
450: PetscCall(MatCreateVecsEmpty(pep->A[0],&wr,NULL));
451: #if !defined(PETSC_USE_COMPLEX)
452: PetscCall(VecDuplicate(xr,&xi));
453: PetscCall(VecDuplicateEmpty(wr,&wi));
454: #endif
455: for (i=0;i<pep->nconv;i++) {
456: PetscCall(EPSGetEigenpair(eps,i,NULL,NULL,xr,xi));
457: #if !defined(PETSC_USE_COMPLEX)
458: if (ei[i]!=0.0) { /* complex conjugate pair */
459: PetscCall(VecGetArrayRead(xr,&px));
460: PetscCall(VecGetArrayRead(xi,&py));
461: PetscCall(VecPlaceArray(wr,px));
462: PetscCall(VecPlaceArray(wi,py));
463: PetscCall(VecNormalizeComplex(wr,wi,PETSC_TRUE,NULL));
464: PetscCall(PEPComputeResidualNorm_Private(pep,er[i],ei[i],wr,wi,pep->work,&rn1));
465: PetscCall(BVInsertVec(pep->V,i,wr));
466: PetscCall(BVInsertVec(pep->V,i+1,wi));
467: for (k=1;k<pep->nmat-1;k++) {
468: PetscCall(VecResetArray(wr));
469: PetscCall(VecResetArray(wi));
470: PetscCall(VecPlaceArray(wr,px+k*pep->nloc));
471: PetscCall(VecPlaceArray(wi,py+k*pep->nloc));
472: PetscCall(VecNormalizeComplex(wr,wi,PETSC_TRUE,NULL));
473: PetscCall(PEPComputeResidualNorm_Private(pep,er[i],ei[i],wr,wi,pep->work,&rn2));
474: if (rn1>rn2) {
475: PetscCall(BVInsertVec(pep->V,i,wr));
476: PetscCall(BVInsertVec(pep->V,i+1,wi));
477: rn1 = rn2;
478: }
479: }
480: PetscCall(VecResetArray(wr));
481: PetscCall(VecResetArray(wi));
482: PetscCall(VecRestoreArrayRead(xr,&px));
483: PetscCall(VecRestoreArrayRead(xi,&py));
484: i++;
485: } else /* real eigenvalue */
486: #endif
487: {
488: PetscCall(VecGetArrayRead(xr,&px));
489: PetscCall(VecPlaceArray(wr,px));
490: PetscCall(VecNormalizeComplex(wr,NULL,PETSC_FALSE,NULL));
491: PetscCall(PEPComputeResidualNorm_Private(pep,er[i],ei[i],wr,NULL,pep->work,&rn1));
492: PetscCall(BVInsertVec(pep->V,i,wr));
493: for (k=1;k<pep->nmat-1;k++) {
494: PetscCall(VecResetArray(wr));
495: PetscCall(VecPlaceArray(wr,px+k*pep->nloc));
496: PetscCall(VecNormalizeComplex(wr,NULL,PETSC_FALSE,NULL));
497: PetscCall(PEPComputeResidualNorm_Private(pep,er[i],ei[i],wr,NULL,pep->work,&rn2));
498: if (rn1>rn2) {
499: PetscCall(BVInsertVec(pep->V,i,wr));
500: rn1 = rn2;
501: }
502: }
503: PetscCall(VecResetArray(wr));
504: PetscCall(VecRestoreArrayRead(xr,&px));
505: }
506: }
507: PetscCall(VecDestroy(&wr));
508: PetscCall(VecDestroy(&xr));
509: #if !defined(PETSC_USE_COMPLEX)
510: PetscCall(VecDestroy(&wi));
511: PetscCall(VecDestroy(&xi));
512: #endif
513: PetscFunctionReturn(PETSC_SUCCESS);
514: }
516: /*
517: PEPLinearExtract_None - Same as PEPLinearExtract_Norm but always takes
518: the first block.
519: */
520: static PetscErrorCode PEPLinearExtract_None(PEP pep,EPS eps)
521: {
522: PetscInt i;
523: const PetscScalar *px;
524: Mat A;
525: Vec xr,xi=NULL,w;
526: #if !defined(PETSC_USE_COMPLEX)
527: PetscScalar *ei=pep->eigi;
528: #endif
530: PetscFunctionBegin;
531: PetscCall(EPSGetOperators(eps,&A,NULL));
532: PetscCall(MatCreateVecs(A,&xr,NULL));
533: #if !defined(PETSC_USE_COMPLEX)
534: PetscCall(VecDuplicate(xr,&xi));
535: #endif
536: PetscCall(MatCreateVecsEmpty(pep->A[0],&w,NULL));
537: for (i=0;i<pep->nconv;i++) {
538: PetscCall(EPSGetEigenvector(eps,i,xr,xi));
539: #if !defined(PETSC_USE_COMPLEX)
540: if (ei[i]!=0.0) { /* complex conjugate pair */
541: PetscCall(VecGetArrayRead(xr,&px));
542: PetscCall(VecPlaceArray(w,px));
543: PetscCall(BVInsertVec(pep->V,i,w));
544: PetscCall(VecResetArray(w));
545: PetscCall(VecRestoreArrayRead(xr,&px));
546: PetscCall(VecGetArrayRead(xi,&px));
547: PetscCall(VecPlaceArray(w,px));
548: PetscCall(BVInsertVec(pep->V,i+1,w));
549: PetscCall(VecResetArray(w));
550: PetscCall(VecRestoreArrayRead(xi,&px));
551: i++;
552: } else /* real eigenvalue */
553: #endif
554: {
555: PetscCall(VecGetArrayRead(xr,&px));
556: PetscCall(VecPlaceArray(w,px));
557: PetscCall(BVInsertVec(pep->V,i,w));
558: PetscCall(VecResetArray(w));
559: PetscCall(VecRestoreArrayRead(xr,&px));
560: }
561: }
562: PetscCall(VecDestroy(&w));
563: PetscCall(VecDestroy(&xr));
564: #if !defined(PETSC_USE_COMPLEX)
565: PetscCall(VecDestroy(&xi));
566: #endif
567: PetscFunctionReturn(PETSC_SUCCESS);
568: }
570: /*
571: PEPLinearExtract_Norm - Auxiliary routine that copies the solution of the
572: linear eigenproblem to the PEP object. The eigenvector of the generalized
573: problem is supposed to be
574: z = [ x ]
575: [ l*x ]
576: If |l|<1.0, the eigenvector is taken from z(1:n), otherwise from z(n+1:2*n).
577: Finally, x is normalized so that ||x||_2 = 1.
578: */
579: static PetscErrorCode PEPLinearExtract_Norm(PEP pep,EPS eps)
580: {
581: PetscInt i,offset;
582: const PetscScalar *px;
583: PetscScalar *er=pep->eigr;
584: Mat A;
585: Vec xr,xi=NULL,w;
586: #if !defined(PETSC_USE_COMPLEX)
587: PetscScalar *ei=pep->eigi;
588: #endif
590: PetscFunctionBegin;
591: PetscCall(EPSGetOperators(eps,&A,NULL));
592: PetscCall(MatCreateVecs(A,&xr,NULL));
593: #if !defined(PETSC_USE_COMPLEX)
594: PetscCall(VecDuplicate(xr,&xi));
595: #endif
596: PetscCall(MatCreateVecsEmpty(pep->A[0],&w,NULL));
597: for (i=0;i<pep->nconv;i++) {
598: PetscCall(EPSGetEigenpair(eps,i,NULL,NULL,xr,xi));
599: if (SlepcAbsEigenvalue(er[i],ei[i])>1.0) offset = (pep->nmat-2)*pep->nloc;
600: else offset = 0;
601: #if !defined(PETSC_USE_COMPLEX)
602: if (ei[i]!=0.0) { /* complex conjugate pair */
603: PetscCall(VecGetArrayRead(xr,&px));
604: PetscCall(VecPlaceArray(w,px+offset));
605: PetscCall(BVInsertVec(pep->V,i,w));
606: PetscCall(VecResetArray(w));
607: PetscCall(VecRestoreArrayRead(xr,&px));
608: PetscCall(VecGetArrayRead(xi,&px));
609: PetscCall(VecPlaceArray(w,px+offset));
610: PetscCall(BVInsertVec(pep->V,i+1,w));
611: PetscCall(VecResetArray(w));
612: PetscCall(VecRestoreArrayRead(xi,&px));
613: i++;
614: } else /* real eigenvalue */
615: #endif
616: {
617: PetscCall(VecGetArrayRead(xr,&px));
618: PetscCall(VecPlaceArray(w,px+offset));
619: PetscCall(BVInsertVec(pep->V,i,w));
620: PetscCall(VecResetArray(w));
621: PetscCall(VecRestoreArrayRead(xr,&px));
622: }
623: }
624: PetscCall(VecDestroy(&w));
625: PetscCall(VecDestroy(&xr));
626: #if !defined(PETSC_USE_COMPLEX)
627: PetscCall(VecDestroy(&xi));
628: #endif
629: PetscFunctionReturn(PETSC_SUCCESS);
630: }
632: static PetscErrorCode PEPExtractVectors_Linear(PEP pep)
633: {
634: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
636: PetscFunctionBegin;
637: switch (pep->extract) {
638: case PEP_EXTRACT_NONE:
639: PetscCall(PEPLinearExtract_None(pep,ctx->eps));
640: break;
641: case PEP_EXTRACT_NORM:
642: PetscCall(PEPLinearExtract_Norm(pep,ctx->eps));
643: break;
644: case PEP_EXTRACT_RESIDUAL:
645: PetscCall(PEPLinearExtract_Residual(pep,ctx->eps));
646: break;
647: case PEP_EXTRACT_STRUCTURED:
648: SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Extraction not implemented in this solver");
649: }
650: PetscFunctionReturn(PETSC_SUCCESS);
651: }
653: static PetscErrorCode PEPSolve_Linear(PEP pep)
654: {
655: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
656: PetscScalar sigma;
657: PetscBool flg;
658: PetscInt i;
660: PetscFunctionBegin;
661: PetscCall(EPSSolve(ctx->eps));
662: PetscCall(EPSGetConverged(ctx->eps,&pep->nconv));
663: PetscCall(EPSGetIterationNumber(ctx->eps,&pep->its));
664: PetscCall(EPSGetConvergedReason(ctx->eps,(EPSConvergedReason*)&pep->reason));
666: /* recover eigenvalues */
667: for (i=0;i<pep->nconv;i++) {
668: PetscCall(EPSGetEigenpair(ctx->eps,i,&pep->eigr[i],&pep->eigi[i],NULL,NULL));
669: pep->eigr[i] *= pep->sfactor;
670: pep->eigi[i] *= pep->sfactor;
671: }
673: /* restore target */
674: PetscCall(EPSGetTarget(ctx->eps,&sigma));
675: PetscCall(EPSSetTarget(ctx->eps,sigma*pep->sfactor));
677: PetscCall(STGetTransform(pep->st,&flg));
678: if (flg) PetscTryTypeMethod(pep,backtransform);
679: if (pep->sfactor!=1.0) {
680: /* Restore original values */
681: for (i=0;i<pep->nmat;i++) {
682: pep->pbc[pep->nmat+i] *= pep->sfactor;
683: pep->pbc[2*pep->nmat+i] *= pep->sfactor*pep->sfactor;
684: }
685: if (!flg && !ctx->explicitmatrix) PetscCall(STScaleShift(pep->st,pep->sfactor));
686: }
687: if (ctx->explicitmatrix || !flg) PetscCall(RGPopScale(pep->rg));
688: PetscFunctionReturn(PETSC_SUCCESS);
689: }
691: static PetscErrorCode EPSMonitor_Linear(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
692: {
693: PEP pep = (PEP)ctx;
695: PetscFunctionBegin;
696: PetscCall(PEPMonitor(pep,its,nconv,eigr,eigi,errest,nest));
697: PetscFunctionReturn(PETSC_SUCCESS);
698: }
700: static PetscErrorCode PEPSetFromOptions_Linear(PEP pep,PetscOptionItems *PetscOptionsObject)
701: {
702: PetscBool set,val;
703: PetscInt k;
704: PetscReal array[2]={0,0};
705: PetscBool flg;
706: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
708: PetscFunctionBegin;
709: PetscOptionsHeadBegin(PetscOptionsObject,"PEP Linear Options");
711: k = 2;
712: PetscCall(PetscOptionsRealArray("-pep_linear_linearization","Parameters of the linearization","PEPLinearSetLinearization",array,&k,&flg));
713: if (flg) PetscCall(PEPLinearSetLinearization(pep,array[0],array[1]));
715: PetscCall(PetscOptionsBool("-pep_linear_explicitmatrix","Use explicit matrix in linearization","PEPLinearSetExplicitMatrix",ctx->explicitmatrix,&val,&set));
716: if (set) PetscCall(PEPLinearSetExplicitMatrix(pep,val));
718: PetscOptionsHeadEnd();
720: if (!ctx->eps) PetscCall(PEPLinearGetEPS(pep,&ctx->eps));
721: PetscCall(EPSSetFromOptions(ctx->eps));
722: PetscFunctionReturn(PETSC_SUCCESS);
723: }
725: static PetscErrorCode PEPLinearSetLinearization_Linear(PEP pep,PetscReal alpha,PetscReal beta)
726: {
727: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
729: PetscFunctionBegin;
730: PetscCheck(beta!=0.0 || alpha!=0.0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONG,"Parameters alpha and beta cannot be zero simultaneously");
731: ctx->alpha = alpha;
732: ctx->beta = beta;
733: PetscFunctionReturn(PETSC_SUCCESS);
734: }
736: /*@
737: PEPLinearSetLinearization - Set the coefficients that define
738: the linearization of a quadratic eigenproblem.
740: Logically Collective
742: Input Parameters:
743: + pep - polynomial eigenvalue solver
744: . alpha - first parameter of the linearization
745: - beta - second parameter of the linearization
747: Options Database Key:
748: . -pep_linear_linearization <alpha,beta> - Sets the coefficients
750: Notes:
751: Cannot pass zero for both alpha and beta. The default values are
752: alpha=1 and beta=0.
754: Level: advanced
756: .seealso: PEPLinearGetLinearization()
757: @*/
758: PetscErrorCode PEPLinearSetLinearization(PEP pep,PetscReal alpha,PetscReal beta)
759: {
760: PetscFunctionBegin;
764: PetscTryMethod(pep,"PEPLinearSetLinearization_C",(PEP,PetscReal,PetscReal),(pep,alpha,beta));
765: PetscFunctionReturn(PETSC_SUCCESS);
766: }
768: static PetscErrorCode PEPLinearGetLinearization_Linear(PEP pep,PetscReal *alpha,PetscReal *beta)
769: {
770: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
772: PetscFunctionBegin;
773: if (alpha) *alpha = ctx->alpha;
774: if (beta) *beta = ctx->beta;
775: PetscFunctionReturn(PETSC_SUCCESS);
776: }
778: /*@
779: PEPLinearGetLinearization - Returns the coefficients that define
780: the linearization of a quadratic eigenproblem.
782: Not Collective
784: Input Parameter:
785: . pep - polynomial eigenvalue solver
787: Output Parameters:
788: + alpha - the first parameter of the linearization
789: - beta - the second parameter of the linearization
791: Level: advanced
793: .seealso: PEPLinearSetLinearization()
794: @*/
795: PetscErrorCode PEPLinearGetLinearization(PEP pep,PetscReal *alpha,PetscReal *beta)
796: {
797: PetscFunctionBegin;
799: PetscUseMethod(pep,"PEPLinearGetLinearization_C",(PEP,PetscReal*,PetscReal*),(pep,alpha,beta));
800: PetscFunctionReturn(PETSC_SUCCESS);
801: }
803: static PetscErrorCode PEPLinearSetExplicitMatrix_Linear(PEP pep,PetscBool explicitmatrix)
804: {
805: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
807: PetscFunctionBegin;
808: if (ctx->explicitmatrix != explicitmatrix) {
809: ctx->explicitmatrix = explicitmatrix;
810: pep->state = PEP_STATE_INITIAL;
811: }
812: PetscFunctionReturn(PETSC_SUCCESS);
813: }
815: /*@
816: PEPLinearSetExplicitMatrix - Indicate if the matrices A and B for the
817: linearization of the problem must be built explicitly.
819: Logically Collective
821: Input Parameters:
822: + pep - polynomial eigenvalue solver
823: - explicitmat - boolean flag indicating if the matrices are built explicitly
825: Options Database Key:
826: . -pep_linear_explicitmatrix <boolean> - Indicates the boolean flag
828: Level: advanced
830: .seealso: PEPLinearGetExplicitMatrix()
831: @*/
832: PetscErrorCode PEPLinearSetExplicitMatrix(PEP pep,PetscBool explicitmat)
833: {
834: PetscFunctionBegin;
837: PetscTryMethod(pep,"PEPLinearSetExplicitMatrix_C",(PEP,PetscBool),(pep,explicitmat));
838: PetscFunctionReturn(PETSC_SUCCESS);
839: }
841: static PetscErrorCode PEPLinearGetExplicitMatrix_Linear(PEP pep,PetscBool *explicitmat)
842: {
843: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
845: PetscFunctionBegin;
846: *explicitmat = ctx->explicitmatrix;
847: PetscFunctionReturn(PETSC_SUCCESS);
848: }
850: /*@
851: PEPLinearGetExplicitMatrix - Returns the flag indicating if the matrices
852: A and B for the linearization are built explicitly.
854: Not Collective
856: Input Parameter:
857: . pep - polynomial eigenvalue solver
859: Output Parameter:
860: . explicitmat - the mode flag
862: Level: advanced
864: .seealso: PEPLinearSetExplicitMatrix()
865: @*/
866: PetscErrorCode PEPLinearGetExplicitMatrix(PEP pep,PetscBool *explicitmat)
867: {
868: PetscFunctionBegin;
870: PetscAssertPointer(explicitmat,2);
871: PetscUseMethod(pep,"PEPLinearGetExplicitMatrix_C",(PEP,PetscBool*),(pep,explicitmat));
872: PetscFunctionReturn(PETSC_SUCCESS);
873: }
875: static PetscErrorCode PEPLinearSetEPS_Linear(PEP pep,EPS eps)
876: {
877: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
879: PetscFunctionBegin;
880: PetscCall(PetscObjectReference((PetscObject)eps));
881: PetscCall(EPSDestroy(&ctx->eps));
882: ctx->eps = eps;
883: ctx->usereps = PETSC_TRUE;
884: pep->state = PEP_STATE_INITIAL;
885: PetscFunctionReturn(PETSC_SUCCESS);
886: }
888: /*@
889: PEPLinearSetEPS - Associate an eigensolver object (EPS) to the
890: polynomial eigenvalue solver.
892: Collective
894: Input Parameters:
895: + pep - polynomial eigenvalue solver
896: - eps - the eigensolver object
898: Level: advanced
900: .seealso: PEPLinearGetEPS()
901: @*/
902: PetscErrorCode PEPLinearSetEPS(PEP pep,EPS eps)
903: {
904: PetscFunctionBegin;
907: PetscCheckSameComm(pep,1,eps,2);
908: PetscTryMethod(pep,"PEPLinearSetEPS_C",(PEP,EPS),(pep,eps));
909: PetscFunctionReturn(PETSC_SUCCESS);
910: }
912: static PetscErrorCode PEPLinearGetEPS_Linear(PEP pep,EPS *eps)
913: {
914: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
916: PetscFunctionBegin;
917: if (!ctx->eps) {
918: PetscCall(EPSCreate(PetscObjectComm((PetscObject)pep),&ctx->eps));
919: PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)pep,1));
920: PetscCall(EPSSetOptionsPrefix(ctx->eps,((PetscObject)pep)->prefix));
921: PetscCall(EPSAppendOptionsPrefix(ctx->eps,"pep_linear_"));
922: PetscCall(PetscObjectSetOptions((PetscObject)ctx->eps,((PetscObject)pep)->options));
923: PetscCall(EPSMonitorSet(ctx->eps,EPSMonitor_Linear,pep,NULL));
924: }
925: *eps = ctx->eps;
926: PetscFunctionReturn(PETSC_SUCCESS);
927: }
929: /*@
930: PEPLinearGetEPS - Retrieve the eigensolver object (EPS) associated
931: to the polynomial eigenvalue solver.
933: Collective
935: Input Parameter:
936: . pep - polynomial eigenvalue solver
938: Output Parameter:
939: . eps - the eigensolver object
941: Level: advanced
943: .seealso: PEPLinearSetEPS()
944: @*/
945: PetscErrorCode PEPLinearGetEPS(PEP pep,EPS *eps)
946: {
947: PetscFunctionBegin;
949: PetscAssertPointer(eps,2);
950: PetscUseMethod(pep,"PEPLinearGetEPS_C",(PEP,EPS*),(pep,eps));
951: PetscFunctionReturn(PETSC_SUCCESS);
952: }
954: static PetscErrorCode PEPView_Linear(PEP pep,PetscViewer viewer)
955: {
956: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
957: PetscBool isascii;
959: PetscFunctionBegin;
960: PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
961: if (isascii) {
962: if (!ctx->eps) PetscCall(PEPLinearGetEPS(pep,&ctx->eps));
963: PetscCall(PetscViewerASCIIPrintf(viewer," %s matrices\n",ctx->explicitmatrix? "explicit": "implicit"));
964: PetscCall(PetscViewerASCIIPrintf(viewer," linearization parameters: alpha=%g beta=%g\n",(double)ctx->alpha,(double)ctx->beta));
965: PetscCall(PetscViewerASCIIPushTab(viewer));
966: PetscCall(EPSView(ctx->eps,viewer));
967: PetscCall(PetscViewerASCIIPopTab(viewer));
968: }
969: PetscFunctionReturn(PETSC_SUCCESS);
970: }
972: static PetscErrorCode PEPReset_Linear(PEP pep)
973: {
974: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
976: PetscFunctionBegin;
977: if (!ctx->eps) PetscCall(EPSReset(ctx->eps));
978: PetscCall(MatDestroy(&ctx->A));
979: PetscCall(MatDestroy(&ctx->B));
980: PetscCall(VecDestroy(&ctx->w[0]));
981: PetscCall(VecDestroy(&ctx->w[1]));
982: PetscCall(VecDestroy(&ctx->w[2]));
983: PetscCall(VecDestroy(&ctx->w[3]));
984: PetscCall(VecDestroy(&ctx->w[4]));
985: PetscCall(VecDestroy(&ctx->w[5]));
986: PetscFunctionReturn(PETSC_SUCCESS);
987: }
989: static PetscErrorCode PEPDestroy_Linear(PEP pep)
990: {
991: PEP_LINEAR *ctx = (PEP_LINEAR*)pep->data;
993: PetscFunctionBegin;
994: PetscCall(EPSDestroy(&ctx->eps));
995: PetscCall(PetscFree(pep->data));
996: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearSetLinearization_C",NULL));
997: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearGetLinearization_C",NULL));
998: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearSetEPS_C",NULL));
999: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearGetEPS_C",NULL));
1000: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearSetExplicitMatrix_C",NULL));
1001: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearGetExplicitMatrix_C",NULL));
1002: PetscFunctionReturn(PETSC_SUCCESS);
1003: }
1005: SLEPC_EXTERN PetscErrorCode PEPCreate_Linear(PEP pep)
1006: {
1007: PEP_LINEAR *ctx;
1009: PetscFunctionBegin;
1010: PetscCall(PetscNew(&ctx));
1011: pep->data = (void*)ctx;
1013: pep->lineariz = PETSC_TRUE;
1014: ctx->explicitmatrix = PETSC_FALSE;
1015: ctx->alpha = 1.0;
1016: ctx->beta = 0.0;
1018: pep->ops->solve = PEPSolve_Linear;
1019: pep->ops->setup = PEPSetUp_Linear;
1020: pep->ops->setfromoptions = PEPSetFromOptions_Linear;
1021: pep->ops->destroy = PEPDestroy_Linear;
1022: pep->ops->reset = PEPReset_Linear;
1023: pep->ops->view = PEPView_Linear;
1024: pep->ops->backtransform = PEPBackTransform_Default;
1025: pep->ops->computevectors = PEPComputeVectors_Default;
1026: pep->ops->extractvectors = PEPExtractVectors_Linear;
1028: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearSetLinearization_C",PEPLinearSetLinearization_Linear));
1029: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearGetLinearization_C",PEPLinearGetLinearization_Linear));
1030: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearSetEPS_C",PEPLinearSetEPS_Linear));
1031: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearGetEPS_C",PEPLinearGetEPS_Linear));
1032: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearSetExplicitMatrix_C",PEPLinearSetExplicitMatrix_Linear));
1033: PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPLinearGetExplicitMatrix_C",PEPLinearGetExplicitMatrix_Linear));
1034: PetscFunctionReturn(PETSC_SUCCESS);
1035: }