Actual source code: krylovschur.c
slepc-3.16.2 2022-02-01
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2021, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: SLEPc eigensolver: "krylovschur"
13: Method: Krylov-Schur
15: Algorithm:
17: Single-vector Krylov-Schur method for non-symmetric problems,
18: including harmonic extraction.
20: References:
22: [1] "Krylov-Schur Methods in SLEPc", SLEPc Technical Report STR-7,
23: available at https://slepc.upv.es.
25: [2] G.W. Stewart, "A Krylov-Schur Algorithm for Large Eigenproblems",
26: SIAM J. Matrix Anal. App. 23(3):601-614, 2001.
28: [3] "Practical Implementation of Harmonic Krylov-Schur", SLEPc Technical
29: Report STR-9, available at https://slepc.upv.es.
30: */
32: #include <slepc/private/epsimpl.h>
33: #include "krylovschur.h"
35: PetscErrorCode EPSGetArbitraryValues(EPS eps,PetscScalar *rr,PetscScalar *ri)
36: {
38: PetscInt i,newi,ld,n,l;
39: Vec xr=eps->work[0],xi=eps->work[1];
40: PetscScalar re,im,*Zr,*Zi,*X;
43: DSGetLeadingDimension(eps->ds,&ld);
44: DSGetDimensions(eps->ds,&n,&l,NULL,NULL);
45: for (i=l;i<n;i++) {
46: re = eps->eigr[i];
47: im = eps->eigi[i];
48: STBackTransform(eps->st,1,&re,&im);
49: newi = i;
50: DSVectors(eps->ds,DS_MAT_X,&newi,NULL);
51: DSGetArray(eps->ds,DS_MAT_X,&X);
52: Zr = X+i*ld;
53: if (newi==i+1) Zi = X+newi*ld;
54: else Zi = NULL;
55: EPSComputeRitzVector(eps,Zr,Zi,eps->V,xr,xi);
56: DSRestoreArray(eps->ds,DS_MAT_X,&X);
57: (*eps->arbitrary)(re,im,xr,xi,rr+i,ri+i,eps->arbitraryctx);
58: }
59: return(0);
60: }
62: static PetscErrorCode EstimateRange(Mat A,PetscReal *left,PetscReal *right)
63: {
65: PetscInt nconv;
66: PetscScalar eig0;
67: PetscReal tol=1e-3,errest=tol;
68: EPS eps;
71: *left = 0.0; *right = 0.0;
72: EPSCreate(PetscObjectComm((PetscObject)A),&eps);
73: EPSSetOptionsPrefix(eps,"eps_filter_");
74: EPSSetOperators(eps,A,NULL);
75: EPSSetProblemType(eps,EPS_HEP);
76: EPSSetTolerances(eps,tol,50);
77: EPSSetConvergenceTest(eps,EPS_CONV_ABS);
78: EPSSetWhichEigenpairs(eps,EPS_SMALLEST_REAL);
79: EPSSolve(eps);
80: EPSGetConverged(eps,&nconv);
81: if (nconv>0) {
82: EPSGetEigenvalue(eps,0,&eig0,NULL);
83: EPSGetErrorEstimate(eps,0,&errest);
84: } else eig0 = eps->eigr[0];
85: *left = PetscRealPart(eig0)-errest;
86: EPSSetWhichEigenpairs(eps,EPS_LARGEST_REAL);
87: EPSSolve(eps);
88: EPSGetConverged(eps,&nconv);
89: if (nconv>0) {
90: EPSGetEigenvalue(eps,0,&eig0,NULL);
91: EPSGetErrorEstimate(eps,0,&errest);
92: } else eig0 = eps->eigr[0];
93: *right = PetscRealPart(eig0)+errest;
94: EPSDestroy(&eps);
95: return(0);
96: }
98: static PetscErrorCode EPSSetUp_KrylovSchur_Filter(EPS eps)
99: {
100: PetscErrorCode ierr;
101: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
102: PetscBool estimaterange=PETSC_TRUE;
103: PetscReal rleft,rright;
104: Mat A;
107: EPSCheckHermitianCondition(eps,PETSC_TRUE," with polynomial filter");
108: EPSCheckStandardCondition(eps,PETSC_TRUE," with polynomial filter");
109: if (eps->intb >= PETSC_MAX_REAL && eps->inta <= PETSC_MIN_REAL) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"The defined computational interval should have at least one of their sides bounded");
110: EPSCheckUnsupportedCondition(eps,EPS_FEATURE_ARBITRARY | EPS_FEATURE_REGION | EPS_FEATURE_EXTRACTION,PETSC_TRUE," with polynomial filter");
111: if (eps->tol==PETSC_DEFAULT) eps->tol = SLEPC_DEFAULT_TOL*1e-2; /* use tighter tolerance */
112: STFilterSetInterval(eps->st,eps->inta,eps->intb);
113: if (!ctx->estimatedrange) {
114: STFilterGetRange(eps->st,&rleft,&rright);
115: estimaterange = (!rleft && !rright)? PETSC_TRUE: PETSC_FALSE;
116: }
117: if (estimaterange) { /* user did not set a range */
118: STGetMatrix(eps->st,0,&A);
119: EstimateRange(A,&rleft,&rright);
120: PetscInfo2(eps,"Setting eigenvalue range to [%g,%g]\n",(double)rleft,(double)rright);
121: STFilterSetRange(eps->st,rleft,rright);
122: ctx->estimatedrange = PETSC_TRUE;
123: }
124: if (eps->ncv==PETSC_DEFAULT && eps->nev==1) eps->nev = 40; /* user did not provide nev estimation */
125: EPSSetDimensions_Default(eps,eps->nev,&eps->ncv,&eps->mpd);
126: if (eps->ncv>eps->nev+eps->mpd) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_USER_INPUT,"The value of ncv must not be larger than nev+mpd");
127: if (eps->max_it==PETSC_DEFAULT) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
128: return(0);
129: }
131: PetscErrorCode EPSSetUp_KrylovSchur(EPS eps)
132: {
133: PetscErrorCode ierr;
134: PetscReal eta;
135: PetscBool isfilt=PETSC_FALSE;
136: BVOrthogType otype;
137: BVOrthogBlockType obtype;
138: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
139: enum { EPS_KS_DEFAULT,EPS_KS_SYMM,EPS_KS_SLICE,EPS_KS_FILTER,EPS_KS_INDEF,EPS_KS_TWOSIDED } variant;
142: if (eps->which==EPS_ALL) { /* default values in case of spectrum slicing or polynomial filter */
143: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
144: if (isfilt) {
145: EPSSetUp_KrylovSchur_Filter(eps);
146: } else {
147: EPSSetUp_KrylovSchur_Slice(eps);
148: }
149: } else {
150: EPSSetDimensions_Default(eps,eps->nev,&eps->ncv,&eps->mpd);
151: if (eps->ncv>eps->nev+eps->mpd) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_USER_INPUT,"The value of ncv must not be larger than nev+mpd");
152: if (eps->max_it==PETSC_DEFAULT) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
153: if (!eps->which) { EPSSetWhichEigenpairs_Default(eps); }
154: }
155: if (!ctx->lock && eps->mpd<eps->ncv) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Should not use mpd parameter in non-locking variant");
157: EPSCheckDefiniteCondition(eps,eps->arbitrary," with arbitrary selection of eigenpairs");
159: if (eps->extraction!=EPS_RITZ && eps->extraction!=EPS_HARMONIC) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
161: if (!ctx->keep) ctx->keep = 0.5;
163: EPSAllocateSolution(eps,1);
164: EPS_SetInnerProduct(eps);
165: if (eps->arbitrary) {
166: EPSSetWorkVecs(eps,2);
167: } else if (eps->ishermitian && !eps->ispositive) {
168: EPSSetWorkVecs(eps,1);
169: }
171: /* dispatch solve method */
172: if (eps->ishermitian) {
173: if (eps->which==EPS_ALL) {
174: if (eps->isgeneralized && !eps->ispositive) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Spectrum slicing not implemented for indefinite problems");
175: else variant = isfilt? EPS_KS_FILTER: EPS_KS_SLICE;
176: } else if (eps->isgeneralized && !eps->ispositive) {
177: variant = EPS_KS_INDEF;
178: } else {
179: switch (eps->extraction) {
180: case EPS_RITZ: variant = EPS_KS_SYMM; break;
181: case EPS_HARMONIC: variant = EPS_KS_DEFAULT; break;
182: default: SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
183: }
184: }
185: } else if (eps->twosided) {
186: variant = EPS_KS_TWOSIDED;
187: } else {
188: switch (eps->extraction) {
189: case EPS_RITZ: variant = EPS_KS_DEFAULT; break;
190: case EPS_HARMONIC: variant = EPS_KS_DEFAULT; break;
191: default: SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
192: }
193: }
194: switch (variant) {
195: case EPS_KS_DEFAULT:
196: eps->ops->solve = EPSSolve_KrylovSchur_Default;
197: eps->ops->computevectors = EPSComputeVectors_Schur;
198: DSSetType(eps->ds,DSNHEP);
199: DSSetExtraRow(eps->ds,PETSC_TRUE);
200: DSAllocate(eps->ds,eps->ncv+1);
201: break;
202: case EPS_KS_SYMM:
203: case EPS_KS_FILTER:
204: eps->ops->solve = EPSSolve_KrylovSchur_Default;
205: eps->ops->computevectors = EPSComputeVectors_Hermitian;
206: DSSetType(eps->ds,DSHEP);
207: DSSetCompact(eps->ds,PETSC_TRUE);
208: DSSetExtraRow(eps->ds,PETSC_TRUE);
209: DSAllocate(eps->ds,eps->ncv+1);
210: break;
211: case EPS_KS_SLICE:
212: eps->ops->solve = EPSSolve_KrylovSchur_Slice;
213: eps->ops->computevectors = EPSComputeVectors_Slice;
214: break;
215: case EPS_KS_INDEF:
216: eps->ops->solve = EPSSolve_KrylovSchur_Indefinite;
217: eps->ops->computevectors = EPSComputeVectors_Indefinite;
218: DSSetType(eps->ds,DSGHIEP);
219: DSSetCompact(eps->ds,PETSC_TRUE);
220: DSSetExtraRow(eps->ds,PETSC_TRUE);
221: DSAllocate(eps->ds,eps->ncv+1);
222: /* force reorthogonalization for pseudo-Lanczos */
223: BVGetOrthogonalization(eps->V,&otype,NULL,&eta,&obtype);
224: BVSetOrthogonalization(eps->V,otype,BV_ORTHOG_REFINE_ALWAYS,eta,obtype);
225: break;
226: case EPS_KS_TWOSIDED:
227: eps->ops->solve = EPSSolve_KrylovSchur_TwoSided;
228: eps->ops->computevectors = EPSComputeVectors_Schur;
229: DSSetType(eps->ds,DSNHEPTS);
230: DSAllocate(eps->ds,eps->ncv+1);
231: DSSetExtraRow(eps->ds,PETSC_TRUE);
232: break;
233: default: SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_PLIB,"Unexpected error");
234: }
235: return(0);
236: }
238: PetscErrorCode EPSSetUpSort_KrylovSchur(EPS eps)
239: {
240: PetscErrorCode ierr;
241: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
242: SlepcSC sc;
243: PetscBool isfilt;
246: EPSSetUpSort_Default(eps);
247: if (eps->which==EPS_ALL) {
248: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
249: if (isfilt) {
250: DSGetSlepcSC(eps->ds,&sc);
251: sc->rg = NULL;
252: sc->comparison = SlepcCompareLargestReal;
253: sc->comparisonctx = NULL;
254: sc->map = NULL;
255: sc->mapobj = NULL;
256: } else {
257: if (!ctx->global && ctx->sr->numEigs>0) {
258: DSGetSlepcSC(eps->ds,&sc);
259: sc->rg = NULL;
260: sc->comparison = SlepcCompareLargestMagnitude;
261: sc->comparisonctx = NULL;
262: sc->map = NULL;
263: sc->mapobj = NULL;
264: }
265: }
266: }
267: return(0);
268: }
270: PetscErrorCode EPSSolve_KrylovSchur_Default(EPS eps)
271: {
272: PetscErrorCode ierr;
273: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
274: PetscInt j,*pj,k,l,nv,ld,nconv;
275: Mat U,Op,H;
276: PetscScalar *g;
277: PetscReal beta,gamma=1.0,*a,*b;
278: PetscBool breakdown,harmonic,hermitian;
281: DSGetLeadingDimension(eps->ds,&ld);
282: harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE;
283: hermitian = (eps->ishermitian && !harmonic)?PETSC_TRUE:PETSC_FALSE;
284: if (harmonic) { PetscMalloc1(ld,&g); }
285: if (eps->arbitrary) pj = &j;
286: else pj = NULL;
288: /* Get the starting Arnoldi vector */
289: EPSGetStartVector(eps,0,NULL);
290: l = 0;
292: /* Restart loop */
293: while (eps->reason == EPS_CONVERGED_ITERATING) {
294: eps->its++;
296: /* Compute an nv-step Arnoldi factorization */
297: nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
298: DSSetDimensions(eps->ds,nv,eps->nconv,eps->nconv+l);
299: STGetOperator(eps->st,&Op);
300: if (hermitian) {
301: DSGetArrayReal(eps->ds,DS_MAT_T,&a);
302: b = a + ld;
303: BVMatLanczos(eps->V,Op,a,b,eps->nconv+l,&nv,&breakdown);
304: beta = b[nv-1];
305: DSRestoreArrayReal(eps->ds,DS_MAT_T,&a);
306: } else {
307: DSGetMat(eps->ds,DS_MAT_A,&H);
308: BVMatArnoldi(eps->V,Op,H,eps->nconv+l,&nv,&beta,&breakdown);
309: DSRestoreMat(eps->ds,DS_MAT_A,&H);
310: }
311: STRestoreOperator(eps->st,&Op);
312: DSSetDimensions(eps->ds,nv,eps->nconv,eps->nconv+l);
313: if (l==0) {
314: DSSetState(eps->ds,DS_STATE_INTERMEDIATE);
315: } else {
316: DSSetState(eps->ds,DS_STATE_RAW);
317: }
318: BVSetActiveColumns(eps->V,eps->nconv,nv);
320: /* Compute translation of Krylov decomposition if harmonic extraction used */
321: if (harmonic) {
322: DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,g,&gamma);
323: }
325: /* Solve projected problem */
326: DSSolve(eps->ds,eps->eigr,eps->eigi);
327: if (eps->arbitrary) {
328: EPSGetArbitraryValues(eps,eps->rr,eps->ri);
329: j=1;
330: }
331: DSSort(eps->ds,eps->eigr,eps->eigi,eps->rr,eps->ri,pj);
332: DSUpdateExtraRow(eps->ds);
333: DSSynchronize(eps->ds,eps->eigr,eps->eigi);
335: /* Check convergence */
336: EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,0.0,gamma,&k);
337: (*eps->stopping)(eps,eps->its,eps->max_it,k,eps->nev,&eps->reason,eps->stoppingctx);
338: nconv = k;
340: /* Update l */
341: if (eps->reason != EPS_CONVERGED_ITERATING || breakdown || k==nv) l = 0;
342: else {
343: l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep));
344: if (!hermitian) { DSGetTruncateSize(eps->ds,k,nv,&l); }
345: }
346: if (!ctx->lock && l>0) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */
347: if (l) { PetscInfo1(eps,"Preparing to restart keeping l=%D vectors\n",l); }
349: if (eps->reason == EPS_CONVERGED_ITERATING) {
350: if (breakdown || k==nv) {
351: /* Start a new Arnoldi factorization */
352: PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%g)\n",eps->its,(double)beta);
353: if (k<eps->nev) {
354: EPSGetStartVector(eps,k,&breakdown);
355: if (breakdown) {
356: eps->reason = EPS_DIVERGED_BREAKDOWN;
357: PetscInfo(eps,"Unable to generate more start vectors\n");
358: }
359: }
360: } else {
361: /* Undo translation of Krylov decomposition */
362: if (harmonic) {
363: DSSetDimensions(eps->ds,nv,k,l);
364: DSTranslateHarmonic(eps->ds,0.0,beta,PETSC_TRUE,g,&gamma);
365: /* gamma u^ = u - U*g~ */
366: BVSetActiveColumns(eps->V,0,nv);
367: BVMultColumn(eps->V,-1.0,1.0,nv,g);
368: BVScaleColumn(eps->V,nv,1.0/gamma);
369: BVSetActiveColumns(eps->V,eps->nconv,nv);
370: DSSetDimensions(eps->ds,nv,k,nv);
371: }
372: /* Prepare the Rayleigh quotient for restart */
373: DSTruncate(eps->ds,k+l,PETSC_FALSE);
374: }
375: }
376: /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
377: DSGetMat(eps->ds,DS_MAT_Q,&U);
378: BVMultInPlace(eps->V,U,eps->nconv,k+l);
379: MatDestroy(&U);
381: if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
382: BVCopyColumn(eps->V,nv,k+l);
383: }
384: eps->nconv = k;
385: EPSMonitor(eps,eps->its,nconv,eps->eigr,eps->eigi,eps->errest,nv);
386: }
388: if (harmonic) { PetscFree(g); }
389: DSTruncate(eps->ds,eps->nconv,PETSC_TRUE);
390: return(0);
391: }
393: static PetscErrorCode EPSKrylovSchurSetRestart_KrylovSchur(EPS eps,PetscReal keep)
394: {
395: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
398: if (keep==PETSC_DEFAULT) ctx->keep = 0.5;
399: else {
400: if (keep<0.1 || keep>0.9) SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The keep argument %g must be in the range [0.1,0.9]",keep);
401: ctx->keep = keep;
402: }
403: return(0);
404: }
406: /*@
407: EPSKrylovSchurSetRestart - Sets the restart parameter for the Krylov-Schur
408: method, in particular the proportion of basis vectors that must be kept
409: after restart.
411: Logically Collective on eps
413: Input Parameters:
414: + eps - the eigenproblem solver context
415: - keep - the number of vectors to be kept at restart
417: Options Database Key:
418: . -eps_krylovschur_restart - Sets the restart parameter
420: Notes:
421: Allowed values are in the range [0.1,0.9]. The default is 0.5.
423: Level: advanced
425: .seealso: EPSKrylovSchurGetRestart()
426: @*/
427: PetscErrorCode EPSKrylovSchurSetRestart(EPS eps,PetscReal keep)
428: {
434: PetscTryMethod(eps,"EPSKrylovSchurSetRestart_C",(EPS,PetscReal),(eps,keep));
435: return(0);
436: }
438: static PetscErrorCode EPSKrylovSchurGetRestart_KrylovSchur(EPS eps,PetscReal *keep)
439: {
440: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
443: *keep = ctx->keep;
444: return(0);
445: }
447: /*@
448: EPSKrylovSchurGetRestart - Gets the restart parameter used in the
449: Krylov-Schur method.
451: Not Collective
453: Input Parameter:
454: . eps - the eigenproblem solver context
456: Output Parameter:
457: . keep - the restart parameter
459: Level: advanced
461: .seealso: EPSKrylovSchurSetRestart()
462: @*/
463: PetscErrorCode EPSKrylovSchurGetRestart(EPS eps,PetscReal *keep)
464: {
470: PetscUseMethod(eps,"EPSKrylovSchurGetRestart_C",(EPS,PetscReal*),(eps,keep));
471: return(0);
472: }
474: static PetscErrorCode EPSKrylovSchurSetLocking_KrylovSchur(EPS eps,PetscBool lock)
475: {
476: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
479: ctx->lock = lock;
480: return(0);
481: }
483: /*@
484: EPSKrylovSchurSetLocking - Choose between locking and non-locking variants of
485: the Krylov-Schur method.
487: Logically Collective on eps
489: Input Parameters:
490: + eps - the eigenproblem solver context
491: - lock - true if the locking variant must be selected
493: Options Database Key:
494: . -eps_krylovschur_locking - Sets the locking flag
496: Notes:
497: The default is to lock converged eigenpairs when the method restarts.
498: This behaviour can be changed so that all directions are kept in the
499: working subspace even if already converged to working accuracy (the
500: non-locking variant).
502: Level: advanced
504: .seealso: EPSKrylovSchurGetLocking()
505: @*/
506: PetscErrorCode EPSKrylovSchurSetLocking(EPS eps,PetscBool lock)
507: {
513: PetscTryMethod(eps,"EPSKrylovSchurSetLocking_C",(EPS,PetscBool),(eps,lock));
514: return(0);
515: }
517: static PetscErrorCode EPSKrylovSchurGetLocking_KrylovSchur(EPS eps,PetscBool *lock)
518: {
519: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
522: *lock = ctx->lock;
523: return(0);
524: }
526: /*@
527: EPSKrylovSchurGetLocking - Gets the locking flag used in the Krylov-Schur
528: method.
530: Not Collective
532: Input Parameter:
533: . eps - the eigenproblem solver context
535: Output Parameter:
536: . lock - the locking flag
538: Level: advanced
540: .seealso: EPSKrylovSchurSetLocking()
541: @*/
542: PetscErrorCode EPSKrylovSchurGetLocking(EPS eps,PetscBool *lock)
543: {
549: PetscUseMethod(eps,"EPSKrylovSchurGetLocking_C",(EPS,PetscBool*),(eps,lock));
550: return(0);
551: }
553: static PetscErrorCode EPSKrylovSchurSetPartitions_KrylovSchur(EPS eps,PetscInt npart)
554: {
555: PetscErrorCode ierr;
556: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
557: PetscMPIInt size;
560: if (ctx->npart!=npart) {
561: if (ctx->commset) { PetscSubcommDestroy(&ctx->subc); }
562: EPSDestroy(&ctx->eps);
563: }
564: if (npart == PETSC_DEFAULT || npart == PETSC_DECIDE) {
565: ctx->npart = 1;
566: } else {
567: MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size);
568: if (npart<1 || npart>size) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of npart");
569: ctx->npart = npart;
570: }
571: eps->state = EPS_STATE_INITIAL;
572: return(0);
573: }
575: /*@
576: EPSKrylovSchurSetPartitions - Sets the number of partitions for the
577: case of doing spectrum slicing for a computational interval with the
578: communicator split in several sub-communicators.
580: Logically Collective on eps
582: Input Parameters:
583: + eps - the eigenproblem solver context
584: - npart - number of partitions
586: Options Database Key:
587: . -eps_krylovschur_partitions <npart> - Sets the number of partitions
589: Notes:
590: By default, npart=1 so all processes in the communicator participate in
591: the processing of the whole interval. If npart>1 then the interval is
592: divided into npart subintervals, each of them being processed by a
593: subset of processes.
595: The interval is split proportionally unless the separation points are
596: specified with EPSKrylovSchurSetSubintervals().
598: Level: advanced
600: .seealso: EPSKrylovSchurSetSubintervals(), EPSSetInterval()
601: @*/
602: PetscErrorCode EPSKrylovSchurSetPartitions(EPS eps,PetscInt npart)
603: {
609: PetscTryMethod(eps,"EPSKrylovSchurSetPartitions_C",(EPS,PetscInt),(eps,npart));
610: return(0);
611: }
613: static PetscErrorCode EPSKrylovSchurGetPartitions_KrylovSchur(EPS eps,PetscInt *npart)
614: {
615: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
618: *npart = ctx->npart;
619: return(0);
620: }
622: /*@
623: EPSKrylovSchurGetPartitions - Gets the number of partitions of the
624: communicator in case of spectrum slicing.
626: Not Collective
628: Input Parameter:
629: . eps - the eigenproblem solver context
631: Output Parameter:
632: . npart - number of partitions
634: Level: advanced
636: .seealso: EPSKrylovSchurSetPartitions()
637: @*/
638: PetscErrorCode EPSKrylovSchurGetPartitions(EPS eps,PetscInt *npart)
639: {
645: PetscUseMethod(eps,"EPSKrylovSchurGetPartitions_C",(EPS,PetscInt*),(eps,npart));
646: return(0);
647: }
649: static PetscErrorCode EPSKrylovSchurSetDetectZeros_KrylovSchur(EPS eps,PetscBool detect)
650: {
651: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
654: ctx->detect = detect;
655: eps->state = EPS_STATE_INITIAL;
656: return(0);
657: }
659: /*@
660: EPSKrylovSchurSetDetectZeros - Sets a flag to enforce detection of
661: zeros during the factorizations throughout the spectrum slicing computation.
663: Logically Collective on eps
665: Input Parameters:
666: + eps - the eigenproblem solver context
667: - detect - check for zeros
669: Options Database Key:
670: . -eps_krylovschur_detect_zeros - Check for zeros; this takes an optional
671: bool value (0/1/no/yes/true/false)
673: Notes:
674: A zero in the factorization indicates that a shift coincides with an eigenvalue.
676: This flag is turned off by default, and may be necessary in some cases,
677: especially when several partitions are being used. This feature currently
678: requires an external package for factorizations with support for zero
679: detection, e.g. MUMPS.
681: Level: advanced
683: .seealso: EPSKrylovSchurSetPartitions(), EPSSetInterval()
684: @*/
685: PetscErrorCode EPSKrylovSchurSetDetectZeros(EPS eps,PetscBool detect)
686: {
692: PetscTryMethod(eps,"EPSKrylovSchurSetDetectZeros_C",(EPS,PetscBool),(eps,detect));
693: return(0);
694: }
696: static PetscErrorCode EPSKrylovSchurGetDetectZeros_KrylovSchur(EPS eps,PetscBool *detect)
697: {
698: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
701: *detect = ctx->detect;
702: return(0);
703: }
705: /*@
706: EPSKrylovSchurGetDetectZeros - Gets the flag that enforces zero detection
707: in spectrum slicing.
709: Not Collective
711: Input Parameter:
712: . eps - the eigenproblem solver context
714: Output Parameter:
715: . detect - whether zeros detection is enforced during factorizations
717: Level: advanced
719: .seealso: EPSKrylovSchurSetDetectZeros()
720: @*/
721: PetscErrorCode EPSKrylovSchurGetDetectZeros(EPS eps,PetscBool *detect)
722: {
728: PetscUseMethod(eps,"EPSKrylovSchurGetDetectZeros_C",(EPS,PetscBool*),(eps,detect));
729: return(0);
730: }
732: static PetscErrorCode EPSKrylovSchurSetDimensions_KrylovSchur(EPS eps,PetscInt nev,PetscInt ncv,PetscInt mpd)
733: {
734: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
737: if (nev<1) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of nev. Must be > 0");
738: ctx->nev = nev;
739: if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
740: ctx->ncv = PETSC_DEFAULT;
741: } else {
742: if (ncv<1) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
743: ctx->ncv = ncv;
744: }
745: if (mpd == PETSC_DECIDE || mpd == PETSC_DEFAULT) {
746: ctx->mpd = PETSC_DEFAULT;
747: } else {
748: if (mpd<1) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of mpd. Must be > 0");
749: ctx->mpd = mpd;
750: }
751: eps->state = EPS_STATE_INITIAL;
752: return(0);
753: }
755: /*@
756: EPSKrylovSchurSetDimensions - Sets the dimensions used for each subsolve
757: step in case of doing spectrum slicing for a computational interval.
758: The meaning of the parameters is the same as in EPSSetDimensions().
760: Logically Collective on eps
762: Input Parameters:
763: + eps - the eigenproblem solver context
764: . nev - number of eigenvalues to compute
765: . ncv - the maximum dimension of the subspace to be used by the subsolve
766: - mpd - the maximum dimension allowed for the projected problem
768: Options Database Key:
769: + -eps_krylovschur_nev <nev> - Sets the number of eigenvalues
770: . -eps_krylovschur_ncv <ncv> - Sets the dimension of the subspace
771: - -eps_krylovschur_mpd <mpd> - Sets the maximum projected dimension
773: Level: advanced
775: .seealso: EPSKrylovSchurGetDimensions(), EPSSetDimensions(), EPSSetInterval()
776: @*/
777: PetscErrorCode EPSKrylovSchurSetDimensions(EPS eps,PetscInt nev,PetscInt ncv,PetscInt mpd)
778: {
786: PetscTryMethod(eps,"EPSKrylovSchurSetDimensions_C",(EPS,PetscInt,PetscInt,PetscInt),(eps,nev,ncv,mpd));
787: return(0);
788: }
790: static PetscErrorCode EPSKrylovSchurGetDimensions_KrylovSchur(EPS eps,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
791: {
792: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
795: if (nev) *nev = ctx->nev;
796: if (ncv) *ncv = ctx->ncv;
797: if (mpd) *mpd = ctx->mpd;
798: return(0);
799: }
801: /*@
802: EPSKrylovSchurGetDimensions - Gets the dimensions used for each subsolve
803: step in case of doing spectrum slicing for a computational interval.
805: Not Collective
807: Input Parameter:
808: . eps - the eigenproblem solver context
810: Output Parameters:
811: + nev - number of eigenvalues to compute
812: . ncv - the maximum dimension of the subspace to be used by the subsolve
813: - mpd - the maximum dimension allowed for the projected problem
815: Level: advanced
817: .seealso: EPSKrylovSchurSetDimensions()
818: @*/
819: PetscErrorCode EPSKrylovSchurGetDimensions(EPS eps,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
820: {
825: PetscUseMethod(eps,"EPSKrylovSchurGetDimensions_C",(EPS,PetscInt*,PetscInt*,PetscInt*),(eps,nev,ncv,mpd));
826: return(0);
827: }
829: static PetscErrorCode EPSKrylovSchurSetSubintervals_KrylovSchur(EPS eps,PetscReal* subint)
830: {
831: PetscErrorCode ierr;
832: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
833: PetscInt i;
836: if (subint[0]!=eps->inta || subint[ctx->npart]!=eps->intb) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"First and last values must match the endpoints of EPSSetInterval()");
837: for (i=0;i<ctx->npart;i++) if (subint[i]>subint[i+1]) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"Array must contain values in ascending order");
838: if (ctx->subintervals) { PetscFree(ctx->subintervals); }
839: PetscMalloc1(ctx->npart+1,&ctx->subintervals);
840: for (i=0;i<ctx->npart+1;i++) ctx->subintervals[i] = subint[i];
841: ctx->subintset = PETSC_TRUE;
842: eps->state = EPS_STATE_INITIAL;
843: return(0);
844: }
846: /*@C
847: EPSKrylovSchurSetSubintervals - Sets the points that delimit the
848: subintervals to be used in spectrum slicing with several partitions.
850: Logically Collective on eps
852: Input Parameters:
853: + eps - the eigenproblem solver context
854: - subint - array of real values specifying subintervals
856: Notes:
857: This function must be called after EPSKrylovSchurSetPartitions(). For npart
858: partitions, the argument subint must contain npart+1 real values sorted in
859: ascending order: subint_0, subint_1, ..., subint_npart, where the first
860: and last values must coincide with the interval endpoints set with
861: EPSSetInterval().
863: The subintervals are then defined by two consecutive points: [subint_0,subint_1],
864: [subint_1,subint_2], and so on.
866: Level: advanced
868: .seealso: EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubintervals(), EPSSetInterval()
869: @*/
870: PetscErrorCode EPSKrylovSchurSetSubintervals(EPS eps,PetscReal *subint)
871: {
876: PetscTryMethod(eps,"EPSKrylovSchurSetSubintervals_C",(EPS,PetscReal*),(eps,subint));
877: return(0);
878: }
880: static PetscErrorCode EPSKrylovSchurGetSubintervals_KrylovSchur(EPS eps,PetscReal **subint)
881: {
882: PetscErrorCode ierr;
883: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
884: PetscInt i;
887: if (!ctx->subintset) {
888: if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
889: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
890: }
891: PetscMalloc1(ctx->npart+1,subint);
892: for (i=0;i<=ctx->npart;i++) (*subint)[i] = ctx->subintervals[i];
893: return(0);
894: }
896: /*@C
897: EPSKrylovSchurGetSubintervals - Returns the points that delimit the
898: subintervals used in spectrum slicing with several partitions.
900: Logically Collective on eps
902: Input Parameter:
903: . eps - the eigenproblem solver context
905: Output Parameter:
906: . subint - array of real values specifying subintervals
908: Notes:
909: If the user passed values with EPSKrylovSchurSetSubintervals(), then the
910: same values are returned. Otherwise, the values computed internally are
911: obtained.
913: This function is only available for spectrum slicing runs.
915: The returned array has length npart+1 (see EPSKrylovSchurGetPartitions())
916: and should be freed by the user.
918: Fortran Notes:
919: The calling sequence from Fortran is
920: .vb
921: EPSKrylovSchurGetSubintervals(eps,subint,ierr)
922: double precision subint(npart+1) output
923: .ve
925: Level: advanced
927: .seealso: EPSKrylovSchurSetSubintervals(), EPSKrylovSchurGetPartitions(), EPSSetInterval()
928: @*/
929: PetscErrorCode EPSKrylovSchurGetSubintervals(EPS eps,PetscReal **subint)
930: {
936: PetscUseMethod(eps,"EPSKrylovSchurGetSubintervals_C",(EPS,PetscReal**),(eps,subint));
937: return(0);
938: }
940: static PetscErrorCode EPSKrylovSchurGetInertias_KrylovSchur(EPS eps,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
941: {
942: PetscErrorCode ierr;
943: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
944: PetscInt i,numsh;
945: EPS_SR sr = ctx->sr;
948: if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
949: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
950: switch (eps->state) {
951: case EPS_STATE_INITIAL:
952: break;
953: case EPS_STATE_SETUP:
954: numsh = ctx->npart+1;
955: if (n) *n = numsh;
956: if (shifts) {
957: PetscMalloc1(numsh,shifts);
958: (*shifts)[0] = eps->inta;
959: if (ctx->npart==1) (*shifts)[1] = eps->intb;
960: else for (i=1;i<numsh;i++) (*shifts)[i] = ctx->subintervals[i];
961: }
962: if (inertias) {
963: PetscMalloc1(numsh,inertias);
964: (*inertias)[0] = (sr->dir==1)?sr->inertia0:sr->inertia1;
965: if (ctx->npart==1) (*inertias)[1] = (sr->dir==1)?sr->inertia1:sr->inertia0;
966: else for (i=1;i<numsh;i++) (*inertias)[i] = (*inertias)[i-1]+ctx->nconv_loc[i-1];
967: }
968: break;
969: case EPS_STATE_SOLVED:
970: case EPS_STATE_EIGENVECTORS:
971: numsh = ctx->nshifts;
972: if (n) *n = numsh;
973: if (shifts) {
974: PetscMalloc1(numsh,shifts);
975: for (i=0;i<numsh;i++) (*shifts)[i] = ctx->shifts[i];
976: }
977: if (inertias) {
978: PetscMalloc1(numsh,inertias);
979: for (i=0;i<numsh;i++) (*inertias)[i] = ctx->inertias[i];
980: }
981: break;
982: }
983: return(0);
984: }
986: /*@C
987: EPSKrylovSchurGetInertias - Gets the values of the shifts and their
988: corresponding inertias in case of doing spectrum slicing for a
989: computational interval.
991: Not Collective
993: Input Parameter:
994: . eps - the eigenproblem solver context
996: Output Parameters:
997: + n - number of shifts, including the endpoints of the interval
998: . shifts - the values of the shifts used internally in the solver
999: - inertias - the values of the inertia in each shift
1001: Notes:
1002: If called after EPSSolve(), all shifts used internally by the solver are
1003: returned (including both endpoints and any intermediate ones). If called
1004: before EPSSolve() and after EPSSetUp() then only the information of the
1005: endpoints of subintervals is available.
1007: This function is only available for spectrum slicing runs.
1009: The returned arrays should be freed by the user. Can pass NULL in any of
1010: the two arrays if not required.
1012: Fortran Notes:
1013: The calling sequence from Fortran is
1014: .vb
1015: EPSKrylovSchurGetInertias(eps,n,shifts,inertias,ierr)
1016: integer n
1017: double precision shifts(*)
1018: integer inertias(*)
1019: .ve
1020: The arrays should be at least of length n. The value of n can be determined
1021: by an initial call
1022: .vb
1023: EPSKrylovSchurGetInertias(eps,n,PETSC_NULL_REAL,PETSC_NULL_INTEGER,ierr)
1024: .ve
1026: Level: advanced
1028: .seealso: EPSSetInterval(), EPSKrylovSchurSetSubintervals()
1029: @*/
1030: PetscErrorCode EPSKrylovSchurGetInertias(EPS eps,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
1031: {
1037: PetscUseMethod(eps,"EPSKrylovSchurGetInertias_C",(EPS,PetscInt*,PetscReal**,PetscInt**),(eps,n,shifts,inertias));
1038: return(0);
1039: }
1041: static PetscErrorCode EPSKrylovSchurGetSubcommInfo_KrylovSchur(EPS eps,PetscInt *k,PetscInt *n,Vec *v)
1042: {
1043: PetscErrorCode ierr;
1044: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1045: EPS_SR sr = ((EPS_KRYLOVSCHUR*)ctx->eps->data)->sr;
1048: if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
1049: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1050: if (k) *k = (ctx->npart==1)? 0: ctx->subc->color;
1051: if (n) *n = sr->numEigs;
1052: if (v) {
1053: BVCreateVec(sr->V,v);
1054: }
1055: return(0);
1056: }
1058: /*@C
1059: EPSKrylovSchurGetSubcommInfo - Gets information related to the case of
1060: doing spectrum slicing for a computational interval with multiple
1061: communicators.
1063: Collective on the subcommunicator (if v is given)
1065: Input Parameter:
1066: . eps - the eigenproblem solver context
1068: Output Parameters:
1069: + k - index of the subinterval for the calling process
1070: . n - number of eigenvalues found in the k-th subinterval
1071: - v - a vector owned by processes in the subcommunicator with dimensions
1072: compatible for locally computed eigenvectors (or NULL)
1074: Notes:
1075: This function is only available for spectrum slicing runs.
1077: The returned Vec should be destroyed by the user.
1079: Level: advanced
1081: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommPairs()
1082: @*/
1083: PetscErrorCode EPSKrylovSchurGetSubcommInfo(EPS eps,PetscInt *k,PetscInt *n,Vec *v)
1084: {
1089: PetscUseMethod(eps,"EPSKrylovSchurGetSubcommInfo_C",(EPS,PetscInt*,PetscInt*,Vec*),(eps,k,n,v));
1090: return(0);
1091: }
1093: static PetscErrorCode EPSKrylovSchurGetSubcommPairs_KrylovSchur(EPS eps,PetscInt i,PetscScalar *eig,Vec v)
1094: {
1095: PetscErrorCode ierr;
1096: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1097: EPS_SR sr = ((EPS_KRYLOVSCHUR*)ctx->eps->data)->sr;
1100: EPSCheckSolved(eps,1);
1101: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1102: if (i<0 || i>=sr->numEigs) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
1103: if (eig) *eig = sr->eigr[sr->perm[i]];
1104: if (v) { BVCopyVec(sr->V,sr->perm[i],v); }
1105: return(0);
1106: }
1108: /*@
1109: EPSKrylovSchurGetSubcommPairs - Gets the i-th eigenpair stored
1110: internally in the subcommunicator to which the calling process belongs.
1112: Collective on the subcommunicator (if v is given)
1114: Input Parameters:
1115: + eps - the eigenproblem solver context
1116: - i - index of the solution
1118: Output Parameters:
1119: + eig - the eigenvalue
1120: - v - the eigenvector
1122: Notes:
1123: It is allowed to pass NULL for v if the eigenvector is not required.
1124: Otherwise, the caller must provide a valid Vec objects, i.e.,
1125: it must be created by the calling program with EPSKrylovSchurGetSubcommInfo().
1127: The index i should be a value between 0 and n-1, where n is the number of
1128: vectors in the local subinterval, see EPSKrylovSchurGetSubcommInfo().
1130: Level: advanced
1132: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommInfo(), EPSKrylovSchurGetSubcommMats()
1133: @*/
1134: PetscErrorCode EPSKrylovSchurGetSubcommPairs(EPS eps,PetscInt i,PetscScalar *eig,Vec v)
1135: {
1141: PetscUseMethod(eps,"EPSKrylovSchurGetSubcommPairs_C",(EPS,PetscInt,PetscScalar*,Vec),(eps,i,eig,v));
1142: return(0);
1143: }
1145: static PetscErrorCode EPSKrylovSchurGetSubcommMats_KrylovSchur(EPS eps,Mat *A,Mat *B)
1146: {
1147: PetscErrorCode ierr;
1148: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1151: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1152: if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
1153: EPSGetOperators(ctx->eps,A,B);
1154: return(0);
1155: }
1157: /*@C
1158: EPSKrylovSchurGetSubcommMats - Gets the eigenproblem matrices stored
1159: internally in the subcommunicator to which the calling process belongs.
1161: Collective on the subcommunicator
1163: Input Parameter:
1164: . eps - the eigenproblem solver context
1166: Output Parameters:
1167: + A - the matrix associated with the eigensystem
1168: - B - the second matrix in the case of generalized eigenproblems
1170: Notes:
1171: This is the analog of EPSGetOperators(), but returns the matrices distributed
1172: differently (in the subcommunicator rather than in the parent communicator).
1174: These matrices should not be modified by the user.
1176: Level: advanced
1178: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommInfo()
1179: @*/
1180: PetscErrorCode EPSKrylovSchurGetSubcommMats(EPS eps,Mat *A,Mat *B)
1181: {
1186: PetscTryMethod(eps,"EPSKrylovSchurGetSubcommMats_C",(EPS,Mat*,Mat*),(eps,A,B));
1187: return(0);
1188: }
1190: static PetscErrorCode EPSKrylovSchurUpdateSubcommMats_KrylovSchur(EPS eps,PetscScalar a,PetscScalar ap,Mat Au,PetscScalar b,PetscScalar bp, Mat Bu,MatStructure str,PetscBool globalup)
1191: {
1192: PetscErrorCode ierr;
1193: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data,*subctx;
1194: Mat A,B=NULL,Ag,Bg=NULL;
1195: PetscBool reuse=PETSC_TRUE;
1198: if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1199: if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
1200: EPSGetOperators(eps,&Ag,&Bg);
1201: EPSGetOperators(ctx->eps,&A,&B);
1203: MatScale(A,a);
1204: if (Au) {
1205: MatAXPY(A,ap,Au,str);
1206: }
1207: if (B) MatScale(B,b);
1208: if (Bu) {
1209: MatAXPY(B,bp,Bu,str);
1210: }
1211: EPSSetOperators(ctx->eps,A,B);
1213: /* Update stored matrix state */
1214: subctx = (EPS_KRYLOVSCHUR*)ctx->eps->data;
1215: PetscObjectStateGet((PetscObject)A,&subctx->Astate);
1216: if (B) { PetscObjectStateGet((PetscObject)B,&subctx->Bstate); }
1218: /* Update matrices in the parent communicator if requested by user */
1219: if (globalup) {
1220: if (ctx->npart>1) {
1221: if (!ctx->isrow) {
1222: MatGetOwnershipIS(Ag,&ctx->isrow,&ctx->iscol);
1223: reuse = PETSC_FALSE;
1224: }
1225: if (str==DIFFERENT_NONZERO_PATTERN || str==UNKNOWN_NONZERO_PATTERN) reuse = PETSC_FALSE;
1226: if (ctx->submata && !reuse) {
1227: MatDestroyMatrices(1,&ctx->submata);
1228: }
1229: MatCreateSubMatrices(A,1,&ctx->isrow,&ctx->iscol,(reuse)?MAT_REUSE_MATRIX:MAT_INITIAL_MATRIX,&ctx->submata);
1230: MatCreateMPIMatConcatenateSeqMat(((PetscObject)Ag)->comm,ctx->submata[0],PETSC_DECIDE,MAT_REUSE_MATRIX,&Ag);
1231: if (B) {
1232: if (ctx->submatb && !reuse) {
1233: MatDestroyMatrices(1,&ctx->submatb);
1234: }
1235: MatCreateSubMatrices(B,1,&ctx->isrow,&ctx->iscol,(reuse)?MAT_REUSE_MATRIX:MAT_INITIAL_MATRIX,&ctx->submatb);
1236: MatCreateMPIMatConcatenateSeqMat(((PetscObject)Bg)->comm,ctx->submatb[0],PETSC_DECIDE,MAT_REUSE_MATRIX,&Bg);
1237: }
1238: }
1239: PetscObjectStateGet((PetscObject)Ag,&ctx->Astate);
1240: if (Bg) { PetscObjectStateGet((PetscObject)Bg,&ctx->Bstate); }
1241: }
1242: EPSSetOperators(eps,Ag,Bg);
1243: return(0);
1244: }
1246: /*@
1247: EPSKrylovSchurUpdateSubcommMats - Update the eigenproblem matrices stored
1248: internally in the subcommunicator to which the calling process belongs.
1250: Collective on eps
1252: Input Parameters:
1253: + eps - the eigenproblem solver context
1254: . s - scalar that multiplies the existing A matrix
1255: . a - scalar used in the axpy operation on A
1256: . Au - matrix used in the axpy operation on A
1257: . t - scalar that multiplies the existing B matrix
1258: . b - scalar used in the axpy operation on B
1259: . Bu - matrix used in the axpy operation on B
1260: . str - structure flag
1261: - globalup - flag indicating if global matrices must be updated
1263: Notes:
1264: This function modifies the eigenproblem matrices at the subcommunicator level,
1265: and optionally updates the global matrices in the parent communicator. The updates
1266: are expressed as A <-- s*A + a*Au, B <-- t*B + b*Bu.
1268: It is possible to update one of the matrices, or both.
1270: The matrices Au and Bu must be equal in all subcommunicators.
1272: The str flag is passed to the MatAXPY() operations to perform the updates.
1274: If globalup is true, communication is carried out to reconstruct the updated
1275: matrices in the parent communicator. The user must be warned that if global
1276: matrices are not in sync with subcommunicator matrices, the errors computed
1277: by EPSComputeError() will be wrong even if the computed solution is correct
1278: (the synchronization may be done only once at the end).
1280: Level: advanced
1282: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommMats()
1283: @*/
1284: PetscErrorCode EPSKrylovSchurUpdateSubcommMats(EPS eps,PetscScalar s,PetscScalar a,Mat Au,PetscScalar t,PetscScalar b,Mat Bu,MatStructure str,PetscBool globalup)
1285: {
1298: PetscTryMethod(eps,"EPSKrylovSchurUpdateSubcommMats_C",(EPS,PetscScalar,PetscScalar,Mat,PetscScalar,PetscScalar,Mat,MatStructure,PetscBool),(eps,s,a,Au,t,b,Bu,str,globalup));
1299: return(0);
1300: }
1302: PetscErrorCode EPSKrylovSchurGetChildEPS(EPS eps,EPS *child)
1303: {
1304: PetscErrorCode ierr;
1305: EPS_KRYLOVSCHUR *ctx=(EPS_KRYLOVSCHUR*)eps->data,*ctx_local;
1306: Mat A,B=NULL,Ar=NULL,Br=NULL;
1307: PetscMPIInt rank;
1308: PetscObjectState Astate,Bstate=0;
1309: PetscObjectId Aid,Bid=0;
1310: STType sttype;
1311: PetscInt nmat;
1312: const char *prefix;
1315: EPSGetOperators(eps,&A,&B);
1316: if (ctx->npart==1) {
1317: if (!ctx->eps) {EPSCreate(((PetscObject)eps)->comm,&ctx->eps);}
1318: EPSGetOptionsPrefix(eps,&prefix);
1319: EPSSetOptionsPrefix(ctx->eps,prefix);
1320: EPSSetOperators(ctx->eps,A,B);
1321: } else {
1322: PetscObjectStateGet((PetscObject)A,&Astate);
1323: PetscObjectGetId((PetscObject)A,&Aid);
1324: if (B) {
1325: PetscObjectStateGet((PetscObject)B,&Bstate);
1326: PetscObjectGetId((PetscObject)B,&Bid);
1327: }
1328: if (!ctx->subc) {
1329: /* Create context for subcommunicators */
1330: PetscSubcommCreate(PetscObjectComm((PetscObject)eps),&ctx->subc);
1331: PetscSubcommSetNumber(ctx->subc,ctx->npart);
1332: PetscSubcommSetType(ctx->subc,PETSC_SUBCOMM_CONTIGUOUS);
1333: PetscLogObjectMemory((PetscObject)eps,sizeof(PetscSubcomm));
1335: /* Duplicate matrices */
1336: MatCreateRedundantMatrix(A,0,PetscSubcommChild(ctx->subc),MAT_INITIAL_MATRIX,&Ar);
1337: PetscLogObjectParent((PetscObject)eps,(PetscObject)Ar);
1338: ctx->Astate = Astate;
1339: ctx->Aid = Aid;
1340: MatPropagateSymmetryOptions(A,Ar);
1341: if (B) {
1342: MatCreateRedundantMatrix(B,0,PetscSubcommChild(ctx->subc),MAT_INITIAL_MATRIX,&Br);
1343: PetscLogObjectParent((PetscObject)eps,(PetscObject)Br);
1344: ctx->Bstate = Bstate;
1345: ctx->Bid = Bid;
1346: MatPropagateSymmetryOptions(B,Br);
1347: }
1348: } else {
1349: if (ctx->Astate != Astate || (B && ctx->Bstate != Bstate) || ctx->Aid != Aid || (B && ctx->Bid != Bid)) {
1350: STGetNumMatrices(ctx->eps->st,&nmat);
1351: if (nmat) {EPSGetOperators(ctx->eps,&Ar,&Br);}
1352: MatCreateRedundantMatrix(A,0,PetscSubcommChild(ctx->subc),MAT_INITIAL_MATRIX,&Ar);
1353: ctx->Astate = Astate;
1354: ctx->Aid = Aid;
1355: MatPropagateSymmetryOptions(A,Ar);
1356: if (B) {
1357: MatCreateRedundantMatrix(B,0,PetscSubcommChild(ctx->subc),MAT_INITIAL_MATRIX,&Br);
1358: ctx->Bstate = Bstate;
1359: ctx->Bid = Bid;
1360: MatPropagateSymmetryOptions(B,Br);
1361: }
1362: EPSSetOperators(ctx->eps,Ar,Br);
1363: MatDestroy(&Ar);
1364: MatDestroy(&Br);
1365: }
1366: }
1368: /* Create auxiliary EPS */
1369: if (!ctx->eps) {
1370: EPSCreate(PetscSubcommChild(ctx->subc),&ctx->eps);
1371: EPSGetOptionsPrefix(eps,&prefix);
1372: EPSSetOptionsPrefix(ctx->eps,prefix);
1373: EPSSetOperators(ctx->eps,Ar,Br);
1374: MatDestroy(&Ar);
1375: MatDestroy(&Br);
1376: }
1377: /* Create subcommunicator grouping processes with same rank */
1378: if (ctx->commset) { MPI_Comm_free(&ctx->commrank); }
1379: MPI_Comm_rank(PetscSubcommChild(ctx->subc),&rank);
1380: MPI_Comm_split(((PetscObject)eps)->comm,rank,ctx->subc->color,&ctx->commrank);
1381: ctx->commset = PETSC_TRUE;
1382: }
1383: EPSSetType(ctx->eps,((PetscObject)eps)->type_name);
1384: STGetType(eps->st,&sttype);
1385: STSetType(ctx->eps->st,sttype);
1387: ctx_local = (EPS_KRYLOVSCHUR*)ctx->eps->data;
1388: ctx_local->npart = ctx->npart;
1389: ctx_local->global = PETSC_FALSE;
1390: ctx_local->eps = eps;
1391: ctx_local->subc = ctx->subc;
1392: ctx_local->commrank = ctx->commrank;
1393: *child = ctx->eps;
1394: return(0);
1395: }
1397: static PetscErrorCode EPSKrylovSchurGetKSP_KrylovSchur(EPS eps,KSP *ksp)
1398: {
1399: PetscErrorCode ierr;
1400: EPS_KRYLOVSCHUR *ctx=(EPS_KRYLOVSCHUR*)eps->data;
1401: ST st;
1402: PetscBool isfilt;
1405: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
1406: if (eps->which!=EPS_ALL || isfilt) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations with spectrum slicing");
1407: EPSKrylovSchurGetChildEPS(eps,&ctx->eps);
1408: EPSGetST(ctx->eps,&st);
1409: STGetOperator(st,NULL);
1410: STGetKSP(st,ksp);
1411: return(0);
1412: }
1414: /*@
1415: EPSKrylovSchurGetKSP - Retrieve the linear solver object associated with the
1416: internal EPS object in case of doing spectrum slicing for a computational interval.
1418: Collective on eps
1420: Input Parameter:
1421: . eps - the eigenproblem solver context
1423: Output Parameters:
1424: - ksp - the internal KSP object
1426: Notes:
1427: When invoked to compute all eigenvalues in an interval with spectrum
1428: slicing, EPSKRYLOVSCHUR creates another EPS object internally that is
1429: used to compute eigenvalues by chunks near selected shifts. This function
1430: allows access to the KSP object associated to this internal EPS object.
1432: This function is only available for spectrum slicing runs. In case of
1433: having more than one partition, the returned KSP will be different
1434: in MPI processes belonging to different partitions. Hence, if required,
1435: EPSKrylovSchurSetPartitions() must be called BEFORE this function.
1437: Level: advanced
1439: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions()
1440: @*/
1441: PetscErrorCode EPSKrylovSchurGetKSP(EPS eps,KSP *ksp)
1442: {
1447: PetscUseMethod(eps,"EPSKrylovSchurGetKSP_C",(EPS,KSP*),(eps,ksp));
1448: return(0);
1449: }
1451: PetscErrorCode EPSSetFromOptions_KrylovSchur(PetscOptionItems *PetscOptionsObject,EPS eps)
1452: {
1453: PetscErrorCode ierr;
1454: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1455: PetscBool flg,lock,b,f1,f2,f3,isfilt;
1456: PetscReal keep;
1457: PetscInt i,j,k;
1458: KSP ksp;
1461: PetscOptionsHead(PetscOptionsObject,"EPS Krylov-Schur Options");
1463: PetscOptionsReal("-eps_krylovschur_restart","Proportion of vectors kept after restart","EPSKrylovSchurSetRestart",0.5,&keep,&flg);
1464: if (flg) { EPSKrylovSchurSetRestart(eps,keep); }
1466: PetscOptionsBool("-eps_krylovschur_locking","Choose between locking and non-locking variants","EPSKrylovSchurSetLocking",PETSC_TRUE,&lock,&flg);
1467: if (flg) { EPSKrylovSchurSetLocking(eps,lock); }
1469: i = ctx->npart;
1470: PetscOptionsInt("-eps_krylovschur_partitions","Number of partitions of the communicator for spectrum slicing","EPSKrylovSchurSetPartitions",ctx->npart,&i,&flg);
1471: if (flg) { EPSKrylovSchurSetPartitions(eps,i); }
1473: b = ctx->detect;
1474: PetscOptionsBool("-eps_krylovschur_detect_zeros","Check zeros during factorizations at subinterval boundaries","EPSKrylovSchurSetDetectZeros",ctx->detect,&b,&flg);
1475: if (flg) { EPSKrylovSchurSetDetectZeros(eps,b); }
1477: i = 1;
1478: j = k = PETSC_DECIDE;
1479: PetscOptionsInt("-eps_krylovschur_nev","Number of eigenvalues to compute in each subsolve (only for spectrum slicing)","EPSKrylovSchurSetDimensions",40,&i,&f1);
1480: PetscOptionsInt("-eps_krylovschur_ncv","Number of basis vectors in each subsolve (only for spectrum slicing)","EPSKrylovSchurSetDimensions",80,&j,&f2);
1481: PetscOptionsInt("-eps_krylovschur_mpd","Maximum dimension of projected problem in each subsolve (only for spectrum slicing)","EPSKrylovSchurSetDimensions",80,&k,&f3);
1482: if (f1 || f2 || f3) { EPSKrylovSchurSetDimensions(eps,i,j,k); }
1484: PetscOptionsTail();
1486: /* set options of child KSP in spectrum slicing */
1487: if (eps->which==EPS_ALL) {
1488: if (!eps->st) { EPSGetST(eps,&eps->st); }
1489: EPSSetDefaultST(eps);
1490: STSetFromOptions(eps->st); /* need to advance this to check ST type */
1491: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
1492: if (!isfilt) {
1493: EPSKrylovSchurGetKSP_KrylovSchur(eps,&ksp);
1494: KSPSetFromOptions(ksp);
1495: }
1496: }
1497: return(0);
1498: }
1500: PetscErrorCode EPSView_KrylovSchur(EPS eps,PetscViewer viewer)
1501: {
1502: PetscErrorCode ierr;
1503: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1504: PetscBool isascii,isfilt;
1505: KSP ksp;
1506: PetscViewer sviewer;
1509: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
1510: if (isascii) {
1511: PetscViewerASCIIPrintf(viewer," %d%% of basis vectors kept after restart\n",(int)(100*ctx->keep));
1512: PetscViewerASCIIPrintf(viewer," using the %slocking variant\n",ctx->lock?"":"non-");
1513: if (eps->which==EPS_ALL) {
1514: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
1515: if (isfilt) {
1516: PetscViewerASCIIPrintf(viewer," using filtering to extract all eigenvalues in an interval\n");
1517: } else {
1518: PetscViewerASCIIPrintf(viewer," doing spectrum slicing with nev=%D, ncv=%D, mpd=%D\n",ctx->nev,ctx->ncv,ctx->mpd);
1519: if (ctx->npart>1) {
1520: PetscViewerASCIIPrintf(viewer," multi-communicator spectrum slicing with %D partitions\n",ctx->npart);
1521: if (ctx->detect) { PetscViewerASCIIPrintf(viewer," detecting zeros when factorizing at subinterval boundaries\n"); }
1522: }
1523: /* view child KSP */
1524: EPSKrylovSchurGetKSP_KrylovSchur(eps,&ksp);
1525: PetscViewerASCIIPushTab(viewer);
1526: if (ctx->npart>1 && ctx->subc) {
1527: PetscViewerGetSubViewer(viewer,ctx->subc->child,&sviewer);
1528: if (!ctx->subc->color) {
1529: KSPView(ksp,sviewer);
1530: }
1531: PetscViewerFlush(sviewer);
1532: PetscViewerRestoreSubViewer(viewer,ctx->subc->child,&sviewer);
1533: PetscViewerFlush(viewer);
1534: /* extra call needed because of the two calls to PetscViewerASCIIPushSynchronized() in PetscViewerGetSubViewer() */
1535: PetscViewerASCIIPopSynchronized(viewer);
1536: } else {
1537: KSPView(ksp,viewer);
1538: }
1539: PetscViewerASCIIPopTab(viewer);
1540: }
1541: }
1542: }
1543: return(0);
1544: }
1546: PetscErrorCode EPSDestroy_KrylovSchur(EPS eps)
1547: {
1549: PetscBool isfilt;
1552: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
1553: if (eps->which==EPS_ALL && !isfilt) {
1554: EPSDestroy_KrylovSchur_Slice(eps);
1555: }
1556: PetscFree(eps->data);
1557: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetRestart_C",NULL);
1558: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetRestart_C",NULL);
1559: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetLocking_C",NULL);
1560: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetLocking_C",NULL);
1561: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetPartitions_C",NULL);
1562: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetPartitions_C",NULL);
1563: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDetectZeros_C",NULL);
1564: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDetectZeros_C",NULL);
1565: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDimensions_C",NULL);
1566: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDimensions_C",NULL);
1567: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetSubintervals_C",NULL);
1568: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubintervals_C",NULL);
1569: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetInertias_C",NULL);
1570: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommInfo_C",NULL);
1571: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommPairs_C",NULL);
1572: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommMats_C",NULL);
1573: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurUpdateSubcommMats_C",NULL);
1574: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetKSP_C",NULL);
1575: return(0);
1576: }
1578: PetscErrorCode EPSReset_KrylovSchur(EPS eps)
1579: {
1581: PetscBool isfilt;
1584: PetscObjectTypeCompare((PetscObject)eps->st,STFILTER,&isfilt);
1585: if (eps->which==EPS_ALL && !isfilt) {
1586: EPSReset_KrylovSchur_Slice(eps);
1587: }
1588: return(0);
1589: }
1591: PetscErrorCode EPSSetDefaultST_KrylovSchur(EPS eps)
1592: {
1596: if (eps->which==EPS_ALL) {
1597: if (!((PetscObject)eps->st)->type_name) {
1598: STSetType(eps->st,STSINVERT);
1599: }
1600: }
1601: return(0);
1602: }
1604: SLEPC_EXTERN PetscErrorCode EPSCreate_KrylovSchur(EPS eps)
1605: {
1606: EPS_KRYLOVSCHUR *ctx;
1607: PetscErrorCode ierr;
1610: PetscNewLog(eps,&ctx);
1611: eps->data = (void*)ctx;
1612: ctx->lock = PETSC_TRUE;
1613: ctx->nev = 1;
1614: ctx->ncv = PETSC_DEFAULT;
1615: ctx->mpd = PETSC_DEFAULT;
1616: ctx->npart = 1;
1617: ctx->detect = PETSC_FALSE;
1618: ctx->global = PETSC_TRUE;
1620: eps->useds = PETSC_TRUE;
1622: /* solve and computevectors determined at setup */
1623: eps->ops->setup = EPSSetUp_KrylovSchur;
1624: eps->ops->setupsort = EPSSetUpSort_KrylovSchur;
1625: eps->ops->setfromoptions = EPSSetFromOptions_KrylovSchur;
1626: eps->ops->destroy = EPSDestroy_KrylovSchur;
1627: eps->ops->reset = EPSReset_KrylovSchur;
1628: eps->ops->view = EPSView_KrylovSchur;
1629: eps->ops->backtransform = EPSBackTransform_Default;
1630: eps->ops->setdefaultst = EPSSetDefaultST_KrylovSchur;
1632: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetRestart_C",EPSKrylovSchurSetRestart_KrylovSchur);
1633: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetRestart_C",EPSKrylovSchurGetRestart_KrylovSchur);
1634: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetLocking_C",EPSKrylovSchurSetLocking_KrylovSchur);
1635: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetLocking_C",EPSKrylovSchurGetLocking_KrylovSchur);
1636: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetPartitions_C",EPSKrylovSchurSetPartitions_KrylovSchur);
1637: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetPartitions_C",EPSKrylovSchurGetPartitions_KrylovSchur);
1638: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDetectZeros_C",EPSKrylovSchurSetDetectZeros_KrylovSchur);
1639: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDetectZeros_C",EPSKrylovSchurGetDetectZeros_KrylovSchur);
1640: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDimensions_C",EPSKrylovSchurSetDimensions_KrylovSchur);
1641: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDimensions_C",EPSKrylovSchurGetDimensions_KrylovSchur);
1642: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetSubintervals_C",EPSKrylovSchurSetSubintervals_KrylovSchur);
1643: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubintervals_C",EPSKrylovSchurGetSubintervals_KrylovSchur);
1644: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetInertias_C",EPSKrylovSchurGetInertias_KrylovSchur);
1645: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommInfo_C",EPSKrylovSchurGetSubcommInfo_KrylovSchur);
1646: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommPairs_C",EPSKrylovSchurGetSubcommPairs_KrylovSchur);
1647: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommMats_C",EPSKrylovSchurGetSubcommMats_KrylovSchur);
1648: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurUpdateSubcommMats_C",EPSKrylovSchurUpdateSubcommMats_KrylovSchur);
1649: PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetKSP_C",EPSKrylovSchurGetKSP_KrylovSchur);
1650: return(0);
1651: }