Actual source code: krylovschur.c

slepc-3.7.0 2016-05-16
Report Typos and Errors
  1: /*

  3:    SLEPc eigensolver: "krylovschur"

  5:    Method: Krylov-Schur

  7:    Algorithm:

  9:        Single-vector Krylov-Schur method for non-symmetric problems,
 10:        including harmonic extraction.

 12:    References:

 14:        [1] "Krylov-Schur Methods in SLEPc", SLEPc Technical Report STR-7,
 15:            available at http://slepc.upv.es.

 17:        [2] G.W. Stewart, "A Krylov-Schur Algorithm for Large Eigenproblems",
 18:            SIAM J. Matrix Anal. App. 23(3):601-614, 2001.

 20:        [3] "Practical Implementation of Harmonic Krylov-Schur", SLEPc Technical
 21:             Report STR-9, available at http://slepc.upv.es.

 23:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 24:    SLEPc - Scalable Library for Eigenvalue Problem Computations
 25:    Copyright (c) 2002-2016, Universitat Politecnica de Valencia, Spain

 27:    This file is part of SLEPc.

 29:    SLEPc is free software: you can redistribute it and/or modify it under  the
 30:    terms of version 3 of the GNU Lesser General Public License as published by
 31:    the Free Software Foundation.

 33:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
 34:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
 35:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
 36:    more details.

 38:    You  should have received a copy of the GNU Lesser General  Public  License
 39:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
 40:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 41: */

 43: #include <slepc/private/epsimpl.h>                /*I "slepceps.h" I*/
 44:  #include krylovschur.h

 48: PetscErrorCode EPSGetArbitraryValues(EPS eps,PetscScalar *rr,PetscScalar *ri)
 49: {
 51:   PetscInt       i,newi,ld,n,l;
 52:   Vec            xr=eps->work[0],xi=eps->work[1];
 53:   PetscScalar    re,im,*Zr,*Zi,*X;

 56:   DSGetLeadingDimension(eps->ds,&ld);
 57:   DSGetDimensions(eps->ds,&n,NULL,&l,NULL,NULL);
 58:   for (i=l;i<n;i++) {
 59:     re = eps->eigr[i];
 60:     im = eps->eigi[i];
 61:     STBackTransform(eps->st,1,&re,&im);
 62:     newi = i;
 63:     DSVectors(eps->ds,DS_MAT_X,&newi,NULL);
 64:     DSGetArray(eps->ds,DS_MAT_X,&X);
 65:     Zr = X+i*ld;
 66:     if (newi==i+1) Zi = X+newi*ld;
 67:     else Zi = NULL;
 68:     EPSComputeRitzVector(eps,Zr,Zi,eps->V,xr,xi);
 69:     DSRestoreArray(eps->ds,DS_MAT_X,&X);
 70:     (*eps->arbitrary)(re,im,xr,xi,rr+i,ri+i,eps->arbitraryctx);
 71:   }
 72:   return(0);
 73: }

 77: PetscErrorCode EPSSetUp_KrylovSchur(EPS eps)
 78: {
 79:   PetscErrorCode    ierr;
 80:   PetscReal         eta;
 81:   BVOrthogType      otype;
 82:   BVOrthogBlockType obtype;
 83:   EPS_KRYLOVSCHUR   *ctx = (EPS_KRYLOVSCHUR*)eps->data;
 84:   enum { EPS_KS_DEFAULT,EPS_KS_SYMM,EPS_KS_SLICE,EPS_KS_INDEF } variant;

 87:   /* spectrum slicing requires special treatment of default values */
 88:   if (eps->which==EPS_ALL) {
 89:     EPSSetUp_KrylovSchur_Slice(eps);
 90:   } else {
 91:     EPSSetDimensions_Default(eps,eps->nev,&eps->ncv,&eps->mpd);
 92:     if (eps->ncv>eps->nev+eps->mpd) SETERRQ(PetscObjectComm((PetscObject)eps),1,"The value of ncv must not be larger than nev+mpd");
 93:     if (!eps->max_it) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
 94:     if (!eps->which) { EPSSetWhichEigenpairs_Default(eps); }
 95:   }
 96:   if (!ctx->lock && eps->mpd<eps->ncv) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Should not use mpd parameter in non-locking variant");

 98:   if (eps->isgeneralized && eps->ishermitian && !eps->ispositive && eps->arbitrary) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Arbitrary selection of eigenpairs not implemented for indefinite problems");
 99:   if (eps->ishermitian && eps->ispositive && (eps->which==EPS_LARGEST_IMAGINARY || eps->which==EPS_SMALLEST_IMAGINARY)) SETERRQ(PetscObjectComm((PetscObject)eps),1,"Wrong value of eps->which");

101:   if (!eps->extraction) {
102:     EPSSetExtraction(eps,EPS_RITZ);
103:   } else if (eps->extraction!=EPS_RITZ && eps->extraction!=EPS_HARMONIC)
104:     SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
105:   if (eps->extraction==EPS_HARMONIC && ctx->lock) { PetscInfo(eps,"Locking was requested but will be deactivated since is not supported with harmonic extraction\n"); }

107:   if (!ctx->keep) ctx->keep = 0.5;

109:   EPSAllocateSolution(eps,1);
110:   EPS_SetInnerProduct(eps);
111:   if (eps->arbitrary) {
112:     EPSSetWorkVecs(eps,2);
113:   } else if (eps->ishermitian && !eps->ispositive){
114:     EPSSetWorkVecs(eps,1);
115:   }

117:   /* dispatch solve method */
118:   if (eps->ishermitian) {
119:     if (eps->which==EPS_ALL) {
120:       if (eps->isgeneralized && !eps->ispositive) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Spectrum slicing not implemented for indefinite problems");
121:       else variant = EPS_KS_SLICE;
122:     } else if (eps->isgeneralized && !eps->ispositive) {
123:       variant = EPS_KS_INDEF;
124:     } else {
125:       switch (eps->extraction) {
126:         case EPS_RITZ:     variant = EPS_KS_SYMM; break;
127:         case EPS_HARMONIC: variant = EPS_KS_DEFAULT; break;
128:         default: SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
129:       }
130:     }
131:   } else {
132:     switch (eps->extraction) {
133:       case EPS_RITZ:     variant = EPS_KS_DEFAULT; break;
134:       case EPS_HARMONIC: variant = EPS_KS_DEFAULT; break;
135:       default: SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
136:     }
137:   }
138:   switch (variant) {
139:     case EPS_KS_DEFAULT:
140:       eps->ops->solve = EPSSolve_KrylovSchur_Default;
141:       eps->ops->computevectors = EPSComputeVectors_Schur;
142:       DSSetType(eps->ds,DSNHEP);
143:       DSAllocate(eps->ds,eps->ncv+1);
144:       break;
145:     case EPS_KS_SYMM:
146:       eps->ops->solve = EPSSolve_KrylovSchur_Symm;
147:       eps->ops->computevectors = EPSComputeVectors_Hermitian;
148:       DSSetType(eps->ds,DSHEP);
149:       DSSetCompact(eps->ds,PETSC_TRUE);
150:       DSSetExtraRow(eps->ds,PETSC_TRUE);
151:       DSAllocate(eps->ds,eps->ncv+1);
152:       break;
153:     case EPS_KS_SLICE:
154:       if (eps->stopping!=EPSStoppingBasic) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Spectrum slicing does not support user-defined stopping test");
155:       eps->ops->solve = EPSSolve_KrylovSchur_Slice;
156:       eps->ops->computevectors = EPSComputeVectors_Slice;
157:       break;
158:     case EPS_KS_INDEF:
159:       eps->ops->solve = EPSSolve_KrylovSchur_Indefinite;
160:       eps->ops->computevectors = EPSComputeVectors_Indefinite;
161:       DSSetType(eps->ds,DSGHIEP);
162:       DSSetCompact(eps->ds,PETSC_TRUE);
163:       DSAllocate(eps->ds,eps->ncv+1);
164:       /* force reorthogonalization for pseudo-Lanczos */
165:       BVGetOrthogonalization(eps->V,&otype,NULL,&eta,&obtype);
166:       BVSetOrthogonalization(eps->V,otype,BV_ORTHOG_REFINE_ALWAYS,eta,obtype);
167:       break;
168:     default: SETERRQ(PetscObjectComm((PetscObject)eps),1,"Unexpected error");
169:   }
170:   return(0);
171: }

