LCOV - code coverage report
Current view: top level - eps/impls/krylov/krylovschur - krylovschur.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 712 780 91.3 %
Date: 2024-11-21 00:34:55 Functions: 50 52 96.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14