LCOV - code coverage report
Current view: top level - eps/impls/davidson - davidson.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 205 217 94.5 %
Date: 2024-04-25 00:29:53 Functions: 14 14 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             :    Skeleton of Davidson solver. Actual solvers are GD and JD.
      12             : 
      13             :    References:
      14             : 
      15             :        [1] E. Romero and J.E. Roman, "A parallel implementation of Davidson
      16             :            methods for large-scale eigenvalue problems in SLEPc", ACM Trans.
      17             :            Math. Software 40(2):13, 2014.
      18             : */
      19             : 
      20             : #include "davidson.h"
      21             : 
      22             : static PetscBool  cited = PETSC_FALSE;
      23             : static const char citation[] =
      24             :   "@Article{slepc-davidson,\n"
      25             :   "   author = \"E. Romero and J. E. Roman\",\n"
      26             :   "   title = \"A parallel implementation of {Davidson} methods for large-scale eigenvalue problems in {SLEPc}\",\n"
      27             :   "   journal = \"{ACM} Trans. Math. Software\",\n"
      28             :   "   volume = \"40\",\n"
      29             :   "   number = \"2\",\n"
      30             :   "   pages = \"13:1--13:29\",\n"
      31             :   "   year = \"2014,\"\n"
      32             :   "   doi = \"https://doi.org/10.1145/2543696\"\n"
      33             :   "}\n";
      34             : 
      35          97 : PetscErrorCode EPSSetUp_XD(EPS eps)
      36             : {
      37          97 :   EPS_DAVIDSON   *data = (EPS_DAVIDSON*)eps->data;
      38          97 :   dvdDashboard   *dvd = &data->ddb;
      39          97 :   dvdBlackboard  b;
      40          97 :   PetscInt       min_size_V,bs,initv,nmat;
      41          97 :   Mat            A,B;
      42          97 :   KSP            ksp;
      43          97 :   PetscBool      ipB,ispositive;
      44          97 :   HarmType_t     harm;
      45          97 :   InitType_t     init;
      46          97 :   PetscScalar    target;
      47             : 
      48          97 :   PetscFunctionBegin;
      49             :   /* Setup EPS options and get the problem specification */
      50          97 :   bs = data->blocksize;
      51          97 :   if (bs <= 0) bs = 1;
      52          97 :   if (eps->ncv!=PETSC_DEFAULT && eps->ncv!=PETSC_DECIDE) {
      53          41 :     PetscCheck(eps->ncv>=eps->nev,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The value of ncv must be at least nev");
      54          56 :   } else if (eps->mpd!=PETSC_DEFAULT && eps->mpd!=PETSC_DECIDE) eps->ncv = eps->mpd + eps->nev + bs;
      55          55 :   else if (eps->n < 10) eps->ncv = eps->n+eps->nev+bs;
      56          55 :   else if (eps->nev < 500) eps->ncv = PetscMax(eps->nev,PetscMin(eps->n-bs,PetscMax(2*eps->nev,eps->nev+15))+bs);
      57           0 :   else eps->ncv = PetscMax(eps->nev,PetscMin(eps->n-bs,eps->nev+500)+bs);
      58          97 :   if (eps->mpd==PETSC_DEFAULT || eps->mpd==PETSC_DECIDE) eps->mpd = PetscMin(eps->n,eps->ncv);
      59          97 :   PetscCheck(eps->mpd<=eps->ncv,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The mpd parameter has to be less than or equal to ncv");
      60          97 :   PetscCheck(eps->mpd>=2,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The mpd parameter has to be greater than 2");
      61          97 :   if (eps->max_it == PETSC_DEFAULT || eps->max_it == PETSC_DECIDE) eps->max_it = PetscMax(100*eps->ncv,2*eps->n);
      62          97 :   if (!eps->which) eps->which = EPS_LARGEST_MAGNITUDE;
      63          97 :   PetscCheck(eps->nev+bs<=eps->ncv,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The value of ncv has to be greater than nev plus blocksize");
      64          97 :   PetscCheck(!eps->trueres,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"-eps_true_residual is disabled in this solver.");
      65          97 :   EPSCheckUnsupported(eps,EPS_FEATURE_REGION | EPS_FEATURE_TWOSIDED);
      66             : 
      67          97 :   if (!data->minv) data->minv = (eps->n && eps->n<10)? 1: PetscMin(PetscMax(bs,6),eps->mpd/2);
      68          97 :   min_size_V = data->minv;
      69          97 :   PetscCheck(min_size_V+bs<=eps->mpd,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The value of minv must be less than mpd minus blocksize");
      70          97 :   if (data->plusk == PETSC_DEFAULT) {
      71          64 :     if (eps->problem_type == EPS_GHIEP || eps->nev+bs>eps->ncv) data->plusk = 0;
      72          62 :     else data->plusk = 1;
      73             :   }
      74         161 :   if (!data->initialsize) data->initialsize = (eps->n && eps->n<10)? 1: 6;
      75          97 :   initv = data->initialsize;
      76          97 :   PetscCheck(eps->mpd>=initv,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The initv parameter has to be less than or equal to mpd");
      77             : 
      78             :   /* Change the default sigma to inf if necessary */
      79          97 :   if (eps->which == EPS_LARGEST_MAGNITUDE || eps->which == EPS_LARGEST_REAL || eps->which == EPS_LARGEST_IMAGINARY) PetscCall(STSetDefaultShift(eps->st,PETSC_MAX_REAL));
      80             : 
      81             :   /* Set up preconditioner */
      82          97 :   PetscCall(STSetUp(eps->st));
      83             : 
      84             :   /* Setup problem specification in dvd */
      85          97 :   PetscCall(STGetNumMatrices(eps->st,&nmat));
      86          97 :   PetscCall(STGetMatrix(eps->st,0,&A));
      87          97 :   if (nmat>1) PetscCall(STGetMatrix(eps->st,1,&B));
      88          97 :   PetscCall(EPSReset_XD(eps));
      89          97 :   PetscCall(PetscMemzero(dvd,sizeof(dvdDashboard)));
      90          97 :   dvd->A = A; dvd->B = eps->isgeneralized? B: NULL;
      91          97 :   ispositive = eps->ispositive;
      92         120 :   dvd->sA = DVD_MAT_IMPLICIT | (eps->ishermitian? DVD_MAT_HERMITIAN: 0) | ((ispositive && !eps->isgeneralized) ? DVD_MAT_POS_DEF: 0);
      93             :   /* Assume -eps_hermitian means hermitian-definite in generalized problems */
      94          97 :   if (!ispositive && !eps->isgeneralized && eps->ishermitian) ispositive = PETSC_TRUE;
      95          97 :   if (!eps->isgeneralized) dvd->sB = DVD_MAT_IMPLICIT | DVD_MAT_HERMITIAN | DVD_MAT_IDENTITY | DVD_MAT_UNITARY | DVD_MAT_POS_DEF;
      96          24 :   else dvd->sB = DVD_MAT_IMPLICIT | (eps->ishermitian? DVD_MAT_HERMITIAN: 0) | (ispositive? DVD_MAT_POS_DEF: 0);
      97          97 :   ipB = (dvd->B && data->ipB && DVD_IS(dvd->sB,DVD_MAT_HERMITIAN))?PETSC_TRUE:PETSC_FALSE;
      98         126 :   dvd->sEP = ((!eps->isgeneralized || (eps->isgeneralized && ipB))? DVD_EP_STD: 0) | (ispositive? DVD_EP_HERMITIAN: 0) | ((eps->problem_type == EPS_GHIEP && ipB) ? DVD_EP_INDEFINITE : 0);
      99          97 :   if (data->ipB && !ipB) data->ipB = PETSC_FALSE;
     100          97 :   dvd->correctXnorm = (dvd->B && (DVD_IS(dvd->sB,DVD_MAT_HERMITIAN)||DVD_IS(dvd->sEP,DVD_EP_INDEFINITE)))?PETSC_TRUE:PETSC_FALSE;
     101          97 :   dvd->nev        = eps->nev;
     102          97 :   dvd->which      = eps->which;
     103          97 :   dvd->withTarget = PETSC_TRUE;
     104          97 :   switch (eps->which) {
     105          15 :     case EPS_TARGET_MAGNITUDE:
     106             :     case EPS_TARGET_IMAGINARY:
     107          15 :       dvd->target[0] = target = eps->target;
     108          15 :       dvd->target[1] = 1.0;
     109          15 :       break;
     110           0 :     case EPS_TARGET_REAL:
     111           0 :       dvd->target[0] = PetscRealPart(target = eps->target);
     112           0 :       dvd->target[1] = 1.0;
     113           0 :       break;
     114          48 :     case EPS_LARGEST_REAL:
     115             :     case EPS_LARGEST_MAGNITUDE:
     116             :     case EPS_LARGEST_IMAGINARY: /* TODO: think about this case */
     117          48 :       dvd->target[0] = 1.0;
     118          48 :       dvd->target[1] = target = 0.0;
     119          48 :       break;
     120          30 :     case EPS_SMALLEST_MAGNITUDE:
     121             :     case EPS_SMALLEST_REAL:
     122             :     case EPS_SMALLEST_IMAGINARY: /* TODO: think about this case */
     123          30 :       dvd->target[0] = target = 0.0;
     124          30 :       dvd->target[1] = 1.0;
     125          30 :       break;
     126           4 :     case EPS_WHICH_USER:
     127           4 :       PetscCall(STGetShift(eps->st,&target));
     128           4 :       dvd->target[0] = target;
     129           4 :       dvd->target[1] = 1.0;
     130           4 :       break;
     131           0 :     case EPS_ALL:
     132           0 :       SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver does not support computing all eigenvalues");
     133           0 :     default:
     134           0 :       SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported value of option 'which'");
     135             :   }
     136          97 :   dvd->tol = SlepcDefaultTol(eps->tol);
     137          97 :   dvd->eps = eps;
     138             : 
     139             :   /* Setup the extraction technique */
     140          97 :   if (!eps->extraction) {
     141          88 :     if (ipB || ispositive) eps->extraction = EPS_RITZ;
     142             :     else {
     143          17 :       switch (eps->which) {
     144           6 :         case EPS_TARGET_REAL:
     145             :         case EPS_TARGET_MAGNITUDE:
     146             :         case EPS_TARGET_IMAGINARY:
     147             :         case EPS_SMALLEST_MAGNITUDE:
     148             :         case EPS_SMALLEST_REAL:
     149             :         case EPS_SMALLEST_IMAGINARY:
     150           6 :           eps->extraction = EPS_HARMONIC;
     151           6 :           break;
     152           8 :         case EPS_LARGEST_REAL:
     153             :         case EPS_LARGEST_MAGNITUDE:
     154             :         case EPS_LARGEST_IMAGINARY:
     155           8 :           eps->extraction = EPS_HARMONIC_LARGEST;
     156           8 :           break;
     157           3 :         default:
     158           3 :           eps->extraction = EPS_RITZ;
     159             :       }
     160             :     }
     161             :   }
     162          97 :   switch (eps->extraction) {
     163             :     case EPS_RITZ:              harm = DVD_HARM_NONE; break;
     164          13 :     case EPS_HARMONIC:          harm = DVD_HARM_RR; break;
     165           0 :     case EPS_HARMONIC_RELATIVE: harm = DVD_HARM_RRR; break;
     166           0 :     case EPS_HARMONIC_RIGHT:    harm = DVD_HARM_REIGS; break;
     167          10 :     case EPS_HARMONIC_LARGEST:  harm = DVD_HARM_LEIGS; break;
     168           0 :     default: SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Unsupported extraction type");
     169             :   }
     170             : 
     171             :   /* Setup the type of starting subspace */
     172          97 :   init = data->krylovstart? DVD_INITV_KRYLOV: DVD_INITV_CLASSIC;
     173             : 
     174             :   /* Preconfigure dvd */
     175          97 :   PetscCall(STGetKSP(eps->st,&ksp));
     176          97 :   PetscCall(dvd_schm_basic_preconf(dvd,&b,eps->mpd,min_size_V,bs,initv,PetscAbs(eps->nini),data->plusk,harm,ksp,init,eps->trackall,data->ipB,data->doubleexp));
     177             : 
     178             :   /* Allocate memory */
     179          97 :   PetscCall(EPSAllocateSolution(eps,0));
     180             : 
     181             :   /* Setup orthogonalization */
     182          97 :   PetscCall(EPS_SetInnerProduct(eps));
     183          97 :   if (!(ipB && dvd->B)) PetscCall(BVSetMatrix(eps->V,NULL,PETSC_FALSE));
     184             : 
     185             :   /* Configure dvd for a basic GD */
     186          97 :   PetscCall(dvd_schm_basic_conf(dvd,&b,eps->mpd,min_size_V,bs,initv,PetscAbs(eps->nini),data->plusk,harm,dvd->withTarget,target,ksp,data->fix,init,eps->trackall,data->ipB,data->dynamic,data->doubleexp));
     187          97 :   PetscFunctionReturn(PETSC_SUCCESS);
     188             : }
     189             : 
     190          97 : PetscErrorCode EPSSolve_XD(EPS eps)
     191             : {
     192          97 :   EPS_DAVIDSON   *data = (EPS_DAVIDSON*)eps->data;
     193          97 :   dvdDashboard   *d = &data->ddb;
     194          97 :   PetscInt       l,k;
     195             : 
     196          97 :   PetscFunctionBegin;
     197          97 :   PetscCall(PetscCitationsRegister(citation,&cited));
     198             :   /* Call the starting routines */
     199          97 :   PetscCall(EPSDavidsonFLCall(d->startList,d));
     200             : 
     201        8926 :   while (eps->reason == EPS_CONVERGED_ITERATING) {
     202             : 
     203             :     /* Initialize V, if it is needed */
     204        8926 :     PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
     205        8926 :     if (PetscUnlikely(l == k)) PetscCall(d->initV(d));
     206             : 
     207             :     /* Find the best approximated eigenpairs in V, X */
     208        8926 :     PetscCall(d->calcPairs(d));
     209             : 
     210             :     /* Test for convergence */
     211        8926 :     PetscCall((*eps->stopping)(eps,eps->its,eps->max_it,eps->nconv,eps->nev,&eps->reason,eps->stoppingctx));
     212        8926 :     if (eps->reason != EPS_CONVERGED_ITERATING) break;
     213             : 
     214             :     /* Expand the subspace */
     215        8829 :     PetscCall(d->updateV(d));
     216             : 
     217             :     /* Monitor progress */
     218        8829 :     eps->nconv = d->nconv;
     219        8829 :     eps->its++;
     220        8829 :     PetscCall(BVGetActiveColumns(d->eps->V,NULL,&k));
     221        8926 :     PetscCall(EPSMonitor(eps,eps->its,eps->nconv+d->npreconv,eps->eigr,eps->eigi,eps->errest,PetscMin(k,eps->nev)));
     222             :   }
     223             : 
     224             :   /* Call the ending routines */
     225          97 :   PetscCall(EPSDavidsonFLCall(d->endList,d));
     226          97 :   PetscFunctionReturn(PETSC_SUCCESS);
     227             : }
     228             : 
     229         169 : PetscErrorCode EPSReset_XD(EPS eps)
     230             : {
     231         169 :   EPS_DAVIDSON   *data = (EPS_DAVIDSON*)eps->data;
     232         169 :   dvdDashboard   *dvd = &data->ddb;
     233             : 
     234         169 :   PetscFunctionBegin;
     235             :   /* Call step destructors and destroys the list */
     236         169 :   PetscCall(EPSDavidsonFLCall(dvd->destroyList,dvd));
     237         169 :   PetscCall(EPSDavidsonFLDestroy(&dvd->destroyList));
     238         169 :   PetscCall(EPSDavidsonFLDestroy(&dvd->startList));
     239         169 :   PetscCall(EPSDavidsonFLDestroy(&dvd->endList));
     240         169 :   PetscFunctionReturn(PETSC_SUCCESS);
     241             : }
     242             : 
     243           4 : PetscErrorCode EPSXDSetKrylovStart_XD(EPS eps,PetscBool krylovstart)
     244             : {
     245           4 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     246             : 
     247           4 :   PetscFunctionBegin;
     248           4 :   data->krylovstart = krylovstart;
     249           4 :   PetscFunctionReturn(PETSC_SUCCESS);
     250             : }
     251             : 
     252          62 : PetscErrorCode EPSXDGetKrylovStart_XD(EPS eps,PetscBool *krylovstart)
     253             : {
     254          62 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     255             : 
     256          62 :   PetscFunctionBegin;
     257          62 :   *krylovstart = data->krylovstart;
     258          62 :   PetscFunctionReturn(PETSC_SUCCESS);
     259             : }
     260             : 
     261           3 : PetscErrorCode EPSXDSetBlockSize_XD(EPS eps,PetscInt blocksize)
     262             : {
     263           3 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     264             : 
     265           3 :   PetscFunctionBegin;
     266           3 :   if (blocksize == PETSC_DEFAULT || blocksize == PETSC_DECIDE) blocksize = 1;
     267           3 :   PetscCheck(blocksize>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid blocksize value, must be >0");
     268           3 :   if (data->blocksize != blocksize) {
     269           3 :     data->blocksize = blocksize;
     270           3 :     eps->state      = EPS_STATE_INITIAL;
     271             :   }
     272           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     273             : }
     274             : 
     275          62 : PetscErrorCode EPSXDGetBlockSize_XD(EPS eps,PetscInt *blocksize)
     276             : {
     277          62 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     278             : 
     279          62 :   PetscFunctionBegin;
     280          62 :   *blocksize = data->blocksize;
     281          62 :   PetscFunctionReturn(PETSC_SUCCESS);
     282             : }
     283             : 
     284           3 : PetscErrorCode EPSXDSetRestart_XD(EPS eps,PetscInt minv,PetscInt plusk)
     285             : {
     286           3 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     287             : 
     288           3 :   PetscFunctionBegin;
     289           3 :   if (minv == PETSC_DEFAULT || minv == PETSC_DECIDE) minv = 0;
     290           3 :   else PetscCheck(minv>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid minv value, must be >0");
     291           3 :   if (plusk == PETSC_DEFAULT || plusk == PETSC_DECIDE) plusk = PETSC_DEFAULT;
     292           2 :   else PetscCheck(plusk>=0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid plusk value, must be >0");
     293           3 :   if (data->minv != minv || data->plusk != plusk) {
     294           3 :     data->minv  = minv;
     295           3 :     data->plusk = plusk;
     296           3 :     eps->state  = EPS_STATE_INITIAL;
     297             :   }
     298           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     299             : }
     300             : 
     301          62 : PetscErrorCode EPSXDGetRestart_XD(EPS eps,PetscInt *minv,PetscInt *plusk)
     302             : {
     303          62 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     304             : 
     305          62 :   PetscFunctionBegin;
     306          62 :   if (minv) *minv = data->minv;
     307          62 :   if (plusk) *plusk = data->plusk;
     308          62 :   PetscFunctionReturn(PETSC_SUCCESS);
     309             : }
     310             : 
     311          61 : PetscErrorCode EPSXDGetInitialSize_XD(EPS eps,PetscInt *initialsize)
     312             : {
     313          61 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     314             : 
     315          61 :   PetscFunctionBegin;
     316          61 :   *initialsize = data->initialsize;
     317          61 :   PetscFunctionReturn(PETSC_SUCCESS);
     318             : }
     319             : 
     320           2 : PetscErrorCode EPSXDSetInitialSize_XD(EPS eps,PetscInt initialsize)
     321             : {
     322           2 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     323             : 
     324           2 :   PetscFunctionBegin;
     325           2 :   if (initialsize == PETSC_DEFAULT || initialsize == PETSC_DECIDE) initialsize = 0;
     326           2 :   else PetscCheck(initialsize>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid initial size value, must be >0");
     327           2 :   if (data->initialsize != initialsize) {
     328           2 :     data->initialsize = initialsize;
     329           2 :     eps->state        = EPS_STATE_INITIAL;
     330             :   }
     331           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     332             : }
     333             : 
     334           2 : PetscErrorCode EPSXDSetBOrth_XD(EPS eps,PetscBool borth)
     335             : {
     336           2 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     337             : 
     338           2 :   PetscFunctionBegin;
     339           2 :   data->ipB = borth;
     340           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     341             : }
     342             : 
     343          62 : PetscErrorCode EPSXDGetBOrth_XD(EPS eps,PetscBool *borth)
     344             : {
     345          62 :   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
     346             : 
     347          62 :   PetscFunctionBegin;
     348          62 :   *borth = data->ipB;
     349          62 :   PetscFunctionReturn(PETSC_SUCCESS);
     350             : }
     351             : 
     352             : /*
     353             :   EPSComputeVectors_XD - Compute eigenvectors from the vectors
     354             :   provided by the eigensolver. This version is intended for solvers
     355             :   that provide Schur vectors from the QZ decomposition. Given the partial
     356             :   Schur decomposition OP*V=V*T, the following steps are performed:
     357             :       1) compute eigenvectors of (S,T): S*Z=T*Z*D
     358             :       2) compute eigenvectors of OP: X=V*Z
     359             :  */
     360          93 : PetscErrorCode EPSComputeVectors_XD(EPS eps)
     361             : {
     362          93 :   Mat            X;
     363          93 :   PetscBool      symm;
     364             : 
     365          93 :   PetscFunctionBegin;
     366          93 :   PetscCall(PetscObjectTypeCompare((PetscObject)eps->ds,DSHEP,&symm));
     367          93 :   if (symm) PetscFunctionReturn(PETSC_SUCCESS);
     368          26 :   PetscCall(DSVectors(eps->ds,DS_MAT_X,NULL,NULL));
     369             : 
     370             :   /* V <- V * X */
     371          26 :   PetscCall(DSGetMat(eps->ds,DS_MAT_X,&X));
     372          26 :   PetscCall(BVSetActiveColumns(eps->V,0,eps->nconv));
     373          26 :   PetscCall(BVMultInPlace(eps->V,X,0,eps->nconv));
     374          26 :   PetscCall(DSRestoreMat(eps->ds,DS_MAT_X,&X));
     375          26 :   PetscFunctionReturn(PETSC_SUCCESS);
     376             : }

Generated by: LCOV version 1.14