175: PetscErrorCode EPSSolve_KrylovSchur_Default(EPS eps)
176: {
177:   PetscErrorCode  ierr;
178:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
179:   PetscInt        i,j,*pj,k,l,nv,ld,nconv;
180:   Mat             U;
181:   PetscScalar     *S,*Q,*g;
182:   PetscReal       beta,gamma=1.0;
183:   PetscBool       breakdown,harmonic;

186:   DSGetLeadingDimension(eps->ds,&ld);
187:   harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE;
188:   if (harmonic) { PetscMalloc1(ld,&g); }
189:   if (eps->arbitrary) pj = &j;
190:   else pj = NULL;

192:   /* Get the starting Arnoldi vector */
193:   EPSGetStartVector(eps,0,NULL);
194:   l = 0;

196:   /* Restart loop */
197:   while (eps->reason == EPS_CONVERGED_ITERATING) {
198:     eps->its++;

200:     /* Compute an nv-step Arnoldi factorization */
201:     nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
202:     DSGetArray(eps->ds,DS_MAT_A,&S);
203:     EPSBasicArnoldi(eps,PETSC_FALSE,S,ld,eps->nconv+l,&nv,&beta,&breakdown);
204:     DSRestoreArray(eps->ds,DS_MAT_A,&S);
205:     DSSetDimensions(eps->ds,nv,0,eps->nconv,eps->nconv+l);
206:     if (l==0) {
207:       DSSetState(eps->ds,DS_STATE_INTERMEDIATE);
208:     } else {
209:       DSSetState(eps->ds,DS_STATE_RAW);
210:     }
211:     BVSetActiveColumns(eps->V,eps->nconv,nv);

213:     /* Compute translation of Krylov decomposition if harmonic extraction used */
214:     if (harmonic) {
215:       DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,g,&gamma);
216:     }

218:     /* Solve projected problem */
219:     DSSolve(eps->ds,eps->eigr,eps->eigi);
220:     if (eps->arbitrary) {
221:       EPSGetArbitraryValues(eps,eps->rr,eps->ri);
222:       j=1;
223:     }
224:     DSSort(eps->ds,eps->eigr,eps->eigi,eps->rr,eps->ri,pj);

226:     /* Check convergence */
227:     EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,gamma,&k);
228:     (*eps->stopping)(eps,eps->its,eps->max_it,k,eps->nev,&eps->reason,eps->stoppingctx);
229:     nconv = k;

231:     /* Update l */
232:     if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
233:     else {
234:       l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep));
235: #if !defined(PETSC_USE_COMPLEX)
236:       DSGetArray(eps->ds,DS_MAT_A,&S);
237:       if (S[k+l+(k+l-1)*ld] != 0.0) {
238:         if (k+l<nv-1) l = l+1;
239:         else l = l-1;
240:       }
241:       DSRestoreArray(eps->ds,DS_MAT_A,&S);
242: #endif
243:     }
244:     if ((!ctx->lock || harmonic) && l>0) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */

246:     if (eps->reason == EPS_CONVERGED_ITERATING) {
247:       if (breakdown) {
248:         /* Start a new Arnoldi factorization */
249:         PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%g)\n",eps->its,(double)beta);
250:         if (k<eps->nev) {
251:           EPSGetStartVector(eps,k,&breakdown);
252:           if (breakdown) {
253:             eps->reason = EPS_DIVERGED_BREAKDOWN;
254:             PetscInfo(eps,"Unable to generate more start vectors\n");
255:           }
256:         }
257:       } else {
258:         /* Undo translation of Krylov decomposition */
259:         if (harmonic) {
260:           DSSetDimensions(eps->ds,nv,0,k,l);
261:           DSTranslateHarmonic(eps->ds,0.0,beta,PETSC_TRUE,g,&gamma);
262:           /* gamma u^ = u - U*g~ */
263:           BVMultColumn(eps->V,-1.0,1.0,nv,g);
264:           BVScaleColumn(eps->V,nv,1.0/gamma);
265:         }
266:         /* Prepare the Rayleigh quotient for restart */
267:         DSGetArray(eps->ds,DS_MAT_A,&S);
268:         DSGetArray(eps->ds,DS_MAT_Q,&Q);
269:         for (i=k;i<k+l;i++) {
270:           S[k+l+i*ld] = Q[nv-1+i*ld]*beta*gamma;
271:         }
272:         DSRestoreArray(eps->ds,DS_MAT_A,&S);
273:         DSRestoreArray(eps->ds,DS_MAT_Q,&Q);
274:       }
275:     }
276:     /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
277:     DSGetMat(eps->ds,DS_MAT_Q,&U);
278:     BVMultInPlace(eps->V,U,eps->nconv,k+l);
279:     MatDestroy(&U);

