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

Generated by: LCOV version 1.14