Actual source code: pjd.c
slepc-3.17.1 2022-04-11
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: "jd"
13: Method: Jacobi-Davidson
15: Algorithm:
17: Jacobi-Davidson for polynomial eigenvalue problems.
19: References:
21: [1] C. Campos and J.E. Roman, "A polynomial Jacobi-Davidson solver
22: with support for non-monomial bases and deflation", BIT Numer.
23: Math. 60:295-318, 2020.
25: [2] G.L.G. Sleijpen et al., "Jacobi-Davidson type methods for
26: generalized eigenproblems and polynomial eigenproblems", BIT
27: 36(3):595-633, 1996.
29: [3] Feng-Nan Hwang, Zih-Hao Wei, Tsung-Ming Huang, Weichung Wang,
30: "A Parallel Additive Schwarz Preconditioned Jacobi-Davidson
31: Algorithm for Polynomial Eigenvalue Problems in Quantum Dot
32: Simulation", J. Comput. Phys. 229(8):2932-2947, 2010.
33: */
35: #include <slepc/private/pepimpl.h>
36: #include <slepcblaslapack.h>
38: static PetscBool cited = PETSC_FALSE;
39: static const char citation[] =
40: "@Article{slepc-slice-qep,\n"
41: " author = \"C. Campos and J. E. Roman\",\n"
42: " title = \"A polynomial {Jacobi-Davidson} solver with support for non-monomial bases and deflation\",\n"
43: " journal = \"{BIT} Numer. Math.\",\n"
44: " volume = \"60\",\n"
45: " pages = \"295--318\",\n"
46: " year = \"2020,\"\n"
47: " doi = \"https://doi.org/10.1007/s10543-019-00778-z\"\n"
48: "}\n";
50: typedef struct {
51: PetscReal keep; /* restart parameter */
52: PetscReal fix; /* fix parameter */
53: PetscBool reusepc; /* flag indicating whether pc is rebuilt or not */
54: BV V; /* work basis vectors to store the search space */
55: BV W; /* work basis vectors to store the test space */
56: BV *TV; /* work basis vectors to store T*V (each TV[i] is the coefficient for \lambda^i of T*V for the extended T) */
57: BV *AX; /* work basis vectors to store A_i*X for locked eigenvectors */
58: BV N[2]; /* auxiliary work BVs */
59: BV X; /* locked eigenvectors */
60: PetscScalar *T; /* matrix of the invariant pair */
61: PetscScalar *Tj; /* matrix containing the powers of the invariant pair matrix */
62: PetscScalar *XpX; /* X^H*X */
63: PetscInt ld; /* leading dimension for Tj and XpX */
64: PC pcshell; /* preconditioner including basic precond+projector */
65: Mat Pshell; /* auxiliary shell matrix */
66: PetscInt nlock; /* number of locked vectors in the invariant pair */
67: Vec vtempl; /* reference nested vector */
68: PetscInt midx; /* minimality index */
69: PetscInt mmidx; /* maximum allowed minimality index */
70: PEPJDProjection proj; /* projection type (orthogonal, harmonic) */
71: } PEP_JD;
73: typedef struct {
74: PEP pep;
75: PC pc; /* basic preconditioner */
76: Vec Bp[2]; /* preconditioned residual of derivative polynomial, B\p */
77: Vec u[2]; /* Ritz vector */
78: PetscScalar gamma[2]; /* precomputed scalar u'*B\p */
79: PetscScalar theta;
80: PetscScalar *M;
81: PetscScalar *ps;
82: PetscInt ld;
83: Vec *work;
84: Mat PPr;
85: BV X;
86: PetscInt n;
87: } PEP_JD_PCSHELL;
89: typedef struct {
90: Mat Pr,Pi; /* matrix polynomial evaluated at theta */
91: PEP pep;
92: Vec *work;
93: PetscScalar theta[2];
94: } PEP_JD_MATSHELL;
96: /*
97: Duplicate and resize auxiliary basis
98: */
99: static PetscErrorCode PEPJDDuplicateBasis(PEP pep,BV *basis)
100: {
101: PEP_JD *pjd = (PEP_JD*)pep->data;
102: PetscInt nloc,m;
103: BVType type;
104: BVOrthogType otype;
105: BVOrthogRefineType oref;
106: PetscReal oeta;
107: BVOrthogBlockType oblock;
109: if (pjd->ld>1) {
110: BVCreate(PetscObjectComm((PetscObject)pep),basis);
111: BVGetSizes(pep->V,&nloc,NULL,&m);
112: nloc += pjd->ld-1;
113: BVSetSizes(*basis,nloc,PETSC_DECIDE,m);
114: BVGetType(pep->V,&type);
115: BVSetType(*basis,type);
116: BVGetOrthogonalization(pep->V,&otype,&oref,&oeta,&oblock);
117: BVSetOrthogonalization(*basis,otype,oref,oeta,oblock);
118: PetscObjectStateIncrease((PetscObject)*basis);
119: } else BVDuplicate(pep->V,basis);
120: PetscFunctionReturn(0);
121: }
123: PetscErrorCode PEPSetUp_JD(PEP pep)
124: {
125: PEP_JD *pjd = (PEP_JD*)pep->data;
126: PetscBool isprecond,flg;
127: PetscRandom rand;
128: PetscInt i;
130: PEPSetDimensions_Default(pep,pep->nev,&pep->ncv,&pep->mpd);
131: if (pep->max_it==PETSC_DEFAULT) pep->max_it = PetscMax(100,2*pep->n/pep->ncv);
132: if (!pep->which) pep->which = PEP_TARGET_MAGNITUDE;
135: PetscObjectTypeCompare((PetscObject)pep->st,STPRECOND,&isprecond);
138: STGetTransform(pep->st,&flg);
140: PEPCheckIgnored(pep,PEP_FEATURE_EXTRACT);
142: if (!pjd->mmidx) pjd->mmidx = pep->nmat-1;
143: pjd->mmidx = PetscMin(pjd->mmidx,pep->nmat-1);
144: if (!pjd->keep) pjd->keep = 0.5;
145: PEPBasisCoefficients(pep,pep->pbc);
146: PEPAllocateSolution(pep,0);
147: BVGetRandomContext(pep->V,&rand); /* make sure the random context is available when duplicating */
148: PEPSetWorkVecs(pep,5);
149: pjd->ld = pep->nev;
150: #if !defined (PETSC_USE_COMPLEX)
151: pjd->ld++;
152: #endif
153: PetscMalloc2(pep->nmat,&pjd->TV,pep->nmat,&pjd->AX);
154: for (i=0;i<pep->nmat;i++) PEPJDDuplicateBasis(pep,pjd->TV+i);
155: if (pjd->ld>1) {
156: PEPJDDuplicateBasis(pep,&pjd->V);
157: BVSetFromOptions(pjd->V);
158: for (i=0;i<pep->nmat;i++) BVDuplicateResize(pep->V,pjd->ld-1,pjd->AX+i);
159: BVDuplicateResize(pep->V,pjd->ld-1,pjd->N);
160: BVDuplicateResize(pep->V,pjd->ld-1,pjd->N+1);
161: pjd->X = pep->V;
162: PetscCalloc3((pjd->ld)*(pjd->ld),&pjd->XpX,pep->ncv*pep->ncv,&pjd->T,pjd->ld*pjd->ld*pep->nmat,&pjd->Tj);
163: } else pjd->V = pep->V;
164: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) PEPJDDuplicateBasis(pep,&pjd->W);
165: else pjd->W = pjd->V;
166: DSSetType(pep->ds,DSPEP);
167: DSPEPSetDegree(pep->ds,pep->nmat-1);
168: if (pep->basis!=PEP_BASIS_MONOMIAL) DSPEPSetCoefficients(pep->ds,pep->pbc);
169: DSAllocate(pep->ds,pep->ncv);
170: PetscFunctionReturn(0);
171: }
173: /*
174: Updates columns (low to (high-1)) of TV[i]
175: */
176: static PetscErrorCode PEPJDUpdateTV(PEP pep,PetscInt low,PetscInt high,Vec *w)
177: {
178: PEP_JD *pjd = (PEP_JD*)pep->data;
179: PetscInt pp,col,i,nloc,nconv;
180: Vec v1,v2,t1,t2;
181: PetscScalar *array1,*array2,*x2,*xx,*N,*Np,*y2=NULL,zero=0.0,sone=1.0,*pT,fact,*psc;
182: PetscReal *cg,*ca,*cb;
183: PetscMPIInt rk,np;
184: PetscBLASInt n_,ld_,one=1;
185: Mat T;
186: BV pbv;
188: ca = pep->pbc; cb = ca+pep->nmat; cg = cb + pep->nmat;
189: nconv = pjd->nlock;
190: PetscMalloc5(nconv,&x2,nconv,&xx,nconv*nconv,&pT,nconv*nconv,&N,nconv*nconv,&Np);
191: MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rk);
192: MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np);
193: BVGetSizes(pep->V,&nloc,NULL,NULL);
194: t1 = w[0];
195: t2 = w[1];
196: PetscBLASIntCast(pjd->nlock,&n_);
197: PetscBLASIntCast(pjd->ld,&ld_);
198: if (nconv) {
199: for (i=0;i<nconv;i++) PetscArraycpy(pT+i*nconv,pjd->T+i*pep->ncv,nconv);
200: MatCreateSeqDense(PETSC_COMM_SELF,nconv,nconv,pT,&T);
201: }
202: for (col=low;col<high;col++) {
203: BVGetColumn(pjd->V,col,&v1);
204: VecGetArray(v1,&array1);
205: if (nconv>0) {
206: for (i=0;i<nconv;i++) x2[i] = array1[nloc+i]* PetscSqrtReal(np);
207: }
208: VecPlaceArray(t1,array1);
209: if (nconv) {
210: BVSetActiveColumns(pjd->N[0],0,nconv);
211: BVSetActiveColumns(pjd->N[1],0,nconv);
212: BVDotVec(pjd->X,t1,xx);
213: }
214: for (pp=pep->nmat-1;pp>=0;pp--) {
215: BVGetColumn(pjd->TV[pp],col,&v2);
216: VecGetArray(v2,&array2);
217: VecPlaceArray(t2,array2);
218: MatMult(pep->A[pp],t1,t2);
219: if (nconv) {
220: if (pp<pep->nmat-3) {
221: BVMult(pjd->N[0],1.0,-cg[pp+2],pjd->AX[pp+1],NULL);
222: MatShift(T,-cb[pp+1]);
223: BVMult(pjd->N[0],1.0/ca[pp],1.0/ca[pp],pjd->N[1],T);
224: pbv = pjd->N[0]; pjd->N[0] = pjd->N[1]; pjd->N[1] = pbv;
225: BVMultVec(pjd->N[1],1.0,1.0,t2,x2);
226: MatShift(T,cb[pp+1]);
227: } else if (pp==pep->nmat-3) {
228: BVCopy(pjd->AX[pp+2],pjd->N[0]);
229: BVScale(pjd->N[0],1/ca[pp+1]);
230: BVCopy(pjd->AX[pp+1],pjd->N[1]);
231: MatShift(T,-cb[pp+1]);
232: BVMult(pjd->N[1],1.0/ca[pp],1.0/ca[pp],pjd->N[0],T);
233: BVMultVec(pjd->N[1],1.0,1.0,t2,x2);
234: MatShift(T,cb[pp+1]);
235: } else if (pp==pep->nmat-2) BVMultVec(pjd->AX[pp+1],1.0/ca[pp],1.0,t2,x2);
236: if (pp<pjd->midx) {
237: y2 = array2+nloc;
238: PetscStackCallBLAS("BLASgemv",BLASgemv_("C",&n_,&n_,&sone,pjd->Tj+pjd->ld*pjd->ld*pp,&ld_,xx,&one,&zero,y2,&one));
239: if (pp<pjd->midx-2) {
240: fact = -cg[pp+2];
241: PetscStackCallBLAS("BLASgemm",BLASgemm_("C","N",&n_,&n_,&n_,&sone,pjd->Tj+(pp+1)*pjd->ld*pjd->ld,&ld_,pjd->XpX,&ld_,&fact,Np,&n_));
242: fact = 1/ca[pp];
243: MatShift(T,-cb[pp+1]);
244: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&fact,N,&n_,pT,&n_,&fact,Np,&n_));
245: MatShift(T,cb[pp+1]);
246: psc = Np; Np = N; N = psc;
247: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,N,&n_,x2,&one,&sone,y2,&one));
248: } else if (pp==pjd->midx-2) {
249: fact = 1/ca[pp];
250: PetscStackCallBLAS("BLASgemm",BLASgemm_("C","N",&n_,&n_,&n_,&fact,pjd->Tj+(pp+1)*pjd->ld*pjd->ld,&ld_,pjd->XpX,&ld_,&zero,N,&n_));
251: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,N,&n_,x2,&one,&sone,y2,&one));
252: } else if (pp==pjd->midx-1) PetscArrayzero(Np,nconv*nconv);
253: }
254: for (i=0;i<nconv;i++) array2[nloc+i] /= PetscSqrtReal(np);
255: }
256: VecResetArray(t2);
257: VecRestoreArray(v2,&array2);
258: BVRestoreColumn(pjd->TV[pp],col,&v2);
259: }
260: VecResetArray(t1);
261: VecRestoreArray(v1,&array1);
262: BVRestoreColumn(pjd->V,col,&v1);
263: }
264: if (nconv) MatDestroy(&T);
265: PetscFree5(x2,xx,pT,N,Np);
266: PetscFunctionReturn(0);
267: }
269: /*
270: RRQR of X. Xin*P=Xou*R. Rank of R is rk
271: */
272: static PetscErrorCode PEPJDOrthogonalize(PetscInt row,PetscInt col,PetscScalar *X,PetscInt ldx,PetscInt *rk,PetscInt *P,PetscScalar *R,PetscInt ldr)
273: {
274: PetscInt i,j,n,r;
275: PetscBLASInt row_,col_,ldx_,*p,lwork,info,n_;
276: PetscScalar *tau,*work;
277: PetscReal tol,*rwork;
279: PetscBLASIntCast(row,&row_);
280: PetscBLASIntCast(col,&col_);
281: PetscBLASIntCast(ldx,&ldx_);
282: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
283: n = PetscMin(row,col);
284: PetscBLASIntCast(n,&n_);
285: lwork = 3*col_+1;
286: PetscMalloc4(col,&p,n,&tau,lwork,&work,2*col,&rwork);
287: for (i=1;i<col;i++) p[i] = 0;
288: p[0] = 1;
290: /* rank revealing QR */
291: #if defined(PETSC_USE_COMPLEX)
292: PetscStackCallBLAS("LAPACKgeqp3",LAPACKgeqp3_(&row_,&col_,X,&ldx_,p,tau,work,&lwork,rwork,&info));
293: #else
294: PetscStackCallBLAS("LAPACKgeqp3",LAPACKgeqp3_(&row_,&col_,X,&ldx_,p,tau,work,&lwork,&info));
295: #endif
296: SlepcCheckLapackInfo("geqp3",info);
297: if (P) for (i=0;i<col;i++) P[i] = p[i]-1;
299: /* rank computation */
300: tol = PetscMax(row,col)*PETSC_MACHINE_EPSILON*PetscAbsScalar(X[0]);
301: r = 1;
302: for (i=1;i<n;i++) {
303: if (PetscAbsScalar(X[i+ldx*i])>tol) r++;
304: else break;
305: }
306: if (rk) *rk=r;
308: /* copy upper triangular matrix if requested */
309: if (R) {
310: for (i=0;i<r;i++) {
311: PetscArrayzero(R+i*ldr,r);
312: for (j=0;j<=i;j++) R[i*ldr+j] = X[i*ldx+j];
313: }
314: }
315: PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&row_,&n_,&n_,X,&ldx_,tau,work,&lwork,&info));
316: SlepcCheckLapackInfo("orgqr",info);
317: PetscFPTrapPop();
318: PetscFree4(p,tau,work,rwork);
319: PetscFunctionReturn(0);
320: }
322: /*
323: Application of extended preconditioner
324: */
325: static PetscErrorCode PEPJDExtendedPCApply(PC pc,Vec x,Vec y)
326: {
327: PetscInt i,j,nloc,n,ld=0;
328: PetscMPIInt np;
329: Vec tx,ty;
330: PEP_JD_PCSHELL *ctx;
331: const PetscScalar *array1;
332: PetscScalar *x2=NULL,*t=NULL,*ps=NULL,*array2,zero=0.0,sone=1.0;
333: PetscBLASInt one=1,ld_,n_,ncv_;
334: PEP_JD *pjd=NULL;
336: MPI_Comm_size(PetscObjectComm((PetscObject)pc),&np);
337: PCShellGetContext(pc,&ctx);
338: n = ctx->n;
339: if (n) {
340: pjd = (PEP_JD*)ctx->pep->data;
341: ps = ctx->ps;
342: ld = pjd->ld;
343: PetscMalloc2(n,&x2,n,&t);
344: VecGetLocalSize(ctx->work[0],&nloc);
345: VecGetArrayRead(x,&array1);
346: for (i=0;i<n;i++) x2[i] = array1[nloc+i]* PetscSqrtReal(np);
347: VecRestoreArrayRead(x,&array1);
348: }
350: /* y = B\x apply PC */
351: tx = ctx->work[0];
352: ty = ctx->work[1];
353: VecGetArrayRead(x,&array1);
354: VecPlaceArray(tx,array1);
355: VecGetArray(y,&array2);
356: VecPlaceArray(ty,array2);
357: PCApply(ctx->pc,tx,ty);
358: if (n) {
359: PetscBLASIntCast(ld,&ld_);
360: PetscBLASIntCast(n,&n_);
361: for (i=0;i<n;i++) {
362: t[i] = 0.0;
363: for (j=0;j<n;j++) t[i] += ctx->M[i+j*ld]*x2[j];
364: }
365: if (pjd->midx==1) {
366: PetscBLASIntCast(ctx->pep->ncv,&ncv_);
367: for (i=0;i<n;i++) pjd->T[i*(1+ctx->pep->ncv)] -= ctx->theta;
368: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,pjd->T,&ncv_,t,&one,&zero,x2,&one));
369: for (i=0;i<n;i++) pjd->T[i*(1+ctx->pep->ncv)] += ctx->theta;
370: for (i=0;i<n;i++) array2[nloc+i] = x2[i];
371: for (i=0;i<n;i++) x2[i] = -t[i];
372: } else {
373: for (i=0;i<n;i++) array2[nloc+i] = t[i];
374: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,ps,&ld_,t,&one,&zero,x2,&one));
375: }
376: for (i=0;i<n;i++) array2[nloc+i] /= PetscSqrtReal(np);
377: BVSetActiveColumns(pjd->X,0,n);
378: BVMultVec(pjd->X,-1.0,1.0,ty,x2);
379: PetscFree2(x2,t);
380: }
381: VecResetArray(tx);
382: VecResetArray(ty);
383: VecRestoreArrayRead(x,&array1);
384: VecRestoreArray(y,&array2);
385: PetscFunctionReturn(0);
386: }
388: /*
389: Application of shell preconditioner:
390: y = B\x - eta*B\p, with eta = (u'*B\x)/(u'*B\p)
391: */
392: static PetscErrorCode PCShellApply_PEPJD(PC pc,Vec x,Vec y)
393: {
394: PetscScalar rr,eta;
395: PEP_JD_PCSHELL *ctx;
396: PetscInt sz;
397: const Vec *xs,*ys;
398: #if !defined(PETSC_USE_COMPLEX)
399: PetscScalar rx,xr,xx;
400: #endif
402: PCShellGetContext(pc,&ctx);
403: VecCompGetSubVecs(x,&sz,&xs);
404: VecCompGetSubVecs(y,NULL,&ys);
405: /* y = B\x apply extended PC */
406: PEPJDExtendedPCApply(pc,xs[0],ys[0]);
407: #if !defined(PETSC_USE_COMPLEX)
408: if (sz==2) PEPJDExtendedPCApply(pc,xs[1],ys[1]);
409: #endif
411: /* Compute eta = u'*y / u'*Bp */
412: VecDot(ys[0],ctx->u[0],&rr);
413: eta = -rr*ctx->gamma[0];
414: #if !defined(PETSC_USE_COMPLEX)
415: if (sz==2) {
416: VecDot(ys[0],ctx->u[1],&xr);
417: VecDot(ys[1],ctx->u[0],&rx);
418: VecDot(ys[1],ctx->u[1],&xx);
419: eta += -ctx->gamma[0]*xx-ctx->gamma[1]*(-xr+rx);
420: }
421: #endif
422: eta /= ctx->gamma[0]*ctx->gamma[0]+ctx->gamma[1]*ctx->gamma[1];
424: /* y = y - eta*Bp */
425: VecAXPY(ys[0],eta,ctx->Bp[0]);
426: #if !defined(PETSC_USE_COMPLEX)
427: if (sz==2) {
428: VecAXPY(ys[1],eta,ctx->Bp[1]);
429: eta = -ctx->gamma[1]*(rr+xx)+ctx->gamma[0]*(-xr+rx);
430: eta /= ctx->gamma[0]*ctx->gamma[0]+ctx->gamma[1]*ctx->gamma[1];
431: VecAXPY(ys[0],eta,ctx->Bp[1]);
432: VecAXPY(ys[1],-eta,ctx->Bp[0]);
433: }
434: #endif
435: PetscFunctionReturn(0);
436: }
438: static PetscErrorCode PEPJDCopyToExtendedVec(PEP pep,Vec v,PetscScalar *a,PetscInt na,PetscInt off,Vec vex,PetscBool back)
439: {
440: PetscMPIInt np,rk,count;
441: PetscScalar *array1,*array2;
442: PetscInt nloc;
444: MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rk);
445: MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np);
446: BVGetSizes(pep->V,&nloc,NULL,NULL);
447: if (v) {
448: VecGetArray(v,&array1);
449: VecGetArray(vex,&array2);
450: if (back) PetscArraycpy(array1,array2,nloc);
451: else PetscArraycpy(array2,array1,nloc);
452: VecRestoreArray(v,&array1);
453: VecRestoreArray(vex,&array2);
454: }
455: if (a) {
456: VecGetArray(vex,&array2);
457: if (back) {
458: PetscArraycpy(a,array2+nloc+off,na);
459: PetscMPIIntCast(na,&count);
460: MPI_Bcast(a,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep));
461: } else {
462: PetscArraycpy(array2+nloc+off,a,na);
463: PetscMPIIntCast(na,&count);
464: MPI_Bcast(array2+nloc+off,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep));
465: }
466: VecRestoreArray(vex,&array2);
467: }
468: PetscFunctionReturn(0);
469: }
471: /* Computes Phi^hat(lambda) times a vector or its derivative (depends on beval)
472: if no vector is provided returns a matrix
473: */
474: static PetscErrorCode PEPJDEvaluateHatBasis(PEP pep,PetscInt n,PetscScalar *H,PetscInt ldh,PetscScalar *beval,PetscScalar *t,PetscInt idx,PetscScalar *qpp,PetscScalar *qp,PetscScalar *q)
475: {
476: PetscInt j,i;
477: PetscBLASInt n_,ldh_,one=1;
478: PetscReal *a,*b,*g;
479: PetscScalar sone=1.0,zero=0.0;
481: a = pep->pbc; b=a+pep->nmat; g=b+pep->nmat;
482: PetscBLASIntCast(n,&n_);
483: PetscBLASIntCast(ldh,&ldh_);
484: if (idx<1) PetscArrayzero(q,t?n:n*n);
485: else if (idx==1) {
486: if (t) {for (j=0;j<n;j++) q[j] = t[j]*beval[idx-1]/a[0];}
487: else {
488: PetscArrayzero(q,n*n);
489: for (j=0;j<n;j++) q[(j+1)*n] = beval[idx-1]/a[0];
490: }
491: } else {
492: if (t) {
493: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,H,&ldh_,qp,&one,&zero,q,&one));
494: for (j=0;j<n;j++) {
495: q[j] += beval[idx-1]*t[j]-b[idx-1]*qp[j]-g[idx-1]*qpp[j];
496: q[j] /= a[idx-1];
497: }
498: } else {
499: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&sone,H,&ldh_,qp,&n_,&zero,q,&n_));
500: for (j=0;j<n;j++) {
501: q[j+n*j] += beval[idx-1];
502: for (i=0;i<n;i++) {
503: q[i+n*j] += -b[idx-1]*qp[j*n+i]-g[idx-1]*qpp[j*n+i];
504: q[i+n*j] /= a[idx-1];
505: }
506: }
507: }
508: }
509: PetscFunctionReturn(0);
510: }
512: static PetscErrorCode PEPJDComputeResidual(PEP pep,PetscBool derivative,PetscInt sz,Vec *u,PetscScalar *theta,Vec *p,Vec *work)
513: {
514: PEP_JD *pjd = (PEP_JD*)pep->data;
515: PetscMPIInt rk,np,count;
516: Vec tu,tp,w;
517: PetscScalar *dval,*dvali,*array1,*array2,*x2=NULL,*y2,*qj=NULL,*tt=NULL,*xx=NULL,*xxi=NULL,sone=1.0;
518: PetscInt i,j,nconv,nloc;
519: PetscBLASInt n,ld,one=1;
520: #if !defined(PETSC_USE_COMPLEX)
521: Vec tui=NULL,tpi=NULL;
522: PetscScalar *x2i=NULL,*qji=NULL,*qq,*y2i,*arrayi1,*arrayi2;
523: #endif
525: nconv = pjd->nlock;
526: if (!nconv) PetscMalloc1(2*sz*pep->nmat,&dval);
527: else {
528: PetscMalloc5(2*pep->nmat,&dval,2*nconv,&xx,nconv,&tt,sz*nconv,&x2,(sz==2?3:1)*nconv*pep->nmat,&qj);
529: MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rk);
530: MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np);
531: BVGetSizes(pep->V,&nloc,NULL,NULL);
532: VecGetArray(u[0],&array1);
533: for (i=0;i<nconv;i++) x2[i] = array1[nloc+i]*PetscSqrtReal(np);
534: VecRestoreArray(u[0],&array1);
535: #if !defined(PETSC_USE_COMPLEX)
536: if (sz==2) {
537: x2i = x2+nconv;
538: VecGetArray(u[1],&arrayi1);
539: for (i=0;i<nconv;i++) x2i[i] = arrayi1[nloc+i]*PetscSqrtReal(np);
540: VecRestoreArray(u[1],&arrayi1);
541: }
542: #endif
543: }
544: dvali = dval+pep->nmat;
545: tu = work[0];
546: tp = work[1];
547: w = work[2];
548: VecGetArray(u[0],&array1);
549: VecPlaceArray(tu,array1);
550: VecGetArray(p[0],&array2);
551: VecPlaceArray(tp,array2);
552: VecSet(tp,0.0);
553: #if !defined(PETSC_USE_COMPLEX)
554: if (sz==2) {
555: tui = work[3];
556: tpi = work[4];
557: VecGetArray(u[1],&arrayi1);
558: VecPlaceArray(tui,arrayi1);
559: VecGetArray(p[1],&arrayi2);
560: VecPlaceArray(tpi,arrayi2);
561: VecSet(tpi,0.0);
562: }
563: #endif
564: if (derivative) PEPEvaluateBasisDerivative(pep,theta[0],theta[1],dval,dvali);
565: else PEPEvaluateBasis(pep,theta[0],theta[1],dval,dvali);
566: for (i=derivative?1:0;i<pep->nmat;i++) {
567: MatMult(pep->A[i],tu,w);
568: VecAXPY(tp,dval[i],w);
569: #if !defined(PETSC_USE_COMPLEX)
570: if (sz==2) {
571: VecAXPY(tpi,dvali[i],w);
572: MatMult(pep->A[i],tui,w);
573: VecAXPY(tpi,dval[i],w);
574: VecAXPY(tp,-dvali[i],w);
575: }
576: #endif
577: }
578: if (nconv) {
579: for (i=0;i<pep->nmat;i++) PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dval,x2,i,i>1?qj+(i-2)*nconv:NULL,i>0?qj+(i-1)*nconv:NULL,qj+i*nconv);
580: #if !defined(PETSC_USE_COMPLEX)
581: if (sz==2) {
582: qji = qj+nconv*pep->nmat;
583: qq = qji+nconv*pep->nmat;
584: for (i=0;i<pep->nmat;i++) PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dvali,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv);
585: for (i=0;i<nconv*pep->nmat;i++) qj[i] -= qji[i];
586: for (i=0;i<pep->nmat;i++) {
587: PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dval,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv);
588: PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dvali,x2,i,i>1?qq+(i-2)*nconv:NULL,i>0?qq+(i-1)*nconv:NULL,qq+i*nconv);
589: }
590: for (i=0;i<nconv*pep->nmat;i++) qji[i] += qq[i];
591: for (i=derivative?2:1;i<pep->nmat;i++) BVMultVec(pjd->AX[i],1.0,1.0,tpi,qji+i*nconv);
592: }
593: #endif
594: for (i=derivative?2:1;i<pep->nmat;i++) BVMultVec(pjd->AX[i],1.0,1.0,tp,qj+i*nconv);
596: /* extended vector part */
597: BVSetActiveColumns(pjd->X,0,nconv);
598: BVDotVec(pjd->X,tu,xx);
599: xxi = xx+nconv;
600: #if !defined(PETSC_USE_COMPLEX)
601: if (sz==2) BVDotVec(pjd->X,tui,xxi);
602: #endif
603: if (sz==1) PetscArrayzero(xxi,nconv);
604: if (rk==np-1) {
605: PetscBLASIntCast(nconv,&n);
606: PetscBLASIntCast(pjd->ld,&ld);
607: y2 = array2+nloc;
608: PetscArrayzero(y2,nconv);
609: for (j=derivative?1:0;j<pjd->midx;j++) {
610: for (i=0;i<nconv;i++) tt[i] = dval[j]*xx[i]-dvali[j]*xxi[i];
611: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qj+j*nconv,&one,&sone,tt,&one));
612: PetscStackCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2,&one));
613: }
614: for (i=0;i<nconv;i++) array2[nloc+i] /= PetscSqrtReal(np);
615: #if !defined(PETSC_USE_COMPLEX)
616: if (sz==2) {
617: y2i = arrayi2+nloc;
618: PetscArrayzero(y2i,nconv);
619: for (j=derivative?1:0;j<pjd->midx;j++) {
620: for (i=0;i<nconv;i++) tt[i] = dval[j]*xxi[i]+dvali[j]*xx[i];
621: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qji+j*nconv,&one,&sone,tt,&one));
622: PetscStackCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2i,&one));
623: }
624: for (i=0;i<nconv;i++) arrayi2[nloc+i] /= PetscSqrtReal(np);
625: }
626: #endif
627: }
628: PetscMPIIntCast(nconv,&count);
629: MPI_Bcast(array2+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep));
630: #if !defined(PETSC_USE_COMPLEX)
631: if (sz==2) MPI_Bcast(arrayi2+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep));
632: #endif
633: }
634: if (nconv) PetscFree5(dval,xx,tt,x2,qj);
635: else PetscFree(dval);
636: VecResetArray(tu);
637: VecRestoreArray(u[0],&array1);
638: VecResetArray(tp);
639: VecRestoreArray(p[0],&array2);
640: #if !defined(PETSC_USE_COMPLEX)
641: if (sz==2) {
642: VecResetArray(tui);
643: VecRestoreArray(u[1],&arrayi1);
644: VecResetArray(tpi);
645: VecRestoreArray(p[1],&arrayi2);
646: }
647: #endif
648: PetscFunctionReturn(0);
649: }
651: static PetscErrorCode PEPJDProcessInitialSpace(PEP pep,Vec *w)
652: {
653: PEP_JD *pjd = (PEP_JD*)pep->data;
654: PetscScalar *tt,target[2];
655: Vec vg,wg;
656: PetscInt i;
657: PetscReal norm;
659: PetscMalloc1(pjd->ld-1,&tt);
661: BVSetRandomColumn(pjd->V,0);
662: for (i=0;i<pjd->ld-1;i++) tt[i] = 0.0;
663: BVGetColumn(pjd->V,0,&vg);
664: PEPJDCopyToExtendedVec(pep,NULL,tt,pjd->ld-1,0,vg,PETSC_FALSE);
665: BVRestoreColumn(pjd->V,0,&vg);
666: BVNormColumn(pjd->V,0,NORM_2,&norm);
667: BVScaleColumn(pjd->V,0,1.0/norm);
668: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
669: BVGetColumn(pjd->V,0,&vg);
670: BVGetColumn(pjd->W,0,&wg);
671: VecSet(wg,0.0);
672: target[0] = pep->target; target[1] = 0.0;
673: PEPJDComputeResidual(pep,PETSC_TRUE,1,&vg,target,&wg,w);
674: BVRestoreColumn(pjd->W,0,&wg);
675: BVRestoreColumn(pjd->V,0,&vg);
676: BVNormColumn(pjd->W,0,NORM_2,&norm);
677: BVScaleColumn(pjd->W,0,1.0/norm);
678: }
679: PetscFree(tt);
680: PetscFunctionReturn(0);
681: }
683: static PetscErrorCode MatMult_PEPJD(Mat P,Vec x,Vec y)
684: {
685: PEP_JD_MATSHELL *matctx;
686: PEP_JD *pjd;
687: PetscInt i,j,nconv,nloc,nmat,ldt,ncv,sz;
688: Vec tx,ty;
689: const Vec *xs,*ys;
690: PetscScalar *array1,*array2,*x2=NULL,*y2,*tt=NULL,*xx=NULL,*xxi,theta[2],sone=1.0,*qj,*val,*vali=NULL;
691: PetscBLASInt n,ld,one=1;
692: PetscMPIInt np;
693: #if !defined(PETSC_USE_COMPLEX)
694: Vec txi=NULL,tyi=NULL;
695: PetscScalar *x2i=NULL,*qji=NULL,*qq,*y2i,*arrayi1,*arrayi2;
696: #endif
698: MPI_Comm_size(PetscObjectComm((PetscObject)P),&np);
699: MatShellGetContext(P,&matctx);
700: pjd = (PEP_JD*)(matctx->pep->data);
701: nconv = pjd->nlock;
702: nmat = matctx->pep->nmat;
703: ncv = matctx->pep->ncv;
704: ldt = pjd->ld;
705: VecCompGetSubVecs(x,&sz,&xs);
706: VecCompGetSubVecs(y,NULL,&ys);
707: theta[0] = matctx->theta[0];
708: theta[1] = (sz==2)?matctx->theta[1]:0.0;
709: if (nconv>0) {
710: PetscMalloc5(nconv,&tt,sz*nconv,&x2,(sz==2?3:1)*nconv*nmat,&qj,2*nconv,&xx,2*nmat,&val);
711: BVGetSizes(matctx->pep->V,&nloc,NULL,NULL);
712: VecGetArray(xs[0],&array1);
713: for (i=0;i<nconv;i++) x2[i] = array1[nloc+i]* PetscSqrtReal(np);
714: VecRestoreArray(xs[0],&array1);
715: #if !defined(PETSC_USE_COMPLEX)
716: if (sz==2) {
717: x2i = x2+nconv;
718: VecGetArray(xs[1],&arrayi1);
719: for (i=0;i<nconv;i++) x2i[i] = arrayi1[nloc+i]* PetscSqrtReal(np);
720: VecRestoreArray(xs[1],&arrayi1);
721: }
722: #endif
723: vali = val+nmat;
724: }
725: tx = matctx->work[0];
726: ty = matctx->work[1];
727: VecGetArray(xs[0],&array1);
728: VecPlaceArray(tx,array1);
729: VecGetArray(ys[0],&array2);
730: VecPlaceArray(ty,array2);
731: MatMult(matctx->Pr,tx,ty);
732: #if !defined(PETSC_USE_COMPLEX)
733: if (sz==2) {
734: txi = matctx->work[2];
735: tyi = matctx->work[3];
736: VecGetArray(xs[1],&arrayi1);
737: VecPlaceArray(txi,arrayi1);
738: VecGetArray(ys[1],&arrayi2);
739: VecPlaceArray(tyi,arrayi2);
740: MatMult(matctx->Pr,txi,tyi);
741: if (theta[1]!=0.0) {
742: MatMult(matctx->Pi,txi,matctx->work[4]);
743: VecAXPY(ty,-1.0,matctx->work[4]);
744: MatMult(matctx->Pi,tx,matctx->work[4]);
745: VecAXPY(tyi,1.0,matctx->work[4]);
746: }
747: }
748: #endif
749: if (nconv>0) {
750: PEPEvaluateBasis(matctx->pep,theta[0],theta[1],val,vali);
751: for (i=0;i<nmat;i++) PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,ncv,val,x2,i,i>1?qj+(i-2)*nconv:NULL,i>0?qj+(i-1)*nconv:NULL,qj+i*nconv);
752: #if !defined(PETSC_USE_COMPLEX)
753: if (sz==2) {
754: qji = qj+nconv*nmat;
755: qq = qji+nconv*nmat;
756: for (i=0;i<nmat;i++) PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,matctx->pep->ncv,vali,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv);
757: for (i=0;i<nconv*nmat;i++) qj[i] -= qji[i];
758: for (i=0;i<nmat;i++) {
759: PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,matctx->pep->ncv,val,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv);
760: PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,matctx->pep->ncv,vali,x2,i,i>1?qq+(i-2)*nconv:NULL,i>0?qq+(i-1)*nconv:NULL,qq+i*nconv);
761: }
762: for (i=0;i<nconv*nmat;i++) qji[i] += qq[i];
763: for (i=1;i<matctx->pep->nmat;i++) BVMultVec(pjd->AX[i],1.0,1.0,tyi,qji+i*nconv);
764: }
765: #endif
766: for (i=1;i<nmat;i++) BVMultVec(pjd->AX[i],1.0,1.0,ty,qj+i*nconv);
768: /* extended vector part */
769: BVSetActiveColumns(pjd->X,0,nconv);
770: BVDotVec(pjd->X,tx,xx);
771: xxi = xx+nconv;
772: #if !defined(PETSC_USE_COMPLEX)
773: if (sz==2) BVDotVec(pjd->X,txi,xxi);
774: #endif
775: if (sz==1) PetscArrayzero(xxi,nconv);
776: PetscBLASIntCast(pjd->nlock,&n);
777: PetscBLASIntCast(ldt,&ld);
778: y2 = array2+nloc;
779: PetscArrayzero(y2,nconv);
780: for (j=0;j<pjd->midx;j++) {
781: for (i=0;i<nconv;i++) tt[i] = val[j]*xx[i]-vali[j]*xxi[i];
782: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qj+j*nconv,&one,&sone,tt,&one));
783: PetscStackCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2,&one));
784: }
785: #if !defined(PETSC_USE_COMPLEX)
786: if (sz==2) {
787: y2i = arrayi2+nloc;
788: PetscArrayzero(y2i,nconv);
789: for (j=0;j<pjd->midx;j++) {
790: for (i=0;i<nconv;i++) tt[i] = val[j]*xxi[i]+vali[j]*xx[i];
791: PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qji+j*nconv,&one,&sone,tt,&one));
792: PetscStackCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2i,&one));
793: }
794: for (i=0;i<nconv;i++) arrayi2[nloc+i] /= PetscSqrtReal(np);
795: }
796: #endif
797: for (i=0;i<nconv;i++) array2[nloc+i] /= PetscSqrtReal(np);
798: PetscFree5(tt,x2,qj,xx,val);
799: }
800: VecResetArray(tx);
801: VecRestoreArray(xs[0],&array1);
802: VecResetArray(ty);
803: VecRestoreArray(ys[0],&array2);
804: #if !defined(PETSC_USE_COMPLEX)
805: if (sz==2) {
806: VecResetArray(txi);
807: VecRestoreArray(xs[1],&arrayi1);
808: VecResetArray(tyi);
809: VecRestoreArray(ys[1],&arrayi2);
810: }
811: #endif
812: PetscFunctionReturn(0);
813: }
815: static PetscErrorCode MatCreateVecs_PEPJD(Mat A,Vec *right,Vec *left)
816: {
817: PEP_JD_MATSHELL *matctx;
818: PEP_JD *pjd;
819: PetscInt kspsf=1,i;
820: Vec v[2];
822: MatShellGetContext(A,&matctx);
823: pjd = (PEP_JD*)(matctx->pep->data);
824: #if !defined (PETSC_USE_COMPLEX)
825: kspsf = 2;
826: #endif
827: for (i=0;i<kspsf;i++) BVCreateVec(pjd->V,v+i);
828: if (right) VecCreateCompWithVecs(v,kspsf,pjd->vtempl,right);
829: if (left) VecCreateCompWithVecs(v,kspsf,pjd->vtempl,left);
830: for (i=0;i<kspsf;i++) VecDestroy(&v[i]);
831: PetscFunctionReturn(0);
832: }
834: static PetscErrorCode PEPJDUpdateExtendedPC(PEP pep,PetscScalar theta)
835: {
836: PEP_JD *pjd = (PEP_JD*)pep->data;
837: PEP_JD_PCSHELL *pcctx;
838: PetscInt i,j,k,n=pjd->nlock,ld=pjd->ld,deg=pep->nmat-1;
839: PetscScalar *M,*ps,*work,*U,*V,*S,*Sp,*Spp,snone=-1.0,sone=1.0,zero=0.0,*val;
840: PetscReal tol,maxeig=0.0,*sg,*rwork;
841: PetscBLASInt n_,info,ld_,*p,lw_,rk=0;
843: if (n) {
844: PCShellGetContext(pjd->pcshell,&pcctx);
845: pcctx->theta = theta;
846: pcctx->n = n;
847: M = pcctx->M;
848: PetscBLASIntCast(n,&n_);
849: PetscBLASIntCast(ld,&ld_);
850: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
851: if (pjd->midx==1) {
852: PetscArraycpy(M,pjd->XpX,ld*ld);
853: PetscCalloc2(10*n,&work,n,&p);
854: } else {
855: ps = pcctx->ps;
856: PetscCalloc7(2*n*n,&U,3*n*n,&S,n,&sg,10*n,&work,5*n,&rwork,n,&p,deg+1,&val);
857: V = U+n*n;
858: /* pseudo-inverse */
859: for (j=0;j<n;j++) {
860: for (i=0;i<n;i++) S[n*j+i] = -pjd->T[pep->ncv*j+i];
861: S[n*j+j] += theta;
862: }
863: lw_ = 10*n_;
864: #if !defined (PETSC_USE_COMPLEX)
865: PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("S","S",&n_,&n_,S,&n_,sg,U,&n_,V,&n_,work,&lw_,&info));
866: #else
867: PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("S","S",&n_,&n_,S,&n_,sg,U,&n_,V,&n_,work,&lw_,rwork,&info));
868: #endif
869: SlepcCheckLapackInfo("gesvd",info);
870: for (i=0;i<n;i++) maxeig = PetscMax(maxeig,sg[i]);
871: tol = 10*PETSC_MACHINE_EPSILON*n*maxeig;
872: for (j=0;j<n;j++) {
873: if (sg[j]>tol) {
874: for (i=0;i<n;i++) U[j*n+i] /= sg[j];
875: rk++;
876: } else break;
877: }
878: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&rk,&sone,U,&n_,V,&n_,&zero,ps,&ld_));
880: /* compute M */
881: PEPEvaluateBasis(pep,theta,0.0,val,NULL);
882: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&snone,pjd->XpX,&ld_,ps,&ld_,&zero,M,&ld_));
883: PetscArrayzero(S,2*n*n);
884: Sp = S+n*n;
885: for (j=0;j<n;j++) S[j*(n+1)] = 1.0;
886: for (k=1;k<pjd->midx;k++) {
887: for (j=0;j<n;j++) for (i=0;i<n;i++) V[j*n+i] = S[j*n+i] - ps[j*ld+i]*val[k];
888: PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&sone,pjd->XpX,&ld_,V,&n_,&zero,U,&n_));
889: PetscStackCallBLAS("BLASgemm",BLASgemm_("C","N",&n_,&n_,&n_,&sone,pjd->Tj+k*ld*ld,&ld_,U,&n_,&sone,M,&ld_));
890: Spp = Sp; Sp = S;
891: PEPJDEvaluateHatBasis(pep,n,pjd->T,pep->ncv,val,NULL,k+1,Spp,Sp,S);
892: }
893: }
894: /* inverse */
895: PetscStackCallBLAS("LAPACKgetrf",LAPACKgetrf_(&n_,&n_,M,&ld_,p,&info));
896: SlepcCheckLapackInfo("getrf",info);
897: PetscStackCallBLAS("LAPACKgetri",LAPACKgetri_(&n_,M,&ld_,p,work,&n_,&info));
898: SlepcCheckLapackInfo("getri",info);
899: PetscFPTrapPop();
900: if (pjd->midx==1) PetscFree2(work,p);
901: else PetscFree7(U,S,sg,work,rwork,p,val);
902: }
903: PetscFunctionReturn(0);
904: }
906: static PetscErrorCode PEPJDMatSetUp(PEP pep,PetscInt sz,PetscScalar *theta)
907: {
908: PEP_JD *pjd = (PEP_JD*)pep->data;
909: PEP_JD_MATSHELL *matctx;
910: PEP_JD_PCSHELL *pcctx;
911: MatStructure str;
912: PetscScalar *vals,*valsi;
913: PetscBool skipmat=PETSC_FALSE;
914: PetscInt i;
915: Mat Pr=NULL;
917: if (sz==2 && theta[1]==0.0) sz = 1;
918: MatShellGetContext(pjd->Pshell,&matctx);
919: PCShellGetContext(pjd->pcshell,&pcctx);
920: if (matctx->Pr && matctx->theta[0]==theta[0] && ((!matctx->Pi && sz==1) || (sz==2 && matctx->theta[1]==theta[1]))) {
921: if (pcctx->n == pjd->nlock) PetscFunctionReturn(0);
922: skipmat = PETSC_TRUE;
923: }
924: if (!skipmat) {
925: PetscMalloc2(pep->nmat,&vals,pep->nmat,&valsi);
926: STGetMatStructure(pep->st,&str);
927: PEPEvaluateBasis(pep,theta[0],theta[1],vals,valsi);
928: if (!matctx->Pr) MatDuplicate(pep->A[0],MAT_COPY_VALUES,&matctx->Pr);
929: else MatCopy(pep->A[0],matctx->Pr,str);
930: for (i=1;i<pep->nmat;i++) MatAXPY(matctx->Pr,vals[i],pep->A[i],str);
931: if (!pjd->reusepc) {
932: if (pcctx->PPr && sz==2) {
933: MatCopy(matctx->Pr,pcctx->PPr,str);
934: Pr = pcctx->PPr;
935: } else Pr = matctx->Pr;
936: }
937: matctx->theta[0] = theta[0];
938: #if !defined(PETSC_USE_COMPLEX)
939: if (sz==2) {
940: if (!matctx->Pi) MatDuplicate(pep->A[0],MAT_COPY_VALUES,&matctx->Pi);
941: else MatCopy(pep->A[1],matctx->Pi,str);
942: MatScale(matctx->Pi,valsi[1]);
943: for (i=2;i<pep->nmat;i++) MatAXPY(matctx->Pi,valsi[i],pep->A[i],str);
944: matctx->theta[1] = theta[1];
945: }
946: #endif
947: PetscFree2(vals,valsi);
948: }
949: if (!pjd->reusepc) {
950: if (!skipmat) {
951: PCSetOperators(pcctx->pc,Pr,Pr);
952: PCSetUp(pcctx->pc);
953: }
954: PEPJDUpdateExtendedPC(pep,theta[0]);
955: }
956: PetscFunctionReturn(0);
957: }
959: static PetscErrorCode PEPJDCreateShellPC(PEP pep,Vec *ww)
960: {
961: PEP_JD *pjd = (PEP_JD*)pep->data;
962: PEP_JD_PCSHELL *pcctx;
963: PEP_JD_MATSHELL *matctx;
964: KSP ksp;
965: PetscInt nloc,mloc,kspsf=1;
966: Vec v[2];
967: PetscScalar target[2];
968: Mat Pr;
970: /* Create the reference vector */
971: BVGetColumn(pjd->V,0,&v[0]);
972: v[1] = v[0];
973: #if !defined (PETSC_USE_COMPLEX)
974: kspsf = 2;
975: #endif
976: VecCreateCompWithVecs(v,kspsf,NULL,&pjd->vtempl);
977: BVRestoreColumn(pjd->V,0,&v[0]);
978: PetscLogObjectParent((PetscObject)pep,(PetscObject)pjd->vtempl);
980: /* Replace preconditioner with one containing projectors */
981: PCCreate(PetscObjectComm((PetscObject)pep),&pjd->pcshell);
982: PCSetType(pjd->pcshell,PCSHELL);
983: PCShellSetName(pjd->pcshell,"PCPEPJD");
984: PCShellSetApply(pjd->pcshell,PCShellApply_PEPJD);
985: PetscNew(&pcctx);
986: PCShellSetContext(pjd->pcshell,pcctx);
987: STGetKSP(pep->st,&ksp);
988: BVCreateVec(pjd->V,&pcctx->Bp[0]);
989: VecDuplicate(pcctx->Bp[0],&pcctx->Bp[1]);
990: KSPGetPC(ksp,&pcctx->pc);
991: PetscObjectReference((PetscObject)pcctx->pc);
992: MatGetLocalSize(pep->A[0],&mloc,&nloc);
993: if (pjd->ld>1) {
994: nloc += pjd->ld-1; mloc += pjd->ld-1;
995: }
996: PetscNew(&matctx);
997: MatCreateShell(PetscObjectComm((PetscObject)pep),kspsf*nloc,kspsf*mloc,PETSC_DETERMINE,PETSC_DETERMINE,matctx,&pjd->Pshell);
998: MatShellSetOperation(pjd->Pshell,MATOP_MULT,(void(*)(void))MatMult_PEPJD);
999: MatShellSetOperation(pjd->Pshell,MATOP_CREATE_VECS,(void(*)(void))MatCreateVecs_PEPJD);
1000: matctx->pep = pep;
1001: target[0] = pep->target; target[1] = 0.0;
1002: PEPJDMatSetUp(pep,1,target);
1003: Pr = matctx->Pr;
1004: pcctx->PPr = NULL;
1005: #if !defined(PETSC_USE_COMPLEX)
1006: if (!pjd->reusepc) {
1007: MatDuplicate(matctx->Pr,MAT_COPY_VALUES,&pcctx->PPr);
1008: Pr = pcctx->PPr;
1009: }
1010: #endif
1011: PCSetOperators(pcctx->pc,Pr,Pr);
1012: PCSetErrorIfFailure(pcctx->pc,PETSC_TRUE);
1013: KSPSetPC(ksp,pjd->pcshell);
1014: if (pjd->reusepc) {
1015: PCSetReusePreconditioner(pcctx->pc,PETSC_TRUE);
1016: KSPSetReusePreconditioner(ksp,PETSC_TRUE);
1017: }
1018: PEP_KSPSetOperators(ksp,pjd->Pshell,pjd->Pshell);
1019: KSPSetUp(ksp);
1020: if (pjd->ld>1) {
1021: PetscMalloc2(pjd->ld*pjd->ld,&pcctx->M,pjd->ld*pjd->ld,&pcctx->ps);
1022: pcctx->pep = pep;
1023: }
1024: matctx->work = ww;
1025: pcctx->work = ww;
1026: PetscFunctionReturn(0);
1027: }
1029: static PetscErrorCode PEPJDEigenvectors(PEP pep)
1030: {
1031: PEP_JD *pjd = (PEP_JD*)pep->data;
1032: PetscBLASInt ld,nconv,info,nc;
1033: PetscScalar *Z;
1034: PetscReal *wr;
1035: Mat U;
1036: #if defined(PETSC_USE_COMPLEX)
1037: PetscScalar *w;
1038: #endif
1040: PetscBLASIntCast(pep->ncv,&ld);
1041: PetscBLASIntCast(pep->nconv,&nconv);
1042: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
1043: #if !defined(PETSC_USE_COMPLEX)
1044: PetscMalloc2(pep->nconv*pep->nconv,&Z,3*pep->ncv,&wr);
1045: PetscStackCallBLAS("LAPACKtrevc",LAPACKtrevc_("R","A",NULL,&nconv,pjd->T,&ld,NULL,&nconv,Z,&nconv,&nconv,&nc,wr,&info));
1046: #else
1047: PetscMalloc3(pep->nconv*pep->nconv,&Z,3*pep->ncv,&wr,2*pep->ncv,&w);
1048: PetscStackCallBLAS("LAPACKtrevc",LAPACKtrevc_("R","A",NULL,&nconv,pjd->T,&ld,NULL,&nconv,Z,&nconv,&nconv,&nc,w,wr,&info));
1049: #endif
1050: PetscFPTrapPop();
1051: SlepcCheckLapackInfo("trevc",info);
1052: MatCreateSeqDense(PETSC_COMM_SELF,nconv,nconv,Z,&U);
1053: BVSetActiveColumns(pjd->X,0,pep->nconv);
1054: BVMultInPlace(pjd->X,U,0,pep->nconv);
1055: BVNormalize(pjd->X,pep->eigi);
1056: MatDestroy(&U);
1057: #if !defined(PETSC_USE_COMPLEX)
1058: PetscFree2(Z,wr);
1059: #else
1060: PetscFree3(Z,wr,w);
1061: #endif
1062: PetscFunctionReturn(0);
1063: }
1065: static PetscErrorCode PEPJDLockConverged(PEP pep,PetscInt *nv,PetscInt sz)
1066: {
1067: PEP_JD *pjd = (PEP_JD*)pep->data;
1068: PetscInt j,i,*P,ldds,rk=0,nvv=*nv;
1069: Vec v,x,w;
1070: PetscScalar *R,*r,*pX,target[2];
1071: Mat X;
1072: PetscBLASInt sz_,rk_,nv_,info;
1073: PetscMPIInt np;
1075: /* update AX and XpX */
1076: for (i=sz;i>0;i--) {
1077: BVGetColumn(pjd->X,pjd->nlock-i,&x);
1078: for (j=0;j<pep->nmat;j++) {
1079: BVGetColumn(pjd->AX[j],pjd->nlock-i,&v);
1080: MatMult(pep->A[j],x,v);
1081: BVRestoreColumn(pjd->AX[j],pjd->nlock-i,&v);
1082: BVSetActiveColumns(pjd->AX[j],0,pjd->nlock-i+1);
1083: }
1084: BVRestoreColumn(pjd->X,pjd->nlock-i,&x);
1085: BVDotColumn(pjd->X,(pjd->nlock-i),pjd->XpX+(pjd->nlock-i)*(pjd->ld));
1086: pjd->XpX[(pjd->nlock-i)*(1+pjd->ld)] = 1.0;
1087: for (j=0;j<pjd->nlock-i;j++) pjd->XpX[j*(pjd->ld)+pjd->nlock-i] = PetscConj(pjd->XpX[(pjd->nlock-i)*(pjd->ld)+j]);
1088: }
1090: /* minimality index */
1091: pjd->midx = PetscMin(pjd->mmidx,pjd->nlock);
1093: /* evaluate the polynomial basis in T */
1094: PetscArrayzero(pjd->Tj,pjd->ld*pjd->ld*pep->nmat);
1095: for (j=0;j<pep->nmat;j++) PEPEvaluateBasisMat(pep,pjd->nlock,pjd->T,pep->ncv,j,(j>1)?pjd->Tj+(j-2)*pjd->ld*pjd->ld:NULL,pjd->ld,j?pjd->Tj+(j-1)*pjd->ld*pjd->ld:NULL,pjd->ld,pjd->Tj+j*pjd->ld*pjd->ld,pjd->ld);
1097: /* Extend search space */
1098: MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np);
1099: PetscCalloc3(nvv,&P,nvv*nvv,&R,nvv*sz,&r);
1100: DSGetLeadingDimension(pep->ds,&ldds);
1101: DSGetArray(pep->ds,DS_MAT_X,&pX);
1102: PEPJDOrthogonalize(nvv,nvv,pX,ldds,&rk,P,R,nvv);
1103: for (j=0;j<sz;j++) {
1104: for (i=0;i<rk;i++) r[i*sz+j] = PetscConj(R[nvv*i+j]*pep->eigr[P[i]]); /* first row scaled with permuted diagonal */
1105: }
1106: PetscBLASIntCast(rk,&rk_);
1107: PetscBLASIntCast(sz,&sz_);
1108: PetscBLASIntCast(nvv,&nv_);
1109: PetscFPTrapPush(PETSC_FP_TRAP_OFF);
1110: PetscStackCallBLAS("LAPACKtrtri",LAPACKtrtri_("U","N",&rk_,R,&nv_,&info));
1111: PetscFPTrapPop();
1112: SlepcCheckLapackInfo("trtri",info);
1113: for (i=0;i<sz;i++) PetscStackCallBLAS("BLAStrmv",BLAStrmv_("U","C","N",&rk_,R,&nv_,r+i,&sz_));
1114: for (i=0;i<sz*rk;i++) r[i] = PetscConj(r[i])/PetscSqrtReal(np); /* revert */
1115: BVSetActiveColumns(pjd->V,0,nvv);
1116: rk -= sz;
1117: for (j=0;j<rk;j++) PetscArraycpy(R+j*nvv,pX+(j+sz)*ldds,nvv);
1118: DSRestoreArray(pep->ds,DS_MAT_X,&pX);
1119: MatCreateSeqDense(PETSC_COMM_SELF,nvv,rk,R,&X);
1120: BVMultInPlace(pjd->V,X,0,rk);
1121: MatDestroy(&X);
1122: BVSetActiveColumns(pjd->V,0,rk);
1123: for (j=0;j<rk;j++) {
1124: BVGetColumn(pjd->V,j,&v);
1125: PEPJDCopyToExtendedVec(pep,NULL,r+sz*(j+sz),sz,pjd->nlock-sz,v,PETSC_FALSE);
1126: BVRestoreColumn(pjd->V,j,&v);
1127: }
1128: BVOrthogonalize(pjd->V,NULL);
1130: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
1131: for (j=0;j<rk;j++) {
1132: /* W = P(target)*V */
1133: BVGetColumn(pjd->W,j,&w);
1134: BVGetColumn(pjd->V,j,&v);
1135: target[0] = pep->target; target[1] = 0.0;
1136: PEPJDComputeResidual(pep,PETSC_FALSE,1,&v,target,&w,pep->work);
1137: BVRestoreColumn(pjd->V,j,&v);
1138: BVRestoreColumn(pjd->W,j,&w);
1139: }
1140: BVSetActiveColumns(pjd->W,0,rk);
1141: BVOrthogonalize(pjd->W,NULL);
1142: }
1143: *nv = rk;
1144: PetscFree3(P,R,r);
1145: PetscFunctionReturn(0);
1146: }
1148: PetscErrorCode PEPJDSystemSetUp(PEP pep,PetscInt sz,PetscScalar *theta,Vec *u,Vec *p,Vec *ww)
1149: {
1150: PEP_JD *pjd = (PEP_JD*)pep->data;
1151: PEP_JD_PCSHELL *pcctx;
1152: #if !defined(PETSC_USE_COMPLEX)
1153: PetscScalar s[2];
1154: #endif
1156: PCShellGetContext(pjd->pcshell,&pcctx);
1157: PEPJDMatSetUp(pep,sz,theta);
1158: pcctx->u[0] = u[0]; pcctx->u[1] = u[1];
1159: /* Compute r'. p is a work space vector */
1160: PEPJDComputeResidual(pep,PETSC_TRUE,sz,u,theta,p,ww);
1161: PEPJDExtendedPCApply(pjd->pcshell,p[0],pcctx->Bp[0]);
1162: VecDot(pcctx->Bp[0],u[0],pcctx->gamma);
1163: #if !defined(PETSC_USE_COMPLEX)
1164: if (sz==2) {
1165: PEPJDExtendedPCApply(pjd->pcshell,p[1],pcctx->Bp[1]);
1166: VecDot(pcctx->Bp[0],u[1],pcctx->gamma+1);
1167: VecMDot(pcctx->Bp[1],2,u,s);
1168: pcctx->gamma[0] += s[1];
1169: pcctx->gamma[1] = -pcctx->gamma[1]+s[0];
1170: }
1171: #endif
1172: if (sz==1) {
1173: VecZeroEntries(pcctx->Bp[1]);
1174: pcctx->gamma[1] = 0.0;
1175: }
1176: PetscFunctionReturn(0);
1177: }
1179: PetscErrorCode PEPSolve_JD(PEP pep)
1180: {
1181: PEP_JD *pjd = (PEP_JD*)pep->data;
1182: PetscInt k,nv,nvc,ld,minv,dim,bupdated=0,sz=1,kspsf=1,idx,off,maxits,nloc;
1183: PetscMPIInt np,count;
1184: PetscScalar theta[2]={0.0,0.0},ritz[2]={0.0,0.0},*pX,*eig,*eigi,*array;
1185: PetscReal norm,*res,tol=0.0,rtol,abstol, dtol;
1186: PetscBool lindep,ini=PETSC_TRUE;
1187: Vec tc,t[2]={NULL,NULL},u[2]={NULL,NULL},p[2]={NULL,NULL};
1188: Vec rc,rr[2],r[2]={NULL,NULL},*ww=pep->work,v[2];
1189: Mat G,X,Y;
1190: KSP ksp;
1191: PEP_JD_PCSHELL *pcctx;
1192: PEP_JD_MATSHELL *matctx;
1193: #if !defined(PETSC_USE_COMPLEX)
1194: PetscReal norm1;
1195: #endif
1197: PetscCitationsRegister(citation,&cited);
1198: MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np);
1199: BVGetSizes(pep->V,&nloc,NULL,NULL);
1200: DSGetLeadingDimension(pep->ds,&ld);
1201: PetscCalloc3(pep->ncv+pep->nev,&eig,pep->ncv+pep->nev,&eigi,pep->ncv+pep->nev,&res);
1202: pjd->nlock = 0;
1203: STGetKSP(pep->st,&ksp);
1204: KSPGetTolerances(ksp,&rtol,&abstol,&dtol,&maxits);
1205: #if !defined (PETSC_USE_COMPLEX)
1206: kspsf = 2;
1207: #endif
1208: PEPJDProcessInitialSpace(pep,ww);
1209: nv = (pep->nini)?pep->nini:1;
1211: /* Replace preconditioner with one containing projectors */
1212: PEPJDCreateShellPC(pep,ww);
1213: PCShellGetContext(pjd->pcshell,&pcctx);
1215: /* Create auxiliary vectors */
1216: BVCreateVec(pjd->V,&u[0]);
1217: VecDuplicate(u[0],&p[0]);
1218: VecDuplicate(u[0],&r[0]);
1219: #if !defined (PETSC_USE_COMPLEX)
1220: VecDuplicate(u[0],&u[1]);
1221: VecDuplicate(u[0],&p[1]);
1222: VecDuplicate(u[0],&r[1]);
1223: #endif
1225: /* Restart loop */
1226: while (pep->reason == PEP_CONVERGED_ITERATING) {
1227: pep->its++;
1228: DSSetDimensions(pep->ds,nv,0,0);
1229: BVSetActiveColumns(pjd->V,bupdated,nv);
1230: PEPJDUpdateTV(pep,bupdated,nv,ww);
1231: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) BVSetActiveColumns(pjd->W,bupdated,nv);
1232: for (k=0;k<pep->nmat;k++) {
1233: BVSetActiveColumns(pjd->TV[k],bupdated,nv);
1234: DSGetMat(pep->ds,DSMatExtra[k],&G);
1235: BVMatProject(pjd->TV[k],NULL,pjd->W,G);
1236: DSRestoreMat(pep->ds,DSMatExtra[k],&G);
1237: }
1238: BVSetActiveColumns(pjd->V,0,nv);
1239: BVSetActiveColumns(pjd->W,0,nv);
1241: /* Solve projected problem */
1242: DSSetState(pep->ds,DS_STATE_RAW);
1243: DSSolve(pep->ds,pep->eigr,pep->eigi);
1244: DSSort(pep->ds,pep->eigr,pep->eigi,NULL,NULL,NULL);
1245: DSSynchronize(pep->ds,pep->eigr,pep->eigi);
1246: idx = 0;
1247: do {
1248: ritz[0] = pep->eigr[idx];
1249: #if !defined(PETSC_USE_COMPLEX)
1250: ritz[1] = pep->eigi[idx];
1251: sz = (ritz[1]==0.0)?1:2;
1252: #endif
1253: /* Compute Ritz vector u=V*X(:,1) */
1254: DSGetArray(pep->ds,DS_MAT_X,&pX);
1255: BVSetActiveColumns(pjd->V,0,nv);
1256: BVMultVec(pjd->V,1.0,0.0,u[0],pX+idx*ld);
1257: #if !defined(PETSC_USE_COMPLEX)
1258: if (sz==2) BVMultVec(pjd->V,1.0,0.0,u[1],pX+(idx+1)*ld);
1259: #endif
1260: DSRestoreArray(pep->ds,DS_MAT_X,&pX);
1261: PEPJDComputeResidual(pep,PETSC_FALSE,sz,u,ritz,r,ww);
1262: /* Check convergence */
1263: VecNorm(r[0],NORM_2,&norm);
1264: #if !defined(PETSC_USE_COMPLEX)
1265: if (sz==2) {
1266: VecNorm(r[1],NORM_2,&norm1);
1267: norm = SlepcAbs(norm,norm1);
1268: }
1269: #endif
1270: (*pep->converged)(pep,ritz[0],ritz[1],norm,&pep->errest[pep->nconv],pep->convergedctx);
1271: if (sz==2) pep->errest[pep->nconv+1] = pep->errest[pep->nconv];
1272: if (ini) {
1273: tol = PetscMin(.1,pep->errest[pep->nconv]); ini = PETSC_FALSE;
1274: } else tol = PetscMin(pep->errest[pep->nconv],tol/2);
1275: (*pep->stopping)(pep,pep->its,pep->max_it,(pep->errest[pep->nconv]<pep->tol)?pep->nconv+sz:pep->nconv,pep->nev,&pep->reason,pep->stoppingctx);
1276: if (pep->errest[pep->nconv]<pep->tol) {
1277: /* Ritz pair converged */
1278: ini = PETSC_TRUE;
1279: minv = PetscMin(nv,(PetscInt)(pjd->keep*pep->ncv));
1280: if (pjd->ld>1) {
1281: BVGetColumn(pjd->X,pep->nconv,&v[0]);
1282: PEPJDCopyToExtendedVec(pep,v[0],pjd->T+pep->ncv*pep->nconv,pjd->ld-1,0,u[0],PETSC_TRUE);
1283: BVRestoreColumn(pjd->X,pep->nconv,&v[0]);
1284: BVSetActiveColumns(pjd->X,0,pep->nconv+1);
1285: BVNormColumn(pjd->X,pep->nconv,NORM_2,&norm);
1286: BVScaleColumn(pjd->X,pep->nconv,1.0/norm);
1287: for (k=0;k<pep->nconv;k++) pjd->T[pep->ncv*pep->nconv+k] *= PetscSqrtReal(np)/norm;
1288: pjd->T[(pep->ncv+1)*pep->nconv] = ritz[0];
1289: eig[pep->nconv] = ritz[0];
1290: idx++;
1291: #if !defined(PETSC_USE_COMPLEX)
1292: if (sz==2) {
1293: BVGetColumn(pjd->X,pep->nconv+1,&v[0]);
1294: PEPJDCopyToExtendedVec(pep,v[0],pjd->T+pep->ncv*(pep->nconv+1),pjd->ld-1,0,u[1],PETSC_TRUE);
1295: BVRestoreColumn(pjd->X,pep->nconv+1,&v[0]);
1296: BVSetActiveColumns(pjd->X,0,pep->nconv+2);
1297: BVNormColumn(pjd->X,pep->nconv+1,NORM_2,&norm1);
1298: BVScaleColumn(pjd->X,pep->nconv+1,1.0/norm1);
1299: for (k=0;k<pep->nconv;k++) pjd->T[pep->ncv*(pep->nconv+1)+k] *= PetscSqrtReal(np)/norm1;
1300: pjd->T[(pep->ncv+1)*(pep->nconv+1)] = ritz[0];
1301: pjd->T[(pep->ncv+1)*pep->nconv+1] = -ritz[1]*norm1/norm;
1302: pjd->T[(pep->ncv+1)*(pep->nconv+1)-1] = ritz[1]*norm/norm1;
1303: eig[pep->nconv+1] = ritz[0];
1304: eigi[pep->nconv] = ritz[1]; eigi[pep->nconv+1] = -ritz[1];
1305: idx++;
1306: }
1307: #endif
1308: } else BVInsertVec(pep->V,pep->nconv,u[0]);
1309: pep->nconv += sz;
1310: }
1311: } while (pep->errest[pep->nconv]<pep->tol && pep->nconv<nv);
1313: if (pep->reason==PEP_CONVERGED_ITERATING) {
1314: nvc = nv;
1315: if (idx) {
1316: pjd->nlock +=idx;
1317: PEPJDLockConverged(pep,&nv,idx);
1318: }
1319: if (nv+sz>=pep->ncv-1) {
1320: /* Basis full, force restart */
1321: minv = PetscMin(nv,(PetscInt)(pjd->keep*pep->ncv));
1322: DSGetDimensions(pep->ds,&dim,NULL,NULL,NULL);
1323: DSGetArray(pep->ds,DS_MAT_X,&pX);
1324: PEPJDOrthogonalize(dim,minv,pX,ld,&minv,NULL,NULL,ld);
1325: DSRestoreArray(pep->ds,DS_MAT_X,&pX);
1326: DSGetArray(pep->ds,DS_MAT_Y,&pX);
1327: PEPJDOrthogonalize(dim,minv,pX,ld,&minv,NULL,NULL,ld);
1328: DSRestoreArray(pep->ds,DS_MAT_Y,&pX);
1329: DSGetMat(pep->ds,DS_MAT_X,&X);
1330: BVMultInPlace(pjd->V,X,0,minv);
1331: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
1332: DSGetMat(pep->ds,DS_MAT_Y,&Y);
1333: BVMultInPlace(pjd->W,Y,pep->nconv,minv);
1334: DSRestoreMat(pep->ds,DS_MAT_Y,&Y);
1335: }
1336: MatDestroy(&X);
1337: nv = minv;
1338: bupdated = 0;
1339: } else {
1340: if (!idx && pep->errest[pep->nconv]<pjd->fix) {theta[0] = ritz[0]; theta[1] = ritz[1];}
1341: else {theta[0] = pep->target; theta[1] = 0.0;}
1342: /* Update system mat */
1343: PEPJDSystemSetUp(pep,sz,theta,u,p,ww);
1344: /* Solve correction equation to expand basis */
1345: BVGetColumn(pjd->V,nv,&t[0]);
1346: rr[0] = r[0];
1347: if (sz==2) {
1348: BVGetColumn(pjd->V,nv+1,&t[1]);
1349: rr[1] = r[1];
1350: } else {
1351: t[1] = NULL;
1352: rr[1] = NULL;
1353: }
1354: VecCreateCompWithVecs(t,kspsf,pjd->vtempl,&tc);
1355: VecCreateCompWithVecs(rr,kspsf,pjd->vtempl,&rc);
1356: VecCompSetSubVecs(pjd->vtempl,sz,NULL);
1357: tol = PetscMax(rtol,tol/2);
1358: KSPSetTolerances(ksp,tol,abstol,dtol,maxits);
1359: KSPSolve(ksp,rc,tc);
1360: VecDestroy(&tc);
1361: VecDestroy(&rc);
1362: VecGetArray(t[0],&array);
1363: PetscMPIIntCast(pep->nconv,&count);
1364: MPI_Bcast(array+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep));
1365: VecRestoreArray(t[0],&array);
1366: BVRestoreColumn(pjd->V,nv,&t[0]);
1367: BVOrthogonalizeColumn(pjd->V,nv,NULL,&norm,&lindep);
1368: if (lindep || norm==0.0) {
1370: off = 1;
1371: } else {
1372: off = 0;
1373: BVScaleColumn(pjd->V,nv,1.0/norm);
1374: }
1375: #if !defined(PETSC_USE_COMPLEX)
1376: if (sz==2) {
1377: VecGetArray(t[1],&array);
1378: MPI_Bcast(array+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep));
1379: VecRestoreArray(t[1],&array);
1380: BVRestoreColumn(pjd->V,nv+1,&t[1]);
1381: if (off) BVCopyColumn(pjd->V,nv+1,nv);
1382: BVOrthogonalizeColumn(pjd->V,nv+1-off,NULL,&norm,&lindep);
1383: if (lindep || norm==0.0) {
1385: off = 1;
1386: } else BVScaleColumn(pjd->V,nv+1-off,1.0/norm);
1387: }
1388: #endif
1389: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
1390: BVInsertVec(pjd->W,nv,r[0]);
1391: if (sz==2 && !off) BVInsertVec(pjd->W,nv+1,r[1]);
1392: BVOrthogonalizeColumn(pjd->W,nv,NULL,&norm,&lindep);
1394: BVScaleColumn(pjd->W,nv,1.0/norm);
1395: if (sz==2 && !off) {
1396: BVOrthogonalizeColumn(pjd->W,nv+1,NULL,&norm,&lindep);
1398: BVScaleColumn(pjd->W,nv+1,1.0/norm);
1399: }
1400: }
1401: bupdated = idx?0:nv;
1402: nv += sz-off;
1403: }
1404: for (k=0;k<nvc;k++) {
1405: eig[pep->nconv-idx+k] = pep->eigr[k];
1406: #if !defined(PETSC_USE_COMPLEX)
1407: eigi[pep->nconv-idx+k] = pep->eigi[k];
1408: #endif
1409: }
1410: PEPMonitor(pep,pep->its,pep->nconv,eig,eigi,pep->errest,pep->nconv+1);
1411: }
1412: }
1413: if (pjd->ld>1) {
1414: for (k=0;k<pep->nconv;k++) {
1415: pep->eigr[k] = eig[k];
1416: pep->eigi[k] = eigi[k];
1417: }
1418: if (pep->nconv>0) PEPJDEigenvectors(pep);
1419: PetscFree2(pcctx->M,pcctx->ps);
1420: }
1421: VecDestroy(&u[0]);
1422: VecDestroy(&r[0]);
1423: VecDestroy(&p[0]);
1424: #if !defined (PETSC_USE_COMPLEX)
1425: VecDestroy(&u[1]);
1426: VecDestroy(&r[1]);
1427: VecDestroy(&p[1]);
1428: #endif
1429: KSPSetTolerances(ksp,rtol,abstol,dtol,maxits);
1430: KSPSetPC(ksp,pcctx->pc);
1431: VecDestroy(&pcctx->Bp[0]);
1432: VecDestroy(&pcctx->Bp[1]);
1433: MatShellGetContext(pjd->Pshell,&matctx);
1434: MatDestroy(&matctx->Pr);
1435: MatDestroy(&matctx->Pi);
1436: MatDestroy(&pjd->Pshell);
1437: MatDestroy(&pcctx->PPr);
1438: PCDestroy(&pcctx->pc);
1439: PetscFree(pcctx);
1440: PetscFree(matctx);
1441: PCDestroy(&pjd->pcshell);
1442: PetscFree3(eig,eigi,res);
1443: VecDestroy(&pjd->vtempl);
1444: PetscFunctionReturn(0);
1445: }
1447: PetscErrorCode PEPJDSetRestart_JD(PEP pep,PetscReal keep)
1448: {
1449: PEP_JD *pjd = (PEP_JD*)pep->data;
1451: if (keep==PETSC_DEFAULT) pjd->keep = 0.5;
1452: else {
1454: pjd->keep = keep;
1455: }
1456: PetscFunctionReturn(0);
1457: }
1459: /*@
1460: PEPJDSetRestart - Sets the restart parameter for the Jacobi-Davidson
1461: method, in particular the proportion of basis vectors that must be kept
1462: after restart.
1464: Logically Collective on pep
1466: Input Parameters:
1467: + pep - the eigenproblem solver context
1468: - keep - the number of vectors to be kept at restart
1470: Options Database Key:
1471: . -pep_jd_restart - Sets the restart parameter
1473: Notes:
1474: Allowed values are in the range [0.1,0.9]. The default is 0.5.
1476: Level: advanced
1478: .seealso: PEPJDGetRestart()
1479: @*/
1480: PetscErrorCode PEPJDSetRestart(PEP pep,PetscReal keep)
1481: {
1484: PetscTryMethod(pep,"PEPJDSetRestart_C",(PEP,PetscReal),(pep,keep));
1485: PetscFunctionReturn(0);
1486: }
1488: PetscErrorCode PEPJDGetRestart_JD(PEP pep,PetscReal *keep)
1489: {
1490: PEP_JD *pjd = (PEP_JD*)pep->data;
1492: *keep = pjd->keep;
1493: PetscFunctionReturn(0);
1494: }
1496: /*@
1497: PEPJDGetRestart - Gets the restart parameter used in the Jacobi-Davidson method.
1499: Not Collective
1501: Input Parameter:
1502: . pep - the eigenproblem solver context
1504: Output Parameter:
1505: . keep - the restart parameter
1507: Level: advanced
1509: .seealso: PEPJDSetRestart()
1510: @*/
1511: PetscErrorCode PEPJDGetRestart(PEP pep,PetscReal *keep)
1512: {
1515: PetscUseMethod(pep,"PEPJDGetRestart_C",(PEP,PetscReal*),(pep,keep));
1516: PetscFunctionReturn(0);
1517: }
1519: PetscErrorCode PEPJDSetFix_JD(PEP pep,PetscReal fix)
1520: {
1521: PEP_JD *pjd = (PEP_JD*)pep->data;
1523: if (fix == PETSC_DEFAULT || fix == PETSC_DECIDE) pjd->fix = 0.01;
1524: else {
1526: pjd->fix = fix;
1527: }
1528: PetscFunctionReturn(0);
1529: }
1531: /*@
1532: PEPJDSetFix - Sets the threshold for changing the target in the correction
1533: equation.
1535: Logically Collective on pep
1537: Input Parameters:
1538: + pep - the eigenproblem solver context
1539: - fix - threshold for changing the target
1541: Options Database Key:
1542: . -pep_jd_fix - the fix value
1544: Note:
1545: The target in the correction equation is fixed at the first iterations.
1546: When the norm of the residual vector is lower than the fix value,
1547: the target is set to the corresponding eigenvalue.
1549: Level: advanced
1551: .seealso: PEPJDGetFix()
1552: @*/
1553: PetscErrorCode PEPJDSetFix(PEP pep,PetscReal fix)
1554: {
1557: PetscTryMethod(pep,"PEPJDSetFix_C",(PEP,PetscReal),(pep,fix));
1558: PetscFunctionReturn(0);
1559: }
1561: PetscErrorCode PEPJDGetFix_JD(PEP pep,PetscReal *fix)
1562: {
1563: PEP_JD *pjd = (PEP_JD*)pep->data;
1565: *fix = pjd->fix;
1566: PetscFunctionReturn(0);
1567: }
1569: /*@
1570: PEPJDGetFix - Returns the threshold for changing the target in the correction
1571: equation.
1573: Not Collective
1575: Input Parameter:
1576: . pep - the eigenproblem solver context
1578: Output Parameter:
1579: . fix - threshold for changing the target
1581: Note:
1582: The target in the correction equation is fixed at the first iterations.
1583: When the norm of the residual vector is lower than the fix value,
1584: the target is set to the corresponding eigenvalue.
1586: Level: advanced
1588: .seealso: PEPJDSetFix()
1589: @*/
1590: PetscErrorCode PEPJDGetFix(PEP pep,PetscReal *fix)
1591: {
1594: PetscUseMethod(pep,"PEPJDGetFix_C",(PEP,PetscReal*),(pep,fix));
1595: PetscFunctionReturn(0);
1596: }
1598: PetscErrorCode PEPJDSetReusePreconditioner_JD(PEP pep,PetscBool reusepc)
1599: {
1600: PEP_JD *pjd = (PEP_JD*)pep->data;
1602: pjd->reusepc = reusepc;
1603: PetscFunctionReturn(0);
1604: }
1606: /*@
1607: PEPJDSetReusePreconditioner - Sets a flag indicating whether the preconditioner
1608: must be reused or not.
1610: Logically Collective on pep
1612: Input Parameters:
1613: + pep - the eigenproblem solver context
1614: - reusepc - the reuse flag
1616: Options Database Key:
1617: . -pep_jd_reuse_preconditioner - the reuse flag
1619: Note:
1620: The default value is False. If set to True, the preconditioner is built
1621: only at the beginning, using the target value. Otherwise, it may be rebuilt
1622: (depending on the fix parameter) at each iteration from the Ritz value.
1624: Level: advanced
1626: .seealso: PEPJDGetReusePreconditioner(), PEPJDSetFix()
1627: @*/
1628: PetscErrorCode PEPJDSetReusePreconditioner(PEP pep,PetscBool reusepc)
1629: {
1632: PetscTryMethod(pep,"PEPJDSetReusePreconditioner_C",(PEP,PetscBool),(pep,reusepc));
1633: PetscFunctionReturn(0);
1634: }
1636: PetscErrorCode PEPJDGetReusePreconditioner_JD(PEP pep,PetscBool *reusepc)
1637: {
1638: PEP_JD *pjd = (PEP_JD*)pep->data;
1640: *reusepc = pjd->reusepc;
1641: PetscFunctionReturn(0);
1642: }
1644: /*@
1645: PEPJDGetReusePreconditioner - Returns the flag for reusing the preconditioner.
1647: Not Collective
1649: Input Parameter:
1650: . pep - the eigenproblem solver context
1652: Output Parameter:
1653: . reusepc - the reuse flag
1655: Level: advanced
1657: .seealso: PEPJDSetReusePreconditioner()
1658: @*/
1659: PetscErrorCode PEPJDGetReusePreconditioner(PEP pep,PetscBool *reusepc)
1660: {
1663: PetscUseMethod(pep,"PEPJDGetReusePreconditioner_C",(PEP,PetscBool*),(pep,reusepc));
1664: PetscFunctionReturn(0);
1665: }
1667: PetscErrorCode PEPJDSetMinimalityIndex_JD(PEP pep,PetscInt mmidx)
1668: {
1669: PEP_JD *pjd = (PEP_JD*)pep->data;
1671: if (mmidx == PETSC_DEFAULT || mmidx == PETSC_DECIDE) {
1672: if (pjd->mmidx != 1) pep->state = PEP_STATE_INITIAL;
1673: pjd->mmidx = 1;
1674: } else {
1676: if (pjd->mmidx != mmidx) pep->state = PEP_STATE_INITIAL;
1677: pjd->mmidx = mmidx;
1678: }
1679: PetscFunctionReturn(0);
1680: }
1682: /*@
1683: PEPJDSetMinimalityIndex - Sets the maximum allowed value for the minimality index.
1685: Logically Collective on pep
1687: Input Parameters:
1688: + pep - the eigenproblem solver context
1689: - mmidx - maximum minimality index
1691: Options Database Key:
1692: . -pep_jd_minimality_index - the minimality index value
1694: Note:
1695: The default value is equal to the degree of the polynomial. A smaller value
1696: can be used if the wanted eigenvectors are known to be linearly independent.
1698: Level: advanced
1700: .seealso: PEPJDGetMinimalityIndex()
1701: @*/
1702: PetscErrorCode PEPJDSetMinimalityIndex(PEP pep,PetscInt mmidx)
1703: {
1706: PetscTryMethod(pep,"PEPJDSetMinimalityIndex_C",(PEP,PetscInt),(pep,mmidx));
1707: PetscFunctionReturn(0);
1708: }
1710: PetscErrorCode PEPJDGetMinimalityIndex_JD(PEP pep,PetscInt *mmidx)
1711: {
1712: PEP_JD *pjd = (PEP_JD*)pep->data;
1714: *mmidx = pjd->mmidx;
1715: PetscFunctionReturn(0);
1716: }
1718: /*@
1719: PEPJDGetMinimalityIndex - Returns the maximum allowed value of the minimality
1720: index.
1722: Not Collective
1724: Input Parameter:
1725: . pep - the eigenproblem solver context
1727: Output Parameter:
1728: . mmidx - minimality index
1730: Level: advanced
1732: .seealso: PEPJDSetMinimalityIndex()
1733: @*/
1734: PetscErrorCode PEPJDGetMinimalityIndex(PEP pep,PetscInt *mmidx)
1735: {
1738: PetscUseMethod(pep,"PEPJDGetMinimalityIndex_C",(PEP,PetscInt*),(pep,mmidx));
1739: PetscFunctionReturn(0);
1740: }
1742: PetscErrorCode PEPJDSetProjection_JD(PEP pep,PEPJDProjection proj)
1743: {
1744: PEP_JD *pjd = (PEP_JD*)pep->data;
1746: switch (proj) {
1747: case PEP_JD_PROJECTION_HARMONIC:
1748: case PEP_JD_PROJECTION_ORTHOGONAL:
1749: if (pjd->proj != proj) {
1750: pep->state = PEP_STATE_INITIAL;
1751: pjd->proj = proj;
1752: }
1753: break;
1754: default:
1755: SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'proj' value");
1756: }
1757: PetscFunctionReturn(0);
1758: }
1760: /*@
1761: PEPJDSetProjection - Sets the type of projection to be used in the Jacobi-Davidson solver.
1763: Logically Collective on pep
1765: Input Parameters:
1766: + pep - the eigenproblem solver context
1767: - proj - the type of projection
1769: Options Database Key:
1770: . -pep_jd_projection - the projection type, either orthogonal or harmonic
1772: Level: advanced
1774: .seealso: PEPJDGetProjection()
1775: @*/
1776: PetscErrorCode PEPJDSetProjection(PEP pep,PEPJDProjection proj)
1777: {
1780: PetscTryMethod(pep,"PEPJDSetProjection_C",(PEP,PEPJDProjection),(pep,proj));
1781: PetscFunctionReturn(0);
1782: }
1784: PetscErrorCode PEPJDGetProjection_JD(PEP pep,PEPJDProjection *proj)
1785: {
1786: PEP_JD *pjd = (PEP_JD*)pep->data;
1788: *proj = pjd->proj;
1789: PetscFunctionReturn(0);
1790: }
1792: /*@
1793: PEPJDGetProjection - Returns the type of projection used by the Jacobi-Davidson solver.
1795: Not Collective
1797: Input Parameter:
1798: . pep - the eigenproblem solver context
1800: Output Parameter:
1801: . proj - the type of projection
1803: Level: advanced
1805: .seealso: PEPJDSetProjection()
1806: @*/
1807: PetscErrorCode PEPJDGetProjection(PEP pep,PEPJDProjection *proj)
1808: {
1811: PetscUseMethod(pep,"PEPJDGetProjection_C",(PEP,PEPJDProjection*),(pep,proj));
1812: PetscFunctionReturn(0);
1813: }
1815: PetscErrorCode PEPSetFromOptions_JD(PetscOptionItems *PetscOptionsObject,PEP pep)
1816: {
1817: PetscBool flg,b1;
1818: PetscReal r1;
1819: PetscInt i1;
1820: PEPJDProjection proj;
1822: PetscOptionsHead(PetscOptionsObject,"PEP JD Options");
1824: PetscOptionsReal("-pep_jd_restart","Proportion of vectors kept after restart","PEPJDSetRestart",0.5,&r1,&flg);
1825: if (flg) PEPJDSetRestart(pep,r1);
1827: PetscOptionsReal("-pep_jd_fix","Tolerance for changing the target in the correction equation","PEPJDSetFix",0.01,&r1,&flg);
1828: if (flg) PEPJDSetFix(pep,r1);
1830: PetscOptionsBool("-pep_jd_reuse_preconditioner","Whether to reuse the preconditioner","PEPJDSetReusePreconditoiner",PETSC_FALSE,&b1,&flg);
1831: if (flg) PEPJDSetReusePreconditioner(pep,b1);
1833: PetscOptionsInt("-pep_jd_minimality_index","Maximum allowed minimality index","PEPJDSetMinimalityIndex",1,&i1,&flg);
1834: if (flg) PEPJDSetMinimalityIndex(pep,i1);
1836: PetscOptionsEnum("-pep_jd_projection","Type of projection","PEPJDSetProjection",PEPJDProjectionTypes,(PetscEnum)PEP_JD_PROJECTION_HARMONIC,(PetscEnum*)&proj,&flg);
1837: if (flg) PEPJDSetProjection(pep,proj);
1839: PetscOptionsTail();
1840: PetscFunctionReturn(0);
1841: }
1843: PetscErrorCode PEPView_JD(PEP pep,PetscViewer viewer)
1844: {
1845: PEP_JD *pjd = (PEP_JD*)pep->data;
1846: PetscBool isascii;
1848: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
1849: if (isascii) {
1850: PetscViewerASCIIPrintf(viewer," %d%% of basis vectors kept after restart\n",(int)(100*pjd->keep));
1851: PetscViewerASCIIPrintf(viewer," threshold for changing the target in the correction equation (fix): %g\n",(double)pjd->fix);
1852: PetscViewerASCIIPrintf(viewer," projection type: %s\n",PEPJDProjectionTypes[pjd->proj]);
1853: PetscViewerASCIIPrintf(viewer," maximum allowed minimality index: %" PetscInt_FMT "\n",pjd->mmidx);
1854: if (pjd->reusepc) PetscViewerASCIIPrintf(viewer," reusing the preconditioner\n");
1855: }
1856: PetscFunctionReturn(0);
1857: }
1859: PetscErrorCode PEPSetDefaultST_JD(PEP pep)
1860: {
1861: KSP ksp;
1863: if (!((PetscObject)pep->st)->type_name) {
1864: STSetType(pep->st,STPRECOND);
1865: STPrecondSetKSPHasMat(pep->st,PETSC_TRUE);
1866: }
1867: STSetTransform(pep->st,PETSC_FALSE);
1868: STGetKSP(pep->st,&ksp);
1869: if (!((PetscObject)ksp)->type_name) {
1870: KSPSetType(ksp,KSPBCGSL);
1871: KSPSetTolerances(ksp,1e-5,PETSC_DEFAULT,PETSC_DEFAULT,100);
1872: }
1873: PetscFunctionReturn(0);
1874: }
1876: PetscErrorCode PEPReset_JD(PEP pep)
1877: {
1878: PEP_JD *pjd = (PEP_JD*)pep->data;
1879: PetscInt i;
1881: for (i=0;i<pep->nmat;i++) BVDestroy(pjd->TV+i);
1882: if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) BVDestroy(&pjd->W);
1883: if (pjd->ld>1) {
1884: BVDestroy(&pjd->V);
1885: for (i=0;i<pep->nmat;i++) BVDestroy(pjd->AX+i);
1886: BVDestroy(&pjd->N[0]);
1887: BVDestroy(&pjd->N[1]);
1888: PetscFree3(pjd->XpX,pjd->T,pjd->Tj);
1889: }
1890: PetscFree2(pjd->TV,pjd->AX);
1891: PetscFunctionReturn(0);
1892: }
1894: PetscErrorCode PEPDestroy_JD(PEP pep)
1895: {
1896: PetscFree(pep->data);
1897: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetRestart_C",NULL);
1898: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetRestart_C",NULL);
1899: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetFix_C",NULL);
1900: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetFix_C",NULL);
1901: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetReusePreconditioner_C",NULL);
1902: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetReusePreconditioner_C",NULL);
1903: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetMinimalityIndex_C",NULL);
1904: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetMinimalityIndex_C",NULL);
1905: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetProjection_C",NULL);
1906: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetProjection_C",NULL);
1907: PetscFunctionReturn(0);
1908: }
1910: SLEPC_EXTERN PetscErrorCode PEPCreate_JD(PEP pep)
1911: {
1912: PEP_JD *pjd;
1914: PetscNewLog(pep,&pjd);
1915: pep->data = (void*)pjd;
1917: pep->lineariz = PETSC_FALSE;
1918: pjd->fix = 0.01;
1919: pjd->mmidx = 0;
1921: pep->ops->solve = PEPSolve_JD;
1922: pep->ops->setup = PEPSetUp_JD;
1923: pep->ops->setfromoptions = PEPSetFromOptions_JD;
1924: pep->ops->destroy = PEPDestroy_JD;
1925: pep->ops->reset = PEPReset_JD;
1926: pep->ops->view = PEPView_JD;
1927: pep->ops->setdefaultst = PEPSetDefaultST_JD;
1929: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetRestart_C",PEPJDSetRestart_JD);
1930: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetRestart_C",PEPJDGetRestart_JD);
1931: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetFix_C",PEPJDSetFix_JD);
1932: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetFix_C",PEPJDGetFix_JD);
1933: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetReusePreconditioner_C",PEPJDSetReusePreconditioner_JD);
1934: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetReusePreconditioner_C",PEPJDGetReusePreconditioner_JD);
1935: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetMinimalityIndex_C",PEPJDSetMinimalityIndex_JD);
1936: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetMinimalityIndex_C",PEPJDGetMinimalityIndex_JD);
1937: PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetProjection_C",PEPJDSetProjection_JD);
1938: PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetProjection_C",PEPJDGetProjection_JD);
1939: PetscFunctionReturn(0);
1940: }