281:     if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
282:       BVCopyColumn(eps->V,nv,k+l);
283:     }
284:     eps->nconv = k;
285:     EPSMonitor(eps,eps->its,nconv,eps->eigr,eps->eigi,eps->errest,nv);
286:   }

288:   if (harmonic) { PetscFree(g); }
289:   /* truncate Schur decomposition and change the state to raw so that
290:      DSVectors() computes eigenvectors from scratch */
291:   DSSetDimensions(eps->ds,eps->nconv,0,0,0);
292:   DSSetState(eps->ds,DS_STATE_RAW);
293:   return(0);
294: }

298: static PetscErrorCode EPSKrylovSchurSetRestart_KrylovSchur(EPS eps,PetscReal keep)
299: {
300:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

303:   if (keep==PETSC_DEFAULT) ctx->keep = 0.5;
304:   else {
305:     if (keep<0.1 || keep>0.9) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The keep argument must be in the range [0.1,0.9]");
306:     ctx->keep = keep;
307:   }
308:   return(0);
309: }

313: /*@
314:    EPSKrylovSchurSetRestart - Sets the restart parameter for the Krylov-Schur
315:    method, in particular the proportion of basis vectors that must be kept
316:    after restart.

318:    Logically Collective on EPS

320:    Input Parameters:
321: +  eps - the eigenproblem solver context
322: -  keep - the number of vectors to be kept at restart

324:    Options Database Key:
325: .  -eps_krylovschur_restart - Sets the restart parameter

327:    Notes:
328:    Allowed values are in the range [0.1,0.9]. The default is 0.5.

330:    Level: advanced

332: .seealso: EPSKrylovSchurGetRestart()
333: @*/
334: PetscErrorCode EPSKrylovSchurSetRestart(EPS eps,PetscReal keep)
335: {

341:   PetscTryMethod(eps,"EPSKrylovSchurSetRestart_C",(EPS,PetscReal),(eps,keep));
342:   return(0);
343: }

347: static PetscErrorCode EPSKrylovSchurGetRestart_KrylovSchur(EPS eps,PetscReal *keep)
348: {
349:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

352:   *keep = ctx->keep;
353:   return(0);
354: }

358: /*@
359:    EPSKrylovSchurGetRestart - Gets the restart parameter used in the
360:    Krylov-Schur method.

362:    Not Collective

364:    Input Parameter:
365: .  eps - the eigenproblem solver context

367:    Output Parameter:
368: .  keep - the restart parameter

370:    Level: advanced

372: .seealso: EPSKrylovSchurSetRestart()
373: @*/
374: PetscErrorCode EPSKrylovSchurGetRestart(EPS eps,PetscReal *keep)
375: {

381:   PetscUseMethod(eps,"EPSKrylovSchurGetRestart_C",(EPS,PetscReal*),(eps,keep));
382:   return(0);
383: }

387: static PetscErrorCode EPSKrylovSchurSetLocking_KrylovSchur(EPS eps,PetscBool lock)
388: {
389:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

392:   ctx->lock = lock;
393:   return(0);
394: }

398: /*@
399:    EPSKrylovSchurSetLocking - Choose between locking and non-locking variants of
400:    the Krylov-Schur method.

402:    Logically Collective on EPS

404:    Input Parameters:
405: +  eps  - the eigenproblem solver context
406: -  lock - true if the locking variant must be selected

408:    Options Database Key:
409: .  -eps_krylovschur_locking - Sets the locking flag

411:    Notes:
412:    The default is to lock converged eigenpairs when the method restarts.
413:    This behaviour can be changed so that all directions are kept in the
414:    working subspace even if already converged to working accuracy (the
415:    non-locking variant).

417:    Level: advanced

419: .seealso: EPSKrylovSchurGetLocking()
420: @*/
421: PetscErrorCode EPSKrylovSchurSetLocking(EPS eps,PetscBool lock)
422: {

428:   PetscTryMethod(eps,"EPSKrylovSchurSetLocking_C",(EPS,PetscBool),(eps,lock));
429:   return(0);
430: }

434: static PetscErrorCode EPSKrylovSchurGetLocking_KrylovSchur(EPS eps,PetscBool *lock)
435: {
436:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

439:   *lock = ctx->lock;
440:   return(0);
441: }

445: /*@
446:    EPSKrylovSchurGetLocking - Gets the locking flag used in the Krylov-Schur
447:    method.

449:    Not Collective

451:    Input Parameter:
452: .  eps - the eigenproblem solver context

454:    Output Parameter:
455: .  lock - the locking flag

457:    Level: advanced

459: .seealso: EPSKrylovSchurSetLocking()
460: @*/
461: PetscErrorCode EPSKrylovSchurGetLocking(EPS eps,PetscBool *lock)
462: {

468:   PetscUseMethod(eps,"EPSKrylovSchurGetLocking_C",(EPS,PetscBool*),(eps,lock));
469:   return(0);
470: }

474: static PetscErrorCode EPSKrylovSchurSetPartitions_KrylovSchur(EPS eps,PetscInt npart)
475: {
476:   PetscErrorCode  ierr;
477:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
478:   PetscMPIInt     size;

481:   if (ctx->npart!=npart) {
482:     if (ctx->commset) { PetscSubcommDestroy(&ctx->subc); }
483:     if (ctx->eps) { EPSDestroy(&ctx->eps); }
484:   } 
485:   if (npart == PETSC_DEFAULT || npart == PETSC_DECIDE) {
486:     ctx->npart = 1;
487:   } else {
488:     MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size);
489:     if (npart<1 || npart>size) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of npart");
490:     ctx->npart = npart;
491:   }
492:   eps->state = EPS_STATE_INITIAL;
493:   return(0);
494: }

498: /*@
499:    EPSKrylovSchurSetPartitions - Sets the number of partitions for the
500:    case of doing spectrum slicing for a computational interval with the
501:    communicator split in several sub-communicators.

503:    Logically Collective on EPS

505:    Input Parameters:
506: +  eps   - the eigenproblem solver context
507: -  npart - number of partitions

509:    Options Database Key:
510: .  -eps_krylovschur_partitions <npart> - Sets the number of partitions

512:    Notes:
513:    By default, npart=1 so all processes in the communicator participate in
514:    the processing of the whole interval. If npart>1 then the interval is
515:    divided into npart subintervals, each of them being processed by a
516:    subset of processes.

518:    The interval is split proportionally unless the separation points are
519:    specified with EPSKrylovSchurSetSubintervals().

521:    Level: advanced

523: .seealso: EPSKrylovSchurSetSubintervals(), EPSSetInterval()
524: @*/
525: PetscErrorCode EPSKrylovSchurSetPartitions(EPS eps,PetscInt npart)
526: {

532:   PetscTryMethod(eps,"EPSKrylovSchurSetPartitions_C",(EPS,PetscInt),(eps,npart));
533:   return(0);
534: }

