LCOV - code coverage report
Current view: top level - eps/impls/external/evsl - evsl.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 440 446 98.7 %
Date: 2024-12-18 00:42:09 Functions: 28 28 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             :    This file implements a wrapper to eigensolvers in EVSL.
      12             : */
      13             : 
      14             : #include <slepc/private/epsimpl.h>    /*I "slepceps.h" I*/
      15             : #include <evsl.h>
      16             : 
      17             : #define PetscCallEVSL(func, ...) do {                                                   \
      18             :     PetscStackPushExternal(PetscStringize(func));                                                      \
      19             :     int evsl_ierr_ = func(__VA_ARGS__);                                              \
      20             :     PetscStackPop;                                                                             \
      21             :     PetscCheck(!evsl_ierr_,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling %s: error code %d",PetscStringize(func(__VA_ARGS__)),evsl_ierr_); \
      22             :   } while (0)
      23             : 
      24             : typedef struct {
      25             :   PetscBool         initialized;
      26             :   Mat               A;           /* problem matrix */
      27             :   Vec               x,y;         /* auxiliary vectors */
      28             :   PetscReal         *sli;        /* slice bounds */
      29             :   PetscInt          nev;         /* approximate number of wanted eigenvalues in each slice */
      30             :   PetscLayout       map;         /* used to distribute slices among MPI processes */
      31             :   PetscBool         estimrange;  /* the filter range was not set by the user */
      32             :   /* user parameters */
      33             :   PetscInt          nslices;     /* number of slices */
      34             :   PetscReal         lmin,lmax;   /* numerical range (min and max eigenvalue) */
      35             :   EPSEVSLDOSMethod  dos;         /* DOS method, either KPM or Lanczos */
      36             :   PetscInt          nvec;        /* number of sample vectors used for DOS */
      37             :   PetscInt          deg;         /* polynomial degree used for DOS (KPM only) */
      38             :   PetscInt          steps;       /* number of Lanczos steps used for DOS (Lanczos only) */
      39             :   PetscInt          npoints;     /* number of sample points used for DOS (Lanczos only) */
      40             :   PetscInt          max_deg;     /* maximum degree allowed for the polynomial */
      41             :   PetscReal         thresh;      /* threshold for accepting polynomial */
      42             :   EPSEVSLDamping    damping;     /* type of damping (for polynomial and for DOS-KPM) */
      43             : } EPS_EVSL;
      44             : 
      45      497050 : static void AMatvec_EVSL(double *xa,double *ya,void *data)
      46             : {
      47      497050 :   EPS_EVSL       *ctx = (EPS_EVSL*)data;
      48      497050 :   Vec            x = ctx->x,y = ctx->y;
      49      497050 :   Mat            A = ctx->A;
      50             : 
      51      497050 :   PetscFunctionBegin;
      52      497050 :   PetscCallAbort(PetscObjectComm((PetscObject)A),VecPlaceArray(x,(PetscScalar*)xa));
      53      497050 :   PetscCallAbort(PetscObjectComm((PetscObject)A),VecPlaceArray(y,(PetscScalar*)ya));
      54      497050 :   PetscCallAbort(PetscObjectComm((PetscObject)A),MatMult(A,x,y));
      55      497050 :   PetscCallAbort(PetscObjectComm((PetscObject)A),VecResetArray(x));
      56      497050 :   PetscCallAbort(PetscObjectComm((PetscObject)A),VecResetArray(y));
      57      497050 :   PetscFunctionReturnVoid();
      58             : }
      59             : 
      60          15 : static PetscErrorCode EPSSetUp_EVSL(EPS eps)
      61             : {
      62          15 :   EPS_EVSL       *ctx = (EPS_EVSL*)eps->data;
      63          15 :   PetscMPIInt    size,rank;
      64          15 :   PetscBool      isshift;
      65          15 :   PetscScalar    *vinit;
      66          15 :   PetscReal      *mu,ecount,xintv[4],*xdos,*ydos;
      67          15 :   Vec            v0;
      68          15 :   Mat            A;
      69          15 :   PetscRandom    rnd;
      70             : 
      71          15 :   PetscFunctionBegin;
      72          15 :   EPSCheckStandard(eps);
      73          15 :   EPSCheckHermitian(eps);
      74          15 :   EPSCheckNotStructured(eps);
      75          15 :   if (eps->nev==0) eps->nev = 1;
      76          15 :   PetscCall(PetscObjectTypeCompare((PetscObject)eps->st,STSHIFT,&isshift));
      77          15 :   PetscCheck(isshift,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver does not support spectral transformations");
      78             : 
      79          15 :   if (ctx->initialized) EVSLFinish();
      80          15 :   EVSLStart();
      81          15 :   ctx->initialized=PETSC_TRUE;
      82             : 
      83             :   /* get number of slices per process */
      84          15 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size));
      85          15 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&rank));
      86          15 :   if (!ctx->nslices) ctx->nslices = size;
      87          15 :   PetscCall(PetscLayoutDestroy(&ctx->map));
      88          15 :   PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)eps),PETSC_DECIDE,ctx->nslices,1,&ctx->map));
      89             : 
      90             :   /* get matrix and prepare auxiliary vectors */
      91          15 :   PetscCall(MatDestroy(&ctx->A));
      92          15 :   PetscCall(STGetMatrix(eps->st,0,&A));
      93          15 :   if (size==1) {
      94           7 :     PetscCall(PetscObjectReference((PetscObject)A));
      95           7 :     ctx->A = A;
      96           8 :   } else PetscCall(MatCreateRedundantMatrix(A,0,PETSC_COMM_SELF,MAT_INITIAL_MATRIX,&ctx->A));
      97          15 :   SetAMatvec(eps->n,&AMatvec_EVSL,(void*)ctx);
      98          15 :   if (!ctx->x) PetscCall(MatCreateVecsEmpty(ctx->A,&ctx->x,&ctx->y));
      99          15 :   EPSCheckUnsupported(eps,EPS_FEATURE_ARBITRARY | EPS_FEATURE_REGION | EPS_FEATURE_STOPPING);
     100          15 :   EPSCheckIgnored(eps,EPS_FEATURE_EXTRACTION | EPS_FEATURE_CONVERGENCE);
     101             : 
     102          15 :   if (!eps->which) eps->which=EPS_ALL;
     103          15 :   PetscCheck(eps->which==EPS_ALL && eps->inta!=eps->intb,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver requires setting an interval with EPSSetInterval()");
     104             : 
     105             :   /* estimate numerical range */
     106          15 :   if (ctx->estimrange || ctx->lmin == PETSC_MIN_REAL || ctx->lmax == PETSC_MAX_REAL) {
     107          14 :     PetscCall(MatCreateVecs(ctx->A,&v0,NULL));
     108          14 :     if (!eps->V) PetscCall(EPSGetBV(eps,&eps->V));
     109          14 :     PetscCall(BVGetRandomContext(eps->V,&rnd));
     110          14 :     PetscCall(VecSetRandom(v0,rnd));
     111          14 :     PetscCall(VecGetArray(v0,&vinit));
     112          14 :     PetscCallEVSL(LanTrbounds,50,200,eps->tol,vinit,1,&ctx->lmin,&ctx->lmax,NULL);
     113          14 :     PetscCall(VecRestoreArray(v0,&vinit));
     114          14 :     PetscCall(VecDestroy(&v0));
     115          14 :     ctx->estimrange = PETSC_TRUE;   /* estimate if called again with another matrix */
     116             :   }
     117          15 :   PetscCheck(ctx->lmin<=eps->inta && ctx->lmax>=eps->intb,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The requested interval [%g,%g] must be contained in the numerical range [%g,%g]",(double)eps->inta,(double)eps->intb,(double)ctx->lmin,(double)ctx->lmax);
     118          15 :   xintv[0] = eps->inta;
     119          15 :   xintv[1] = eps->intb;
     120          15 :   xintv[2] = ctx->lmin;
     121          15 :   xintv[3] = ctx->lmax;
     122             : 
     123             :   /* estimate number of eigenvalues in the interval */
     124          15 :   switch (ctx->dos) {
     125           9 :     case EPS_EVSL_DOS_KPM:
     126           9 :       PetscCall(PetscMalloc1(ctx->deg+1,&mu));
     127           9 :       if (!rank) PetscCallEVSL(kpmdos,ctx->deg,(int)ctx->damping,ctx->nvec,xintv,mu,&ecount);
     128          18 :       PetscCallMPI(MPI_Bcast(mu,ctx->deg+1,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
     129             :       break;
     130           6 :     case EPS_EVSL_DOS_LANCZOS:
     131           6 :       PetscCall(PetscMalloc2(ctx->npoints,&xdos,ctx->npoints,&ydos));
     132           6 :       if (!rank) PetscCallEVSL(LanDos,ctx->nvec,PetscMin(ctx->steps,eps->n/2),ctx->npoints,xdos,ydos,&ecount,xintv);
     133          12 :       PetscCallMPI(MPI_Bcast(xdos,ctx->npoints,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
     134          12 :       PetscCallMPI(MPI_Bcast(ydos,ctx->npoints,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
     135             :       break;
     136           0 :     default:
     137           0 :       SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid DOS method");
     138             :   }
     139          30 :   PetscCallMPI(MPI_Bcast(&ecount,1,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
     140             : 
     141          15 :   PetscCall(PetscInfo(eps,"Estimated eigenvalue count in the interval: %g\n",ecount));
     142          15 :   eps->ncv = (PetscInt)PetscCeilReal(1.5*ecount);
     143             : 
     144             :   /* slice the spectrum */
     145          15 :   PetscCall(PetscFree(ctx->sli));
     146          15 :   PetscCall(PetscMalloc1(ctx->nslices+1,&ctx->sli));
     147          15 :   if (ctx->dos == EPS_EVSL_DOS_KPM) {
     148           9 :     PetscCallEVSL(spslicer,ctx->sli,mu,ctx->deg,xintv,ctx->nslices,10*(PetscInt)ecount);
     149           9 :     PetscCall(PetscFree(mu));
     150           6 :   } else if (ctx->dos == EPS_EVSL_DOS_LANCZOS) {
     151           6 :     spslicer2(xdos,ydos,ctx->nslices,ctx->npoints,ctx->sli);
     152           6 :     PetscCall(PetscFree2(xdos,ydos));
     153             :   }
     154             : 
     155             :   /* approximate number of eigenvalues wanted in each slice */
     156          15 :   ctx->nev = (PetscInt)(1.0 + ecount/(PetscReal)ctx->nslices) + 2;
     157             : 
     158          15 :   if (eps->mpd!=PETSC_DETERMINE) PetscCall(PetscInfo(eps,"Warning: parameter mpd ignored\n"));
     159          15 :   if (eps->max_it==PETSC_DETERMINE) eps->max_it = 1;
     160          15 :   PetscCall(EPSAllocateSolution(eps,0));
     161          15 :   PetscFunctionReturn(PETSC_SUCCESS);
     162             : }
     163             : 
     164          15 : static PetscErrorCode EPSSolve_EVSL(EPS eps)
     165             : {
     166          15 :   EPS_EVSL       *ctx = (EPS_EVSL*)eps->data;
     167          15 :   PetscInt       i,j,k=0,sl,mlan,nevout,*ind,nevmax,rstart,rend,*nevloc,*disp,N;
     168          15 :   PetscReal      *res,xintv[4],*errest;
     169          15 :   PetscScalar    *lam,*X,*Y,*vinit,*eigr;
     170          15 :   PetscMPIInt    size,rank;
     171          15 :   PetscRandom    rnd;
     172          15 :   Vec            v,w,v0,x;
     173          15 :   VecScatter     vs;
     174          15 :   IS             is;
     175          15 :   polparams      pol;
     176             : 
     177          15 :   PetscFunctionBegin;
     178          15 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size));
     179          15 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&rank));
     180          15 :   PetscCall(PetscLayoutGetRange(ctx->map,&rstart,&rend));
     181          15 :   nevmax = (rend-rstart)*ctx->nev;
     182          15 :   PetscCall(MatCreateVecs(ctx->A,&v0,NULL));
     183          15 :   PetscCall(BVGetRandomContext(eps->V,&rnd));
     184          15 :   PetscCall(VecSetRandom(v0,rnd));
     185          15 :   PetscCall(VecGetArray(v0,&vinit));
     186          15 :   PetscCall(PetscMalloc5(size,&nevloc,size+1,&disp,nevmax,&eigr,nevmax,&errest,nevmax*eps->n,&X));
     187          15 :   mlan = PetscMin(PetscMax(5*ctx->nev,300),eps->n);
     188          37 :   for (sl=rstart; sl<rend; sl++) {
     189          22 :     xintv[0] = ctx->sli[sl];
     190          22 :     xintv[1] = ctx->sli[sl+1];
     191          22 :     xintv[2] = ctx->lmin;
     192          22 :     xintv[3] = ctx->lmax;
     193          22 :     PetscCall(PetscInfo(ctx->A,"Subinterval %" PetscInt_FMT ": [%.4e, %.4e]\n",sl+1,xintv[0],xintv[1]));
     194          22 :     set_pol_def(&pol);
     195          22 :     pol.max_deg    = ctx->max_deg;
     196          22 :     pol.damping    = (int)ctx->damping;
     197          22 :     pol.thresh_int = ctx->thresh;
     198          22 :     find_pol(xintv,&pol);
     199          22 :     PetscCall(PetscInfo(ctx->A,"Polynomial [type = %" PetscInt_FMT "], deg %" PetscInt_FMT ", bar %e gam %e\n",pol.type,pol.deg,pol.bar,pol.gam));
     200          22 :     PetscCallEVSL(ChebLanNr,xintv,mlan,eps->tol,vinit,&pol,&nevout,&lam,&Y,&res,NULL);
     201          22 :     PetscCheck(k+nevout<=nevmax,PetscObjectComm((PetscObject)eps),PETSC_ERR_LIB,"Too low estimation of eigenvalue count, try modifying the sampling parameters");
     202          22 :     free_pol(&pol);
     203          22 :     PetscCall(PetscInfo(ctx->A,"Computed %" PetscInt_FMT " eigenvalues\n",nevout));
     204          22 :     PetscCall(PetscMalloc1(nevout,&ind));
     205          22 :     sort_double(nevout,lam,ind);
     206         170 :     for (i=0;i<nevout;i++) {
     207         126 :       eigr[i+k]   = lam[i];
     208         126 :       errest[i+k] = res[ind[i]];
     209         126 :       PetscCall(PetscArraycpy(X+(i+k)*eps->n,Y+ind[i]*eps->n,eps->n));
     210             :     }
     211          22 :     k += nevout;
     212          22 :     if (lam) evsl_Free(lam);
     213          22 :     if (Y)   evsl_Free_device(Y);
     214          22 :     if (res) evsl_Free(res);
     215          22 :     PetscCall(PetscFree(ind));
     216             :   }
     217          15 :   PetscCall(VecRestoreArray(v0,&vinit));
     218          15 :   PetscCall(VecDestroy(&v0));
     219             : 
     220             :   /* gather eigenvalues computed by each MPI process */
     221          30 :   PetscCallMPI(MPI_Allgather(&k,1,MPIU_INT,nevloc,1,MPIU_INT,PetscObjectComm((PetscObject)eps)));
     222          15 :   eps->nev = nevloc[0];
     223          15 :   disp[0]  = 0;
     224          23 :   for (i=1;i<size;i++) {
     225           8 :     eps->nev += nevloc[i];
     226           8 :     disp[i]   = disp[i-1]+nevloc[i-1];
     227             :   }
     228          15 :   disp[size] = disp[size-1]+nevloc[size-1];
     229          15 :   PetscCheck(eps->nev<=eps->ncv,PetscObjectComm((PetscObject)eps),PETSC_ERR_LIB,"Too low estimation of eigenvalue count, try modifying the sampling parameters");
     230          30 :   PetscCallMPI(MPI_Allgatherv(eigr,k,MPIU_SCALAR,eps->eigr,nevloc,disp,MPIU_SCALAR,PetscObjectComm((PetscObject)eps)));
     231          30 :   PetscCallMPI(MPI_Allgatherv(errest,k,MPIU_REAL,eps->errest,nevloc,disp,MPIU_REAL,PetscObjectComm((PetscObject)eps)));
     232          15 :   eps->nconv  = eps->nev;
     233          15 :   eps->its    = 1;
     234          15 :   eps->reason = EPS_CONVERGED_TOL;
     235             : 
     236             :   /* scatter computed eigenvectors and store them in eps->V */
     237          15 :   PetscCall(BVCreateVec(eps->V,&w));
     238          38 :   for (i=0;i<size;i++) {
     239          23 :     N = (rank==i)? eps->n: 0;
     240          23 :     PetscCall(VecCreateSeq(PETSC_COMM_SELF,N,&x));
     241          23 :     PetscCall(VecSetFromOptions(x));
     242          23 :     PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&is));
     243          23 :     PetscCall(VecScatterCreate(x,is,w,is,&vs));
     244          23 :     PetscCall(ISDestroy(&is));
     245         176 :     for (j=disp[i];j<disp[i+1];j++) {
     246         153 :       PetscCall(BVGetColumn(eps->V,j,&v));
     247         153 :       if (rank==i) PetscCall(VecPlaceArray(x,X+(j-disp[i])*eps->n));
     248         153 :       PetscCall(VecScatterBegin(vs,x,v,INSERT_VALUES,SCATTER_FORWARD));
     249         153 :       PetscCall(VecScatterEnd(vs,x,v,INSERT_VALUES,SCATTER_FORWARD));
     250         153 :       if (rank==i) PetscCall(VecResetArray(x));
     251         153 :       PetscCall(BVRestoreColumn(eps->V,j,&v));
     252             :     }
     253          23 :     PetscCall(VecScatterDestroy(&vs));
     254          23 :     PetscCall(VecDestroy(&x));
     255             :   }
     256          15 :   PetscCall(VecDestroy(&w));
     257          15 :   PetscCall(PetscFree5(nevloc,disp,eigr,errest,X));
     258          15 :   PetscFunctionReturn(PETSC_SUCCESS);
     259             : }
     260             : 
     261           2 : static PetscErrorCode EPSEVSLSetSlices_EVSL(EPS eps,PetscInt nslices)
     262             : {
     263           2 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     264             : 
     265           2 :   PetscFunctionBegin;
     266           2 :   if (nslices == PETSC_DECIDE || nslices == PETSC_DEFAULT) nslices = 0;
     267           2 :   else PetscCheck(nslices>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Number of slices must be 1 at least");
     268           2 :   if (ctx->nslices != nslices) {
     269           2 :     ctx->nslices = nslices;
     270           2 :     eps->state   = EPS_STATE_INITIAL;
     271             :   }
     272           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     273             : }
     274             : 
     275             : /*@
     276             :    EPSEVSLSetSlices - Set the number of slices in which the interval must be
     277             :    subdivided.
     278             : 
     279             :    Logically Collective
     280             : 
     281             :    Input Parameters:
     282             : +  eps     - the eigensolver context
     283             : -  nslices - the number of slices
     284             : 
     285             :    Options Database Key:
     286             : .  -eps_evsl_slices <n> - set the number of slices to n
     287             : 
     288             :    Notes:
     289             :    By default, one slice per MPI process is used. Depending on the number of
     290             :    eigenvalues, using more slices may be beneficial, but very narrow subintervals
     291             :    imply higher polynomial degree.
     292             : 
     293             :    Level: intermediate
     294             : 
     295             : .seealso: EPSEVSLGetSlices()
     296             : @*/
     297           2 : PetscErrorCode EPSEVSLSetSlices(EPS eps,PetscInt nslices)
     298             : {
     299           2 :   PetscFunctionBegin;
     300           2 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     301           6 :   PetscValidLogicalCollectiveInt(eps,nslices,2);
     302           2 :   PetscTryMethod(eps,"EPSEVSLSetSlices_C",(EPS,PetscInt),(eps,nslices));
     303           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     304             : }
     305             : 
     306           1 : static PetscErrorCode EPSEVSLGetSlices_EVSL(EPS eps,PetscInt *nslices)
     307             : {
     308           1 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     309             : 
     310           1 :   PetscFunctionBegin;
     311           1 :   *nslices = ctx->nslices;
     312           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     313             : }
     314             : 
     315             : /*@
     316             :    EPSEVSLGetSlices - Gets the number of slices in which the interval must be
     317             :    subdivided.
     318             : 
     319             :    Not Collective
     320             : 
     321             :    Input Parameter:
     322             : .  eps - the eigensolver context
     323             : 
     324             :    Output Parameter:
     325             : .  nslices - the number of slices
     326             : 
     327             :    Level: intermediate
     328             : 
     329             : .seealso: EPSEVSLSetSlices()
     330             : @*/
     331           1 : PetscErrorCode EPSEVSLGetSlices(EPS eps,PetscInt *nslices)
     332             : {
     333           1 :   PetscFunctionBegin;
     334           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     335           1 :   PetscAssertPointer(nslices,2);
     336           1 :   PetscUseMethod(eps,"EPSEVSLGetSlices_C",(EPS,PetscInt*),(eps,nslices));
     337           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     338             : }
     339             : 
     340           1 : static PetscErrorCode EPSEVSLSetRange_EVSL(EPS eps,PetscReal lmin,PetscReal lmax)
     341             : {
     342           1 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     343             : 
     344           1 :   PetscFunctionBegin;
     345           1 :   PetscCheck(lmin<lmax,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be lmin<lmax");
     346           1 :   if (ctx->lmin != lmin || ctx->lmax != lmax) {
     347           1 :     ctx->lmin  = lmin;
     348           1 :     ctx->lmax  = lmax;
     349           1 :     eps->state = EPS_STATE_INITIAL;
     350             :   }
     351           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     352             : }
     353             : 
     354             : /*@
     355             :    EPSEVSLSetRange - Defines the numerical range (or field of values) of the problem,
     356             :    that is, the interval containing all eigenvalues.
     357             : 
     358             :    Logically Collective
     359             : 
     360             :    Input Parameters:
     361             : +  eps  - the eigensolver context
     362             : .  lmin - left end of the interval
     363             : -  lmax - right end of the interval
     364             : 
     365             :    Options Database Key:
     366             : .  -eps_evsl_range <a,b> - set [a,b] as the numerical range
     367             : 
     368             :    Notes:
     369             :    The filter will be most effective if the numerical range is tight, that is, lmin
     370             :    and lmax are good approximations to the leftmost and rightmost eigenvalues,
     371             :    respectively. If not set by the user, an approximation is computed internally.
     372             : 
     373             :    The wanted computational interval specified via EPSSetInterval() must be
     374             :    contained in the numerical range.
     375             : 
     376             :    Level: intermediate
     377             : 
     378             : .seealso: EPSEVSLGetRange(), EPSSetInterval()
     379             : @*/
     380           1 : PetscErrorCode EPSEVSLSetRange(EPS eps,PetscReal lmin,PetscReal lmax)
     381             : {
     382           1 :   PetscFunctionBegin;
     383           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     384           3 :   PetscValidLogicalCollectiveReal(eps,lmin,2);
     385           3 :   PetscValidLogicalCollectiveReal(eps,lmax,3);
     386           1 :   PetscTryMethod(eps,"EPSEVSLSetRange_C",(EPS,PetscReal,PetscReal),(eps,lmin,lmax));
     387           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     388             : }
     389             : 
     390           1 : static PetscErrorCode EPSEVSLGetRange_EVSL(EPS eps,PetscReal *lmin,PetscReal *lmax)
     391             : {
     392           1 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     393             : 
     394           1 :   PetscFunctionBegin;
     395           1 :   if (lmin) *lmin = ctx->lmin;
     396           1 :   if (lmax) *lmax = ctx->lmax;
     397           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     398             : }
     399             : 
     400             : /*@
     401             :    EPSEVSLGetRange - Gets the interval containing all eigenvalues.
     402             : 
     403             :    Not Collective
     404             : 
     405             :    Input Parameter:
     406             : .  eps - the eigensolver context
     407             : 
     408             :    Output Parameters:
     409             : +  lmin - left end of the interval
     410             : -  lmax - right end of the interval
     411             : 
     412             :    Level: intermediate
     413             : 
     414             : .seealso: EPSEVSLSetRange()
     415             : @*/
     416           1 : PetscErrorCode EPSEVSLGetRange(EPS eps,PetscReal *lmin,PetscReal *lmax)
     417             : {
     418           1 :   PetscFunctionBegin;
     419           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     420           1 :   PetscUseMethod(eps,"EPSEVSLGetRange_C",(EPS,PetscReal*,PetscReal*),(eps,lmin,lmax));
     421           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     422             : }
     423             : 
     424           4 : static PetscErrorCode EPSEVSLSetDOSParameters_EVSL(EPS eps,EPSEVSLDOSMethod dos,PetscInt nvec,PetscInt deg,PetscInt steps,PetscInt npoints)
     425             : {
     426           4 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     427             : 
     428           4 :   PetscFunctionBegin;
     429           4 :   ctx->dos = dos;
     430           4 :   if (nvec == PETSC_DETERMINE) ctx->nvec = 80;
     431           4 :   else if (nvec != PETSC_CURRENT) {
     432           4 :     PetscCheck(nvec>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The nvec argument must be > 0");
     433           4 :     ctx->nvec = nvec;
     434             :   }
     435           4 :   switch (dos) {
     436           1 :     case EPS_EVSL_DOS_KPM:
     437           1 :       if (deg == PETSC_DETERMINE) ctx->deg = 300;
     438           1 :       else if (deg != PETSC_CURRENT) {
     439           1 :         PetscCheck(deg>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The deg argument must be > 0");
     440           1 :         ctx->deg = deg;
     441             :       }
     442             :       break;
     443           3 :     case EPS_EVSL_DOS_LANCZOS:
     444           3 :       if (steps == PETSC_DETERMINE) ctx->steps = 40;
     445           3 :       else if (steps != PETSC_CURRENT) {
     446           3 :         PetscCheck(steps>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The steps argument must be > 0");
     447           3 :         ctx->steps = steps;
     448             :       }
     449           3 :       if (npoints == PETSC_DETERMINE) ctx->npoints = 200;
     450           3 :       else if (npoints != PETSC_CURRENT) {
     451           3 :         PetscCheck(npoints>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The npoints argument must be > 0");
     452           3 :         ctx->npoints = npoints;
     453             :       }
     454             :       break;
     455             :   }
     456           4 :   eps->state = EPS_STATE_INITIAL;
     457           4 :   PetscFunctionReturn(PETSC_SUCCESS);
     458             : }
     459             : 
     460             : /*@
     461             :    EPSEVSLSetDOSParameters - Defines the parameters used for computing the
     462             :    density of states (DOS) in the EVSL solver.
     463             : 
     464             :    Logically Collective
     465             : 
     466             :    Input Parameters:
     467             : +  eps     - the eigensolver context
     468             : .  dos     - DOS method, either KPM or Lanczos
     469             : .  nvec    - number of sample vectors
     470             : .  deg     - polynomial degree (KPM only)
     471             : .  steps   - number of Lanczos steps (Lanczos only)
     472             : -  npoints - number of sample points (Lanczos only)
     473             : 
     474             :    Options Database Keys:
     475             : +  -eps_evsl_dos_method <dos> - set the DOS method, either kpm or lanczos
     476             : .  -eps_evsl_dos_nvec <n> - set the number of sample vectors
     477             : .  -eps_evsl_dos_degree <n> - set the polynomial degree
     478             : .  -eps_evsl_dos_steps <n> - set the number of Lanczos steps
     479             : -  -eps_evsl_dos_npoints <n> - set the number of sample points
     480             : 
     481             :    Notes:
     482             :    The density of states (or spectral density) can be approximated with two
     483             :    methods, kernel polynomial method (KPM) or Lanczos. Some parameters for
     484             :    these methods can be set by the user with this function, with some of
     485             :    them being relevant for one of the methods only.
     486             : 
     487             :    For the integer argumens, you can use PETSC_CURRENT to keep the current
     488             :    value, and PETSC_DETERMINE to set them to a reasonable default.
     489             : 
     490             :    Level: intermediate
     491             : 
     492             : .seealso: EPSEVSLGetDOSParameters()
     493             : @*/
     494           4 : PetscErrorCode EPSEVSLSetDOSParameters(EPS eps,EPSEVSLDOSMethod dos,PetscInt nvec,PetscInt deg,PetscInt steps,PetscInt npoints)
     495             : {
     496           4 :   PetscFunctionBegin;
     497           4 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     498          12 :   PetscValidLogicalCollectiveEnum(eps,dos,2);
     499          12 :   PetscValidLogicalCollectiveInt(eps,nvec,3);
     500          12 :   PetscValidLogicalCollectiveInt(eps,deg,4);
     501          12 :   PetscValidLogicalCollectiveInt(eps,steps,5);
     502          12 :   PetscValidLogicalCollectiveInt(eps,npoints,6);
     503           4 :   PetscTryMethod(eps,"EPSEVSLSetDOSParameters_C",(EPS,EPSEVSLDOSMethod,PetscInt,PetscInt,PetscInt,PetscInt),(eps,dos,nvec,deg,steps,npoints));
     504           4 :   PetscFunctionReturn(PETSC_SUCCESS);
     505             : }
     506             : 
     507           9 : static PetscErrorCode EPSEVSLGetDOSParameters_EVSL(EPS eps,EPSEVSLDOSMethod *dos,PetscInt *nvec,PetscInt *deg,PetscInt *steps,PetscInt *npoints)
     508             : {
     509           9 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     510             : 
     511           9 :   PetscFunctionBegin;
     512           9 :   if (dos)     *dos     = ctx->dos;
     513           9 :   if (nvec)    *nvec    = ctx->nvec;
     514           9 :   if (deg)     *deg     = ctx->deg;
     515           9 :   if (steps)   *steps   = ctx->steps;
     516           9 :   if (npoints) *npoints = ctx->npoints;
     517           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     518             : }
     519             : 
     520             : /*@
     521             :    EPSEVSLGetDOSParameters - Gets the parameters used for computing the
     522             :    density of states (DOS) in the EVSL solver.
     523             : 
     524             :    Not Collective
     525             : 
     526             :    Input Parameter:
     527             : .  eps - the eigensolver context
     528             : 
     529             :    Output Parameters:
     530             : +  dos     - DOS method, either KPM or Lanczos
     531             : .  nvec    - number of sample vectors
     532             : .  deg     - polynomial degree (KPM only)
     533             : .  steps   - number of Lanczos steps (Lanczos only)
     534             : -  npoints - number of sample points (Lanczos only)
     535             : 
     536             :    Level: intermediate
     537             : 
     538             : .seealso: EPSEVSLSetDOSParameters()
     539             : @*/
     540           9 : PetscErrorCode EPSEVSLGetDOSParameters(EPS eps,EPSEVSLDOSMethod *dos,PetscInt *nvec,PetscInt *deg,PetscInt *steps,PetscInt *npoints)
     541             : {
     542           9 :   PetscFunctionBegin;
     543           9 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     544           9 :   PetscUseMethod(eps,"EPSEVSLGetDOSParameters_C",(EPS,EPSEVSLDOSMethod*,PetscInt*,PetscInt*,PetscInt*,PetscInt*),(eps,dos,nvec,deg,steps,npoints));
     545           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     546             : }
     547             : 
     548           1 : static PetscErrorCode EPSEVSLSetPolParameters_EVSL(EPS eps,PetscInt max_deg,PetscReal thresh)
     549             : {
     550           1 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     551             : 
     552           1 :   PetscFunctionBegin;
     553           1 :   if (max_deg == PETSC_DETERMINE) ctx->max_deg = 10000;
     554           1 :   else if (max_deg != PETSC_CURRENT) {
     555           1 :     PetscCheck(max_deg>2,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The max_deg argument must be > 2");
     556           1 :     ctx->max_deg = max_deg;
     557             :   }
     558           1 :   if (thresh == (PetscReal)PETSC_DETERMINE) ctx->thresh = 0.8;
     559           1 :   else if (thresh != (PetscReal)PETSC_CURRENT) {
     560           1 :     PetscCheck(thresh>0.0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The thresh argument must be > 0.0");
     561           1 :     ctx->thresh = thresh;
     562             :   }
     563           1 :   eps->state = EPS_STATE_INITIAL;
     564           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     565             : }
     566             : 
     567             : /*@
     568             :    EPSEVSLSetPolParameters - Defines the parameters used for building the
     569             :    building the polynomial in the EVSL solver.
     570             : 
     571             :    Logically Collective
     572             : 
     573             :    Input Parameters:
     574             : +  eps     - the eigensolver context
     575             : .  max_deg - maximum degree allowed for the polynomial
     576             : -  thresh  - threshold for accepting polynomial
     577             : 
     578             :    Options Database Keys:
     579             : +  -eps_evsl_pol_max_deg <d> - set maximum polynomial degree
     580             : -  -eps_evsl_pol_thresh <t> - set the threshold
     581             : 
     582             :    Note:
     583             :    PETSC_CURRENT can be used to preserve the current value of any of the
     584             :    arguments, and PETSC_DETERMINE to set them to a default value.
     585             : 
     586             :    Level: intermediate
     587             : 
     588             : .seealso: EPSEVSLGetPolParameters()
     589             : @*/
     590           1 : PetscErrorCode EPSEVSLSetPolParameters(EPS eps,PetscInt max_deg,PetscReal thresh)
     591             : {
     592           1 :   PetscFunctionBegin;
     593           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     594           3 :   PetscValidLogicalCollectiveInt(eps,max_deg,2);
     595           3 :   PetscValidLogicalCollectiveReal(eps,thresh,3);
     596           1 :   PetscTryMethod(eps,"EPSEVSLSetPolParameters_C",(EPS,PetscInt,PetscReal),(eps,max_deg,thresh));
     597           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     598             : }
     599             : 
     600           9 : static PetscErrorCode EPSEVSLGetPolParameters_EVSL(EPS eps,PetscInt *max_deg,PetscReal *thresh)
     601             : {
     602           9 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     603             : 
     604           9 :   PetscFunctionBegin;
     605           9 :   if (max_deg) *max_deg = ctx->max_deg;
     606           9 :   if (thresh)  *thresh  = ctx->thresh;
     607           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     608             : }
     609             : 
     610             : /*@
     611             :    EPSEVSLGetPolParameters - Gets the parameters used for building the
     612             :    polynomial in the EVSL solver.
     613             : 
     614             :    Not Collective
     615             : 
     616             :    Input Parameter:
     617             : .  eps - the eigensolver context
     618             : 
     619             :    Output Parameters:
     620             : +  max_deg - the maximum degree of the polynomial
     621             : -  thresh  - the threshold
     622             : 
     623             :    Level: intermediate
     624             : 
     625             : .seealso: EPSEVSLSetPolParameters()
     626             : @*/
     627           9 : PetscErrorCode EPSEVSLGetPolParameters(EPS eps,PetscInt *max_deg,PetscReal *thresh)
     628             : {
     629           9 :   PetscFunctionBegin;
     630           9 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     631           9 :   PetscUseMethod(eps,"EPSEVSLGetPolParameters_C",(EPS,PetscInt*,PetscReal*),(eps,max_deg,thresh));
     632           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     633             : }
     634             : 
     635           2 : static PetscErrorCode EPSEVSLSetDamping_EVSL(EPS eps,EPSEVSLDamping damping)
     636             : {
     637           2 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     638             : 
     639           2 :   PetscFunctionBegin;
     640           2 :   if (ctx->damping != damping) {
     641           1 :     ctx->damping = damping;
     642           1 :     eps->state   = EPS_STATE_INITIAL;
     643             :   }
     644           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     645             : }
     646             : 
     647             : /*@
     648             :    EPSEVSLSetDamping - Set the type of damping to be used in EVSL.
     649             : 
     650             :    Logically Collective
     651             : 
     652             :    Input Parameters:
     653             : +  eps     - the eigensolver context
     654             : -  damping - the type of damping
     655             : 
     656             :    Options Database Key:
     657             : .  -eps_evsl_damping <n> - set the type of damping
     658             : 
     659             :    Notes:
     660             :    Damping is applied when building the polynomial to be used when solving the
     661             :    eigenproblem, and also during estimation of DOS with the KPM method.
     662             : 
     663             :    Level: intermediate
     664             : 
     665             : .seealso: EPSEVSLGetDamping(), EPSEVSLSetDOSParameters()
     666             : @*/
     667           2 : PetscErrorCode EPSEVSLSetDamping(EPS eps,EPSEVSLDamping damping)
     668             : {
     669           2 :   PetscFunctionBegin;
     670           2 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     671           6 :   PetscValidLogicalCollectiveEnum(eps,damping,2);
     672           2 :   PetscTryMethod(eps,"EPSEVSLSetDamping_C",(EPS,EPSEVSLDamping),(eps,damping));
     673           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     674             : }
     675             : 
     676           1 : static PetscErrorCode EPSEVSLGetDamping_EVSL(EPS eps,EPSEVSLDamping *damping)
     677             : {
     678           1 :   EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
     679             : 
     680           1 :   PetscFunctionBegin;
     681           1 :   *damping = ctx->damping;
     682           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     683             : }
     684             : 
     685             : /*@
     686             :    EPSEVSLGetDamping - Gets the type of damping.
     687             : 
     688             :    Not Collective
     689             : 
     690             :    Input Parameter:
     691             : .  eps - the eigensolver context
     692             : 
     693             :    Output Parameter:
     694             : .  damping - the type of damping
     695             : 
     696             :    Level: intermediate
     697             : 
     698             : .seealso: EPSEVSLSetDamping()
     699             : @*/
     700           1 : PetscErrorCode EPSEVSLGetDamping(EPS eps,EPSEVSLDamping *damping)
     701             : {
     702           1 :   PetscFunctionBegin;
     703           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     704           1 :   PetscAssertPointer(damping,2);
     705           1 :   PetscUseMethod(eps,"EPSEVSLGetDamping_C",(EPS,EPSEVSLDamping*),(eps,damping));
     706           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     707             : }
     708             : 
     709           1 : static PetscErrorCode EPSView_EVSL(EPS eps,PetscViewer viewer)
     710             : {
     711           1 :   PetscBool      isascii;
     712           1 :   EPS_EVSL       *ctx = (EPS_EVSL*)eps->data;
     713             : 
     714           1 :   PetscFunctionBegin;
     715           1 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     716           1 :   if (isascii) {
     717           1 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  numerical range = [%g,%g]\n",(double)ctx->lmin,(double)ctx->lmax));
     718           1 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of slices = %" PetscInt_FMT "\n",ctx->nslices));
     719           1 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  type of damping = %s\n",EPSEVSLDampings[ctx->damping]));
     720           1 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  computing DOS with %s: nvec=%" PetscInt_FMT ", ",EPSEVSLDOSMethods[ctx->dos],ctx->nvec));
     721           1 :     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
     722           1 :     switch (ctx->dos) {
     723           1 :       case EPS_EVSL_DOS_KPM:
     724           1 :         PetscCall(PetscViewerASCIIPrintf(viewer,"degree=%" PetscInt_FMT "\n",ctx->deg));
     725             :         break;
     726           0 :       case EPS_EVSL_DOS_LANCZOS:
     727           0 :         PetscCall(PetscViewerASCIIPrintf(viewer,"steps=%" PetscInt_FMT ", npoints=%" PetscInt_FMT "\n",ctx->steps,ctx->npoints));
     728             :         break;
     729             :     }
     730           1 :     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
     731           1 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  polynomial parameters: max degree = %" PetscInt_FMT ", threshold = %g\n",ctx->max_deg,(double)ctx->thresh));
     732             :   }
     733           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     734             : }
     735             : 
     736           9 : static PetscErrorCode EPSSetFromOptions_EVSL(EPS eps,PetscOptionItems *PetscOptionsObject)
     737             : {
     738           9 :   PetscReal        array[2]={0,0},th;
     739           9 :   PetscInt         k,i1,i2,i3,i4;
     740           9 :   PetscBool        flg,flg1;
     741           9 :   EPSEVSLDOSMethod dos;
     742           9 :   EPSEVSLDamping   damping;
     743           9 :   EPS_EVSL         *ctx = (EPS_EVSL*)eps->data;
     744             : 
     745           9 :   PetscFunctionBegin;
     746           9 :   PetscOptionsHeadBegin(PetscOptionsObject,"EPS EVSL Options");
     747             : 
     748           9 :     k = 2;
     749           9 :     PetscCall(PetscOptionsRealArray("-eps_evsl_range","Interval containing all eigenvalues (two real values separated with a comma without spaces)","EPSEVSLSetRange",array,&k,&flg));
     750           9 :     if (flg) {
     751           0 :       PetscCheck(k>1,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_SIZ,"Must pass two values in -eps_evsl_range (comma-separated without spaces)");
     752           0 :       PetscCall(EPSEVSLSetRange(eps,array[0],array[1]));
     753             :     }
     754             : 
     755           9 :     PetscCall(PetscOptionsInt("-eps_evsl_slices","Number of slices","EPSEVSLSetSlices",ctx->nslices,&i1,&flg));
     756           9 :     if (flg) PetscCall(EPSEVSLSetSlices(eps,i1));
     757             : 
     758           9 :     PetscCall(PetscOptionsEnum("-eps_evsl_damping","Type of damping","EPSEVSLSetDamping",EPSEVSLDampings,(PetscEnum)ctx->damping,(PetscEnum*)&damping,&flg));
     759           9 :     if (flg) PetscCall(EPSEVSLSetDamping(eps,damping));
     760             : 
     761           9 :     PetscCall(EPSEVSLGetDOSParameters(eps,&dos,&i1,&i2,&i3,&i4));
     762           9 :     PetscCall(PetscOptionsEnum("-eps_evsl_dos_method","Method to compute the DOS","EPSEVSLSetDOSParameters",EPSEVSLDOSMethods,(PetscEnum)ctx->dos,(PetscEnum*)&dos,&flg));
     763           9 :     PetscCall(PetscOptionsInt("-eps_evsl_dos_nvec","Number of sample vectors for DOS","EPSEVSLSetDOSParameters",i1,&i1,&flg1));
     764           9 :     if (flg1) flg = PETSC_TRUE;
     765           9 :     PetscCall(PetscOptionsInt("-eps_evsl_dos_degree","Polynomial degree used for DOS","EPSEVSLSetDOSParameters",i2,&i2,&flg1));
     766           9 :     if (flg1) flg = PETSC_TRUE;
     767           9 :     PetscCall(PetscOptionsInt("-eps_evsl_dos_steps","Number of Lanczos steps in DOS","EPSEVSLSetDOSParameters",i3,&i3,&flg1));
     768           9 :     if (flg1) flg = PETSC_TRUE;
     769           9 :     PetscCall(PetscOptionsInt("-eps_evsl_dos_npoints","Number of sample points used for DOS","EPSEVSLSetDOSParameters",i4,&i4,&flg1));
     770           9 :     if (flg || flg1) PetscCall(EPSEVSLSetDOSParameters(eps,dos,i1,i2,i3,i4));
     771             : 
     772           9 :     PetscCall(EPSEVSLGetPolParameters(eps,&i1,&th));
     773           9 :     PetscCall(PetscOptionsInt("-eps_evsl_pol_max_deg","Maximum degree allowed for the polynomial","EPSEVSLSetPolParameters",i1,&i1,&flg));
     774           9 :     PetscCall(PetscOptionsReal("-eps_evsl_pol_threshold","Threshold for accepting polynomial","EPSEVSLSetPolParameters",th,&th,&flg1));
     775           9 :     if (flg || flg1) PetscCall(EPSEVSLSetPolParameters(eps,i1,th));
     776             : 
     777           9 :   PetscOptionsHeadEnd();
     778           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     779             : }
     780             : 
     781           9 : static PetscErrorCode EPSDestroy_EVSL(EPS eps)
     782             : {
     783           9 :   EPS_EVSL       *ctx = (EPS_EVSL*)eps->data;
     784             : 
     785           9 :   PetscFunctionBegin;
     786           9 :   if (ctx->initialized) EVSLFinish();
     787           9 :   PetscCall(PetscLayoutDestroy(&ctx->map));
     788           9 :   PetscCall(PetscFree(ctx->sli));
     789           9 :   PetscCall(PetscFree(eps->data));
     790           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetRange_C",NULL));
     791           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetRange_C",NULL));
     792           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetSlices_C",NULL));
     793           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetSlices_C",NULL));
     794           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDOSParameters_C",NULL));
     795           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDOSParameters_C",NULL));
     796           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetPolParameters_C",NULL));
     797           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetPolParameters_C",NULL));
     798           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDamping_C",NULL));
     799           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDamping_C",NULL));
     800           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     801             : }
     802             : 
     803          12 : static PetscErrorCode EPSReset_EVSL(EPS eps)
     804             : {
     805          12 :   EPS_EVSL       *ctx = (EPS_EVSL*)eps->data;
     806             : 
     807          12 :   PetscFunctionBegin;
     808          12 :   PetscCall(MatDestroy(&ctx->A));
     809          12 :   PetscCall(VecDestroy(&ctx->x));
     810          12 :   PetscCall(VecDestroy(&ctx->y));
     811          12 :   PetscFunctionReturn(PETSC_SUCCESS);
     812             : }
     813             : 
     814           9 : SLEPC_EXTERN PetscErrorCode EPSCreate_EVSL(EPS eps)
     815             : {
     816           9 :   EPS_EVSL       *ctx;
     817             : 
     818           9 :   PetscFunctionBegin;
     819           9 :   PetscCall(PetscNew(&ctx));
     820           9 :   eps->data = (void*)ctx;
     821             : 
     822           9 :   ctx->nslices = 0;
     823           9 :   ctx->lmin    = PETSC_MIN_REAL;
     824           9 :   ctx->lmax    = PETSC_MAX_REAL;
     825           9 :   ctx->dos     = EPS_EVSL_DOS_KPM;
     826           9 :   ctx->nvec    = 80;
     827           9 :   ctx->deg     = 300;
     828           9 :   ctx->steps   = 40;
     829           9 :   ctx->npoints = 200;
     830           9 :   ctx->max_deg = 10000;
     831           9 :   ctx->thresh  = 0.8;
     832           9 :   ctx->damping = EPS_EVSL_DAMPING_SIGMA;
     833             : 
     834           9 :   eps->categ = EPS_CATEGORY_OTHER;
     835             : 
     836           9 :   eps->ops->solve          = EPSSolve_EVSL;
     837           9 :   eps->ops->setup          = EPSSetUp_EVSL;
     838           9 :   eps->ops->setupsort      = EPSSetUpSort_Basic;
     839           9 :   eps->ops->setfromoptions = EPSSetFromOptions_EVSL;
     840           9 :   eps->ops->destroy        = EPSDestroy_EVSL;
     841           9 :   eps->ops->reset          = EPSReset_EVSL;
     842           9 :   eps->ops->view           = EPSView_EVSL;
     843           9 :   eps->ops->backtransform  = EPSBackTransform_Default;
     844           9 :   eps->ops->setdefaultst   = EPSSetDefaultST_NoFactor;
     845             : 
     846           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetRange_C",EPSEVSLSetRange_EVSL));
     847           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetRange_C",EPSEVSLGetRange_EVSL));
     848           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetSlices_C",EPSEVSLSetSlices_EVSL));
     849           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetSlices_C",EPSEVSLGetSlices_EVSL));
     850           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDOSParameters_C",EPSEVSLSetDOSParameters_EVSL));
     851           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDOSParameters_C",EPSEVSLGetDOSParameters_EVSL));
     852           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetPolParameters_C",EPSEVSLSetPolParameters_EVSL));
     853           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetPolParameters_C",EPSEVSLGetPolParameters_EVSL));
     854           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDamping_C",EPSEVSLSetDamping_EVSL));
     855           9 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDamping_C",EPSEVSLGetDamping_EVSL));
     856           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     857             : }

Generated by: LCOV version 1.14