538: static PetscErrorCode EPSKrylovSchurGetPartitions_KrylovSchur(EPS eps,PetscInt *npart)
539: {
540:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

543:   *npart  = ctx->npart;
544:   return(0);
545: }

549: /*@
550:    EPSKrylovSchurGetPartitions - Gets the number of partitions of the
551:    communicator in case of spectrum slicing.

553:    Not Collective

555:    Input Parameter:
556: .  eps - the eigenproblem solver context

558:    Output Parameter:
559: .  npart - number of partitions

561:    Level: advanced

563: .seealso: EPSKrylovSchurSetPartitions()
564: @*/
565: PetscErrorCode EPSKrylovSchurGetPartitions(EPS eps,PetscInt *npart)
566: {

572:   PetscUseMethod(eps,"EPSKrylovSchurGetPartitions_C",(EPS,PetscInt*),(eps,npart));
573:   return(0);
574: }

578: static PetscErrorCode EPSKrylovSchurSetDetectZeros_KrylovSchur(EPS eps,PetscBool detect)
579: {
580:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

583:   ctx->detect = detect;
584:   eps->state  = EPS_STATE_INITIAL;
585:   return(0);
586: }

590: /*@
591:    EPSKrylovSchurSetDetectZeros - Sets a flag to enforce detection of
592:    zeros during the factorizations throughout the spectrum slicing computation.

594:    Logically Collective on EPS

596:    Input Parameters:
597: +  eps    - the eigenproblem solver context
598: -  detect - check for zeros

600:    Options Database Key:
601: .  -eps_krylovschur_detect_zeros - Check for zeros; this takes an optional
602:    bool value (0/1/no/yes/true/false)

604:    Notes:
605:    A zero in the factorization indicates that a shift coincides with an eigenvalue.

607:    This flag is turned off by default, and may be necessary in some cases,
608:    especially when several partitions are being used. This feature currently
609:    requires an external package for factorizations with support for zero
610:    detection, e.g. MUMPS.

612:    Level: advanced

614: .seealso: EPSKrylovSchurSetPartitions(), EPSSetInterval()
615: @*/
616: PetscErrorCode EPSKrylovSchurSetDetectZeros(EPS eps,PetscBool detect)
617: {

623:   PetscTryMethod(eps,"EPSKrylovSchurSetDetectZeros_C",(EPS,PetscBool),(eps,detect));
624:   return(0);
625: }

629: static PetscErrorCode EPSKrylovSchurGetDetectZeros_KrylovSchur(EPS eps,PetscBool *detect)
630: {
631:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

634:   *detect = ctx->detect;
635:   return(0);
636: }

640: /*@
641:    EPSKrylovSchurGetDetectZeros - Gets the flag that enforces zero detection
642:    in spectrum slicing.

644:    Not Collective

646:    Input Parameter:
647: .  eps - the eigenproblem solver context

649:    Output Parameter:
650: .  detect - whether zeros detection is enforced during factorizations

652:    Level: advanced

654: .seealso: EPSKrylovSchurSetDetectZeros()
655: @*/
656: PetscErrorCode EPSKrylovSchurGetDetectZeros(EPS eps,PetscBool *detect)
657: {

663:   PetscUseMethod(eps,"EPSKrylovSchurGetDetectZeros_C",(EPS,PetscBool*),(eps,detect));
664:   return(0);
665: }

669: static PetscErrorCode EPSKrylovSchurSetDimensions_KrylovSchur(EPS eps,PetscInt nev,PetscInt ncv,PetscInt mpd)
670: {
671:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

674:   if (nev<1) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of nev. Must be > 0");
675:   ctx->nev = nev;
676:   if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
677:     ctx->ncv = 0;
678:   } else {
679:     if (ncv<1) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
680:     ctx->ncv = ncv;
681:   }
682:   if (mpd == PETSC_DECIDE || mpd == PETSC_DEFAULT) {
683:     ctx->mpd = 0;
684:   } else {
685:     if (mpd<1) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of mpd. Must be > 0");
686:     ctx->mpd = mpd;
687:   }
688:   eps->state = EPS_STATE_INITIAL;
689:   return(0);
690: }

694: /*@
695:    EPSKrylovSchurSetDimensions - Sets the dimensions used for each subsolve
696:    step in case of doing spectrum slicing for a computational interval.
697:    The meaning of the parameters is the same as in EPSSetDimensions().

699:    Logically Collective on EPS

701:    Input Parameters:
702: +  eps - the eigenproblem solver context
703: .  nev - number of eigenvalues to compute
704: .  ncv - the maximum dimension of the subspace to be used by the subsolve
705: -  mpd - the maximum dimension allowed for the projected problem

707:    Options Database Key:
708: +  -eps_krylovschur_nev <nev> - Sets the number of eigenvalues
709: .  -eps_krylovschur_ncv <ncv> - Sets the dimension of the subspace
710: -  -eps_krylovschur_mpd <mpd> - Sets the maximum projected dimension

712:    Level: advanced

714: .seealso: EPSKrylovSchurGetDimensions(), EPSSetDimensions(), EPSSetInterval()
715: @*/
716: PetscErrorCode EPSKrylovSchurSetDimensions(EPS eps,PetscInt nev,PetscInt ncv,PetscInt mpd)
717: {

725:   PetscTryMethod(eps,"EPSKrylovSchurSetDimensions_C",(EPS,PetscInt,PetscInt,PetscInt),(eps,nev,ncv,mpd));
726:   return(0);
727: }

731: static PetscErrorCode EPSKrylovSchurGetDimensions_KrylovSchur(EPS eps,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
732: {
733:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

736:   if (nev) *nev = ctx->nev;
737:   if (ncv) *ncv = ctx->ncv;
738:   if (mpd) *mpd = ctx->mpd;
739:   return(0);
740: }

744: /*@
745:    EPSKrylovSchurGetDimensions - Gets the dimensions used for each subsolve
746:    step in case of doing spectrum slicing for a computational interval.

748:    Not Collective

750:    Input Parameter:
751: .  eps - the eigenproblem solver context

753:    Output Parameters:
754: +  nev - number of eigenvalues to compute
755: .  ncv - the maximum dimension of the subspace to be used by the subsolve
756: -  mpd - the maximum dimension allowed for the projected problem

758:    Level: advanced

760: .seealso: EPSKrylovSchurSetDimensions()
761: @*/
762: PetscErrorCode EPSKrylovSchurGetDimensions(EPS eps,PetscInt *nev,PetscInt *ncv,PetscInt *mpd)
763: {

768:   PetscUseMethod(eps,"EPSKrylovSchurGetDimensions_C",(EPS,PetscInt*,PetscInt*,PetscInt*),(eps,nev,ncv,mpd));
769:   return(0);
770: }

774: static PetscErrorCode EPSKrylovSchurSetSubintervals_KrylovSchur(EPS eps,PetscReal* subint)
775: {
776:   PetscErrorCode  ierr;
777:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
778:   PetscInt        i;

781:   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()");
782:   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");
783:   if (ctx->subintervals) { PetscFree(ctx->subintervals); }
784:   PetscMalloc1(ctx->npart+1,&ctx->subintervals);
785:   for (i=0;i<ctx->npart+1;i++) ctx->subintervals[i] = subint[i];
786:   ctx->subintset = PETSC_TRUE;
787:   eps->state = EPS_STATE_INITIAL;
788:   return(0);
789: }

793: /*@C
794:    EPSKrylovSchurSetSubintervals - Sets the points that delimit the
795:    subintervals to be used in spectrum slicing with several partitions.

797:    Logically Collective on EPS

799:    Input Parameters:
800: +  eps    - the eigenproblem solver context
801: -  subint - array of real values specifying subintervals

803:    Notes:
804:    This function must be called after EPSKrylovSchurSetPartitions(). For npart
805:    partitions, the argument subint must contain npart+1 real values sorted in
806:    ascending order: subint_0, subint_1, ..., subint_npart, where the first
807:    and last values must coincide with the interval endpoints set with
808:    EPSSetInterval().

810:    The subintervals are then defined by two consecutive points: [subint_0,subint_1],
811:    [subint_1,subint_2], and so on.

813:    Level: advanced

815: .seealso: EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubintervals(), EPSSetInterval()
816: @*/
817: PetscErrorCode EPSKrylovSchurSetSubintervals(EPS eps,PetscReal *subint)
818: {

823:   PetscTryMethod(eps,"EPSKrylovSchurSetSubintervals_C",(EPS,PetscReal*),(eps,subint));
824:   return(0);
825: }

829: static PetscErrorCode EPSKrylovSchurGetSubintervals_KrylovSchur(EPS eps,PetscReal **subint)
830: {
831:   PetscErrorCode  ierr;
832:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
833:   PetscInt        i;

836:   if (!ctx->subintset) {
837:     if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
838:     if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
839:   }
840:   PetscMalloc1(ctx->npart+1,subint);
841:   for (i=0;i<=ctx->npart;i++) (*subint)[i] = ctx->subintervals[i];
842:   return(0);
843: }

847: /*@C
848:    EPSKrylovSchurGetSubintervals - Returns the points that delimit the
849:    subintervals used in spectrum slicing with several partitions.

851:    Logically Collective on EPS

853:    Input Parameter:
854: .  eps    - the eigenproblem solver context

856:    Output Parameter:
857: .  subint - array of real values specifying subintervals

859:    Notes:
860:    If the user passed values with EPSKrylovSchurSetSubintervals(), then the
861:    same values are returned. Otherwise, the values computed internally are
862:    obtained.

864:    This function is only available for spectrum slicing runs.

866:    The returned array has length npart+1 (see EPSKrylovSchurGetPartitions())
867:    and should be freed by the user.

869:    Level: advanced

871: .seealso: EPSKrylovSchurSetSubintervals(), EPSKrylovSchurGetPartitions(), EPSSetInterval()
872: @*/
873: PetscErrorCode EPSKrylovSchurGetSubintervals(EPS eps,PetscReal** subint)
874: {

880:   PetscUseMethod(eps,"EPSKrylovSchurGetSubintervals_C",(EPS,PetscReal**),(eps,subint));
881:   return(0);
882: }

886: static PetscErrorCode EPSKrylovSchurGetInertias_KrylovSchur(EPS eps,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
887: {
888:   PetscErrorCode  ierr;
889:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
890:   PetscInt        i;
891:   EPS_SR          sr = ctx->sr;

894:   if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
895:   if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
896:   switch (eps->state) {
897:   case EPS_STATE_INITIAL:
898:     break;
899:   case EPS_STATE_SETUP:
900:     *n = ctx->npart+1;
901:     PetscMalloc1(*n,shifts);
902:     PetscMalloc1(*n,inertias);
903:     (*shifts)[0] = eps->inta;
904:     (*inertias)[0] = (sr->dir==1)?sr->inertia0:sr->inertia1;
905:     if (ctx->npart==1) {
906:       (*shifts)[1] = eps->intb;
907:       (*inertias)[1] = (sr->dir==1)?sr->inertia1:sr->inertia0;
908:     } else {
909:       for (i=1;i<*n;i++) {
910:         (*shifts)[i] = ctx->subintervals[i];
911:         (*inertias)[i] = (*inertias)[i-1]+ctx->nconv_loc[i-1];
912:       }
913:     }
914:     break;
915:   case EPS_STATE_SOLVED:
916:   case EPS_STATE_EIGENVECTORS:
917:     *n = ctx->nshifts;
918:     PetscMalloc1(*n,shifts);
919:     PetscMalloc1(*n,inertias);
920:     for (i=0;i<*n;i++) {
921:       (*shifts)[i] = ctx->shifts[i];
922:       (*inertias)[i] = ctx->inertias[i];
923:     }
924:     break;
925:   }
926:   return(0);
927: }

931: /*@C
932:    EPSKrylovSchurGetInertias - Gets the values of the shifts and their
933:    corresponding inertias in case of doing spectrum slicing for a
934:    computational interval.

936:    Not Collective

938:    Input Parameter:
939: .  eps - the eigenproblem solver context

941:    Output Parameters:
942: +  n        - number of shifts, including the endpoints of the interval
943: .  shifts   - the values of the shifts used internally in the solver
944: -  inertias - the values of the inertia in each shift

946:    Notes:
947:    If called after EPSSolve(), all shifts used internally by the solver are
948:    returned (including both endpoints and any intermediate ones). If called
949:    before EPSSolve() and after EPSSetUp() then only the information of the
950:    endpoints of subintervals is available.

952:    This function is only available for spectrum slicing runs.

954:    The returned arrays should be freed by the user.

956:    Level: advanced

958: .seealso: EPSSetInterval(), EPSKrylovSchurSetSubintervals()
959: @*/
960: PetscErrorCode EPSKrylovSchurGetInertias(EPS eps,PetscInt *n,PetscReal **shifts,PetscInt **inertias)
961: {

967:   PetscUseMethod(eps,"EPSKrylovSchurGetInertias_C",(EPS,PetscInt*,PetscReal**,PetscInt**),(eps,n,shifts,inertias));
968:   return(0);
969: }

973: static PetscErrorCode EPSKrylovSchurGetSubcommInfo_KrylovSchur(EPS eps,PetscInt *k,PetscInt *n,Vec *v)
974: {
975:   PetscErrorCode  ierr;
976:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
977:   EPS_SR          sr = ((EPS_KRYLOVSCHUR*)ctx->eps->data)->sr;

980:   if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
981:   if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
982:   if (k) *k = (ctx->npart==1)? 0: ctx->subc->color;
983:   if (n) *n = sr->numEigs;
984:   if (v) {
985:     BVCreateVec(sr->V,v);
986:   }
987:   return(0);
988: }

992: /*@C
993:    EPSKrylovSchurGetSubcommInfo - Gets information related to the case of
994:    doing spectrum slicing for a computational interval with multiple
995:    communicators.

997:    Collective on the subcommunicator (if v is given)

999:    Input Parameter:
1000: .  eps - the eigenproblem solver context

1002:    Output Parameters:
1003: +  k - index of the subinterval for the calling process
1004: .  n - number of eigenvalues found in the k-th subinterval
1005: -  v - a vector owned by processes in the subcommunicator with dimensions
1006:        compatible for locally computed eigenvectors (or NULL)

1008:    Notes:
1009:    This function is only available for spectrum slicing runs.

1011:    The returned Vec should be destroyed by the user.

1013:    Level: advanced

1015: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommPairs()
1016: @*/
1017: PetscErrorCode EPSKrylovSchurGetSubcommInfo(EPS eps,PetscInt *k,PetscInt *n,Vec *v)
1018: {

1023:   PetscUseMethod(eps,"EPSKrylovSchurGetSubcommInfo_C",(EPS,PetscInt*,PetscInt*,Vec*),(eps,k,n,v));
1024:   return(0);
1025: }

1029: static PetscErrorCode EPSKrylovSchurGetSubcommPairs_KrylovSchur(EPS eps,PetscInt i,PetscScalar *eig,Vec v)
1030: {
1031:   PetscErrorCode  ierr;
1032:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1033:   EPS_SR          sr = ((EPS_KRYLOVSCHUR*)ctx->eps->data)->sr;

1036:   EPSCheckSolved(eps,1);
1037:   if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1038:   if (i<0 || i>=sr->numEigs) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
1039:   if (eig) *eig = sr->eigr[sr->perm[i]];
1040:   BVCopyVec(sr->V,sr->perm[i],v);
1041:   return(0);
1042: }

1046: /*@C
1047:    EPSKrylovSchurGetSubcommPairs - Gets the i-th eigenpair stored
1048:    internally in the subcommunicator to which the calling process belongs.

1050:    Collective on the subcommunicator (if v is given)

1052:    Input Parameter:
1053: +  eps - the eigenproblem solver context
1054: -  i   - index of the solution

1056:    Output Parameters:
1057: +  eig - the eigenvalue
1058: -  v   - the eigenvector

1060:    Notes:
1061:    It is allowed to pass NULL for v if the eigenvector is not required.
1062:    Otherwise, the caller must provide a valid Vec objects, i.e.,
1063:    it must be created by the calling program with EPSKrylovSchurGetSubcommInfo().

1065:    The index i should be a value between 0 and n-1, where n is the number of
1066:    vectors in the local subinterval, see EPSKrylovSchurGetSubcommInfo().

1068:    Level: advanced

1070: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommInfo(), EPSKrylovSchurGetSubcommMats()
1071: @*/
1072: PetscErrorCode EPSKrylovSchurGetSubcommPairs(EPS eps,PetscInt i,PetscScalar *eig,Vec v)
1073: {

1079:   PetscUseMethod(eps,"EPSKrylovSchurGetSubcommPairs_C",(EPS,PetscInt,PetscScalar*,Vec),(eps,i,eig,v));
1080:   return(0);
1081: }

1085: static PetscErrorCode EPSKrylovSchurGetSubcommMats_KrylovSchur(EPS eps,Mat *A,Mat *B)
1086: {
1087:   PetscErrorCode  ierr;
1088:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;

1091:   if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1092:   if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
1093:   EPSGetOperators(ctx->eps,A,B);
1094:   return(0);
1095: }

1099: /*@C
1100:    EPSKrylovSchurGetSubcommMats - Gets the eigenproblem matrices stored
1101:    internally in the subcommunicator to which the calling process belongs.

1103:    Collective on the subcommunicator

1105:    Input Parameter:
1106: .  eps - the eigenproblem solver context

1108:    Output Parameters:
1109: +  A  - the matrix associated with the eigensystem
1110: -  B  - the second matrix in the case of generalized eigenproblems

1112:    Notes:
1113:    This is the analog of EPSGetOperators(), but returns the matrices distributed
1114:    differently (in the subcommunicator rather than in the parent communicator).

1116:    These matrices should not be modified by the user.

1118:    Level: advanced

1120: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommInfo()
1121: @*/
1122: PetscErrorCode EPSKrylovSchurGetSubcommMats(EPS eps,Mat *A,Mat *B)
1123: {

1128:   PetscTryMethod(eps,"EPSKrylovSchurGetSubcommMats_C",(EPS,Mat*,Mat*),(eps,A,B));
1129:   return(0);
1130: }

1134: static PetscErrorCode EPSKrylovSchurUpdateSubcommMats_KrylovSchur(EPS eps,PetscScalar a,PetscScalar ap,Mat Au,PetscScalar b,PetscScalar bp, Mat Bu,MatStructure str,PetscBool globalup)
1135: {
1136:   PetscErrorCode  ierr;
1137:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data,*subctx;
1138:   Mat             A,B=NULL,Ag,Bg=NULL;
1139:   PetscBool       reuse=PETSC_TRUE;
1140:    
1142:   if (!ctx->sr) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Only available in interval computations, see EPSSetInterval()");
1143:   if (!eps->state) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"Must call EPSSetUp() first");
1144:   EPSGetOperators(eps,&Ag,&Bg);
1145:   EPSGetOperators(ctx->eps,&A,&B);
1146:   
1147:   MatScale(A,a);
1148:   if (Au) {
1149:     MatAXPY(A,ap,Au,str);
1150:   }
1151:   if (B) MatScale(B,b);
1152:   if (Bu) {
1153:     MatAXPY(B,bp,Bu,str);
1154:   }
1155:   EPSSetOperators(ctx->eps,A,B);

1157:   /* Update stored matrix state */
1158:   subctx = (EPS_KRYLOVSCHUR*)ctx->eps->data;
1159:   PetscObjectStateGet((PetscObject)A,&subctx->Astate);
1160:   if (B) { PetscObjectStateGet((PetscObject)B,&subctx->Bstate); }

1162:   /* Update matrices in the parent communicator if requested by user */
1163:   if (globalup) {
1164:     if (ctx->npart>1) {
1165:       if (!ctx->isrow) {
1166:         MatGetOwnershipIS(Ag,&ctx->isrow,&ctx->iscol);
1167:         reuse = PETSC_FALSE;
1168:       }
1169:       if (str==DIFFERENT_NONZERO_PATTERN) reuse = PETSC_FALSE;
1170:       if (ctx->submata && !reuse) {
1171:         MatDestroyMatrices(1,&ctx->submata);
1172:       }
1173:       MatGetSubMatrices(A,1,&ctx->isrow,&ctx->iscol,(reuse)?MAT_REUSE_MATRIX:MAT_INITIAL_MATRIX,&ctx->submata);
1174:       MatCreateMPIMatConcatenateSeqMat(((PetscObject)Ag)->comm,ctx->submata[0],PETSC_DECIDE,MAT_REUSE_MATRIX,&Ag);
1175:       if (B) {
1176:         if (ctx->submatb && !reuse) {
1177:           MatDestroyMatrices(1,&ctx->submatb);
1178:         }
1179:         MatGetSubMatrices(B,1,&ctx->isrow,&ctx->iscol,(reuse)?MAT_REUSE_MATRIX:MAT_INITIAL_MATRIX,&ctx->submatb);
1180:         MatCreateMPIMatConcatenateSeqMat(((PetscObject)Bg)->comm,ctx->submatb[0],PETSC_DECIDE,MAT_REUSE_MATRIX,&Bg);
1181:       }
1182:     }
1183:     PetscObjectStateGet((PetscObject)Ag,&ctx->Astate);
1184:     if (Bg) { PetscObjectStateGet((PetscObject)Bg,&ctx->Bstate); }
1185:   }
1186:   EPSSetOperators(eps,Ag,Bg);
1187:   return(0);
1188: }

1192: /*@C
1193:    EPSKrylovSchurUpdateSubcommMats - Update the eigenproblem matrices stored
1194:    internally in the subcommunicator to which the calling process belongs.

1196:    Collective on EPS

1198:    Input Parameters:
1199: +  eps - the eigenproblem solver context
1200: .  s   - scalar that multiplies the existing A matrix
1201: .  a   - scalar used in the axpy operation on A
1202: .  Au  - matrix used in the axpy operation on A
1203: .  t   - scalar that multiplies the existing B matrix
1204: .  b   - scalar used in the axpy operation on B
1205: .  Bu  - matrix used in the axpy operation on B
1206: .  str - structure flag
1207: -  globalup - flag indicating if global matrices must be updated

1209:    Notes:
1210:    This function modifies the eigenproblem matrices at the subcommunicator level,
1211:    and optionally updates the global matrices in the parent communicator. The updates
1212:    are expressed as A <-- s*A + a*Au,  B <-- t*B + b*Bu.

1214:    It is possible to update one of the matrices, or both.

1216:    The matrices Au and Bu must be equal in all subcommunicators.

1218:    The str flag is passed to the MatAXPY() operations to perform the updates.

1220:    If globalup is true, communication is carried out to reconstruct the updated
1221:    matrices in the parent communicator. The user must be warned that if global
1222:    matrices are not in sync with subcommunicator matrices, the errors computed
1223:    by EPSComputeError() will be wrong even if the computed solution is correct
1224:    (the synchronization may be done only once at the end).

1226:    Level: advanced

1228: .seealso: EPSSetInterval(), EPSKrylovSchurSetPartitions(), EPSKrylovSchurGetSubcommMats()
1229: @*/
1230: PetscErrorCode EPSKrylovSchurUpdateSubcommMats(EPS eps,PetscScalar s,PetscScalar a,Mat Au,PetscScalar t,PetscScalar b, Mat Bu,MatStructure str,PetscBool globalup)
1231: {

1244:   PetscTryMethod(eps,"EPSKrylovSchurUpdateSubcommMats_C",(EPS,PetscScalar,PetscScalar,Mat,PetscScalar,PetscScalar,Mat,MatStructure,PetscBool),(eps,s,a,Au,t,b,Bu,str,globalup));
1245:   return(0);
1246: }

1250: PetscErrorCode EPSSetFromOptions_KrylovSchur(PetscOptionItems *PetscOptionsObject,EPS eps)
1251: {
1252:   PetscErrorCode  ierr;
1253:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1254:   PetscBool       flg,lock,b,f1,f2,f3;
1255:   PetscReal       keep;
1256:   PetscInt        i,j,k;

1259:   PetscOptionsHead(PetscOptionsObject,"EPS Krylov-Schur Options");
1260:   PetscOptionsReal("-eps_krylovschur_restart","Proportion of vectors kept after restart","EPSKrylovSchurSetRestart",0.5,&keep,&flg);
1261:   if (flg) {
1262:     EPSKrylovSchurSetRestart(eps,keep);
1263:   }
1264:   PetscOptionsBool("-eps_krylovschur_locking","Choose between locking and non-locking variants","EPSKrylovSchurSetLocking",PETSC_TRUE,&lock,&flg);
1265:   if (flg) {
1266:     EPSKrylovSchurSetLocking(eps,lock);
1267:   }
1268:   i = ctx->npart;
1269:   PetscOptionsInt("-eps_krylovschur_partitions","Number of partitions of the communicator for spectrum slicing","EPSKrylovSchurSetPartitions",ctx->npart,&i,&flg);
1270:   if (flg) {
1271:     EPSKrylovSchurSetPartitions(eps,i);
1272:   }
1273:   b = ctx->detect;
1274:   PetscOptionsBool("-eps_krylovschur_detect_zeros","Check zeros during factorizations at subinterval boundaries","EPSKrylovSchurSetDetectZeros",ctx->detect,&b,&flg);
1275:   if (flg) {
1276:     EPSKrylovSchurSetDetectZeros(eps,b);
1277:   }
1278:   i = 1;
1279:   j = k = PETSC_DECIDE;
1280:   PetscOptionsInt("-eps_krylovschur_nev","Number of eigenvalues to compute in each subsolve (only for spectrum slicing)","EPSKrylovSchurSetDimensions",40,&i,&f1);
1281:   PetscOptionsInt("-eps_krylovschur_ncv","Number of basis vectors in each subsolve (only for spectrum slicing)","EPSKrylovSchurSetDimensions",80,&j,&f2);
1282:   PetscOptionsInt("-eps_krylovschur_mpd","Maximum dimension of projected problem in each subsolve (only for spectrum slicing)","EPSKrylovSchurSetDimensions",80,&k,&f3);
1283:   if (f1 || f2 || f3) {
1284:     EPSKrylovSchurSetDimensions(eps,i,j,k);
1285:   }
1286:   PetscOptionsTail();
1287:   return(0);
1288: }

1292: PetscErrorCode EPSView_KrylovSchur(EPS eps,PetscViewer viewer)
1293: {
1294:   PetscErrorCode  ierr;
1295:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
1296:   PetscBool       isascii;

1299:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
1300:   if (isascii) {
1301:     PetscViewerASCIIPrintf(viewer,"  Krylov-Schur: %d%% of basis vectors kept after restart\n",(int)(100*ctx->keep));
1302:     PetscViewerASCIIPrintf(viewer,"  Krylov-Schur: using the %slocking variant\n",ctx->lock?"":"non-");
1303:     if (eps->which==EPS_ALL) {
1304:       PetscViewerASCIIPrintf(viewer,"  Krylov-Schur: doing spectrum slicing with nev=%D, ncv=%D, mpd=%D\n",ctx->nev,ctx->ncv,ctx->mpd);
1305:       if (ctx->npart>1) {
1306:         PetscViewerASCIIPrintf(viewer,"  Krylov-Schur: multi-communicator spectrum slicing with %D partitions\n",ctx->npart);
1307:         if (ctx->detect) { PetscViewerASCIIPrintf(viewer,"  Krylov-Schur: detecting zeros when factorizing at subinterval boundaries\n"); }
1308:       }
1309:     }
1310:   }
1311:   return(0);
1312: }

1316: PetscErrorCode EPSDestroy_KrylovSchur(EPS eps)
1317: {

1321:   PetscFree(eps->data);
1322:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetRestart_C",NULL);
1323:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetRestart_C",NULL);
1324:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetLocking_C",NULL);
1325:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetLocking_C",NULL);
1326:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetPartitions_C",NULL);
1327:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetPartitions_C",NULL);
1328:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDetectZeros_C",NULL);
1329:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDetectZeros_C",NULL);
1330:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDimensions_C",NULL);
1331:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDimensions_C",NULL);
1332:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetSubintervals_C",NULL);
1333:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubintervals_C",NULL);
1334:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetInertias_C",NULL);
1335:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommInfo_C",NULL);
1336:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommPairs_C",NULL);
1337:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommMats_C",NULL);
1338:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurUpdateSubcommMats_C",NULL);
1339:   return(0);
1340: }

1344: PetscErrorCode EPSReset_KrylovSchur(EPS eps)
1345: {
1348:   if (eps->which==EPS_ALL) {
1349:     EPSReset_KrylovSchur_Slice(eps);
1350:   }
1351:   return(0);
1352: }

1356: PETSC_EXTERN PetscErrorCode EPSCreate_KrylovSchur(EPS eps)
1357: {
1358:   EPS_KRYLOVSCHUR *ctx;
1359:   PetscErrorCode  ierr;

1362:   PetscNewLog(eps,&ctx);
1363:   eps->data   = (void*)ctx;
1364:   ctx->lock   = PETSC_TRUE;
1365:   ctx->nev    = 1;
1366:   ctx->npart  = 1;
1367:   ctx->detect = PETSC_FALSE;
1368:   ctx->global = PETSC_TRUE;

1370:   eps->ops->setup          = EPSSetUp_KrylovSchur;
1371:   eps->ops->setfromoptions = EPSSetFromOptions_KrylovSchur;
1372:   eps->ops->destroy        = EPSDestroy_KrylovSchur;
1373:   eps->ops->reset          = EPSReset_KrylovSchur;
1374:   eps->ops->view           = EPSView_KrylovSchur;
1375:   eps->ops->backtransform  = EPSBackTransform_Default;
1376:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetRestart_C",EPSKrylovSchurSetRestart_KrylovSchur);
1377:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetRestart_C",EPSKrylovSchurGetRestart_KrylovSchur);
1378:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetLocking_C",EPSKrylovSchurSetLocking_KrylovSchur);
1379:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetLocking_C",EPSKrylovSchurGetLocking_KrylovSchur);
1380:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetPartitions_C",EPSKrylovSchurSetPartitions_KrylovSchur);
1381:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetPartitions_C",EPSKrylovSchurGetPartitions_KrylovSchur);
1382:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDetectZeros_C",EPSKrylovSchurSetDetectZeros_KrylovSchur);
1383:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDetectZeros_C",EPSKrylovSchurGetDetectZeros_KrylovSchur);
1384:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetDimensions_C",EPSKrylovSchurSetDimensions_KrylovSchur);
1385:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetDimensions_C",EPSKrylovSchurGetDimensions_KrylovSchur);
1386:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurSetSubintervals_C",EPSKrylovSchurSetSubintervals_KrylovSchur);
1387:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubintervals_C",EPSKrylovSchurGetSubintervals_KrylovSchur);
1388:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetInertias_C",EPSKrylovSchurGetInertias_KrylovSchur);
1389:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommInfo_C",EPSKrylovSchurGetSubcommInfo_KrylovSchur);
1390:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommPairs_C",EPSKrylovSchurGetSubcommPairs_KrylovSchur);
1391:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurGetSubcommMats_C",EPSKrylovSchurGetSubcommMats_KrylovSchur);
1392:   PetscObjectComposeFunction((PetscObject)eps,"EPSKrylovSchurUpdateSubcommMats_C",EPSKrylovSchurUpdateSubcommMats_KrylovSchur);
1393:   return(0);
1394: }