LCOV - code coverage report
Current view: top level - eps/impls/krylov/lanczos - lanczos.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 461 491 93.9 %
Date: 2024-11-23 00:39:48 Functions: 17 18 94.4 %
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: "lanczos"
      12             : 
      13             :    Method: Explicitly Restarted Symmetric/Hermitian Lanczos
      14             : 
      15             :    Algorithm:
      16             : 
      17             :        Lanczos method for symmetric (Hermitian) problems, with explicit
      18             :        restart and deflation. Several reorthogonalization strategies can
      19             :        be selected.
      20             : 
      21             :    References:
      22             : 
      23             :        [1] "Lanczos Methods in SLEPc", SLEPc Technical Report STR-5,
      24             :            available at https://slepc.upv.es.
      25             : */
      26             : 
      27             : #include <slepc/private/epsimpl.h>                /*I "slepceps.h" I*/
      28             : #include <slepcblaslapack.h>
      29             : 
      30             : typedef struct {
      31             :   EPSLanczosReorthogType reorthog;      /* user-provided reorthogonalization parameter */
      32             :   PetscInt               allocsize;     /* number of columns of work BV's allocated at setup */
      33             :   BV                     AV;            /* work BV used in selective reorthogonalization */
      34             : } EPS_LANCZOS;
      35             : 
      36          36 : static PetscErrorCode EPSSetUp_Lanczos(EPS eps)
      37             : {
      38          36 :   EPS_LANCZOS        *lanczos = (EPS_LANCZOS*)eps->data;
      39          36 :   BVOrthogRefineType refine;
      40          36 :   BVOrthogBlockType  btype;
      41          36 :   PetscReal          eta;
      42             : 
      43          36 :   PetscFunctionBegin;
      44          36 :   EPSCheckHermitianDefinite(eps);
      45          36 :   EPSCheckNotStructured(eps);
      46          36 :   PetscCall(EPSSetDimensions_Default(eps,eps->nev,&eps->ncv,&eps->mpd));
      47          36 :   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");
      48          36 :   if (eps->max_it==PETSC_DETERMINE) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
      49          36 :   if (!eps->which) PetscCall(EPSSetWhichEigenpairs_Default(eps));
      50          36 :   PetscCheck(eps->which!=EPS_ALL,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver does not support computing all eigenvalues");
      51          36 :   EPSCheckUnsupported(eps,EPS_FEATURE_ARBITRARY | EPS_FEATURE_REGION | EPS_FEATURE_EXTRACTION);
      52          36 :   EPSCheckIgnored(eps,EPS_FEATURE_BALANCE);
      53             : 
      54          36 :   PetscCheck(lanczos->reorthog!=(EPSLanczosReorthogType)-1,PetscObjectComm((PetscObject)eps),PETSC_ERR_USER_INPUT,"You should explicitly provide the reorthogonalization type, e.g., -eps_lanczos_reorthog local. Note that the EPSLANCZOS solver is *NOT RECOMMENDED* for general use, because it uses explicit restart which typically has slow convergence. The recommended solver is EPSKRYLOVSCHUR (the default), which implements Lanczos with thick restart in the case of symmetric/Hermitian problems");
      55             : 
      56          36 :   PetscCall(EPSAllocateSolution(eps,1));
      57          36 :   PetscCall(EPS_SetInnerProduct(eps));
      58          36 :   if (lanczos->reorthog != EPS_LANCZOS_REORTHOG_FULL) {
      59          29 :     PetscCall(BVGetOrthogonalization(eps->V,NULL,&refine,&eta,&btype));
      60          29 :     PetscCall(BVSetOrthogonalization(eps->V,BV_ORTHOG_MGS,refine,eta,btype));
      61          29 :     PetscCall(PetscInfo(eps,"Switching to MGS orthogonalization\n"));
      62             :   }
      63          36 :   if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_SELECTIVE) {
      64           3 :     if (!lanczos->allocsize) {
      65           1 :       PetscCall(BVDuplicate(eps->V,&lanczos->AV));
      66           1 :       PetscCall(BVGetSizes(lanczos->AV,NULL,NULL,&lanczos->allocsize));
      67             :     } else { /* make sure V and AV have the same size */
      68           2 :       PetscCall(BVGetSizes(eps->V,NULL,NULL,&lanczos->allocsize));
      69           2 :       PetscCall(BVResize(lanczos->AV,lanczos->allocsize,PETSC_FALSE));
      70             :     }
      71             :   }
      72             : 
      73          36 :   PetscCall(DSSetType(eps->ds,DSHEP));
      74          36 :   PetscCall(DSSetCompact(eps->ds,PETSC_TRUE));
      75          36 :   PetscCall(DSAllocate(eps->ds,eps->ncv+1));
      76          36 :   if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL) PetscCall(EPSSetWorkVecs(eps,1));
      77          36 :   PetscFunctionReturn(PETSC_SUCCESS);
      78             : }
      79             : 
      80             : /*
      81             :    EPSLocalLanczos - Local reorthogonalization.
      82             : 
      83             :    This is the simplest variant. At each Lanczos step, the corresponding Lanczos vector
      84             :    is orthogonalized with respect to the two previous Lanczos vectors, according to
      85             :    the three term Lanczos recurrence. WARNING: This variant does not track the loss of
      86             :    orthogonality that occurs in finite-precision arithmetic and, therefore, the
      87             :    generated vectors are not guaranteed to be (semi-)orthogonal.
      88             : */
      89         520 : static PetscErrorCode EPSLocalLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,PetscInt k,PetscInt *M,PetscBool *breakdown)
      90             : {
      91         520 :   PetscInt       i,j,m = *M;
      92         520 :   Mat            Op;
      93         520 :   PetscBool      *which,lwhich[100];
      94         520 :   PetscScalar    *hwork,lhwork[100];
      95             : 
      96         520 :   PetscFunctionBegin;
      97         520 :   if (m > 100) PetscCall(PetscMalloc2(m,&which,m,&hwork));
      98             :   else {
      99         520 :     which = lwhich;
     100         520 :     hwork = lhwork;
     101             :   }
     102        1794 :   for (i=0;i<k;i++) which[i] = PETSC_TRUE;
     103             : 
     104         520 :   PetscCall(BVSetActiveColumns(eps->V,0,m));
     105         520 :   PetscCall(STGetOperator(eps->st,&Op));
     106        7536 :   for (j=k;j<m;j++) {
     107        7016 :     PetscCall(BVMatMultColumn(eps->V,Op,j));
     108        7016 :     which[j] = PETSC_TRUE;
     109        7016 :     if (j-2>=k) which[j-2] = PETSC_FALSE;
     110        7016 :     PetscCall(BVOrthogonalizeSomeColumn(eps->V,j+1,which,hwork,beta+j,breakdown));
     111        7016 :     alpha[j] = PetscRealPart(hwork[j]);
     112        7016 :     if (PetscUnlikely(*breakdown)) {
     113           0 :       *M = j+1;
     114           0 :       break;
     115        7016 :     } else PetscCall(BVScaleColumn(eps->V,j+1,1/beta[j]));
     116             :   }
     117         520 :   PetscCall(STRestoreOperator(eps->st,&Op));
     118         520 :   if (m > 100) PetscCall(PetscFree2(which,hwork));
     119         520 :   PetscFunctionReturn(PETSC_SUCCESS);
     120             : }
     121             : 
     122             : /*
     123             :    DenseTridiagonal - Solves a real tridiagonal Hermitian Eigenvalue Problem.
     124             : 
     125             :    Input Parameters:
     126             : +  n   - dimension of the eigenproblem
     127             : .  D   - pointer to the array containing the diagonal elements
     128             : -  E   - pointer to the array containing the off-diagonal elements
     129             : 
     130             :    Output Parameters:
     131             : +  w  - pointer to the array to store the computed eigenvalues
     132             : -  V  - pointer to the array to store the eigenvectors
     133             : 
     134             :    Notes:
     135             :    If V is NULL then the eigenvectors are not computed.
     136             : 
     137             :    This routine use LAPACK routines xSTEVR.
     138             : */
     139         676 : static PetscErrorCode DenseTridiagonal(PetscInt n_,PetscReal *D,PetscReal *E,PetscReal *w,PetscScalar *V)
     140             : {
     141         676 :   PetscReal      abstol = 0.0,vl,vu,*work;
     142         676 :   PetscBLASInt   il,iu,m,*isuppz,n,lwork,*iwork,liwork,info;
     143         676 :   const char     *jobz;
     144             : #if defined(PETSC_USE_COMPLEX)
     145         676 :   PetscInt       i,j;
     146         676 :   PetscReal      *VV=NULL;
     147             : #endif
     148             : 
     149         676 :   PetscFunctionBegin;
     150         676 :   PetscCall(PetscBLASIntCast(n_,&n));
     151         676 :   PetscCall(PetscBLASIntCast(20*n_,&lwork));
     152         676 :   PetscCall(PetscBLASIntCast(10*n_,&liwork));
     153         676 :   if (V) {
     154         676 :     jobz = "V";
     155             : #if defined(PETSC_USE_COMPLEX)
     156         676 :     PetscCall(PetscMalloc1(n*n,&VV));
     157             : #endif
     158             :   } else jobz = "N";
     159         676 :   PetscCall(PetscMalloc3(2*n,&isuppz,lwork,&work,liwork,&iwork));
     160         676 :   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
     161             : #if defined(PETSC_USE_COMPLEX)
     162         676 :   PetscCallBLAS("LAPACKstevr",LAPACKstevr_(jobz,"A",&n,D,E,&vl,&vu,&il,&iu,&abstol,&m,w,VV,&n,isuppz,work,&lwork,iwork,&liwork,&info));
     163             : #else
     164             :   PetscCallBLAS("LAPACKstevr",LAPACKstevr_(jobz,"A",&n,D,E,&vl,&vu,&il,&iu,&abstol,&m,w,V,&n,isuppz,work,&lwork,iwork,&liwork,&info));
     165             : #endif
     166         676 :   PetscCall(PetscFPTrapPop());
     167         676 :   SlepcCheckLapackInfo("stevr",info);
     168             : #if defined(PETSC_USE_COMPLEX)
     169         676 :   if (V) {
     170        7053 :     for (i=0;i<n;i++)
     171       84762 :       for (j=0;j<n;j++)
     172       78385 :         V[i*n+j] = VV[i*n+j];
     173         676 :     PetscCall(PetscFree(VV));
     174             :   }
     175             : #endif
     176         676 :   PetscCall(PetscFree3(isuppz,work,iwork));
     177         676 :   PetscFunctionReturn(PETSC_SUCCESS);
     178             : }
     179             : 
     180             : /*
     181             :    EPSSelectiveLanczos - Selective reorthogonalization.
     182             : */
     183          38 : static PetscErrorCode EPSSelectiveLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,PetscInt k,PetscInt *M,PetscBool *breakdown,PetscReal anorm)
     184             : {
     185          38 :   EPS_LANCZOS    *lanczos = (EPS_LANCZOS*)eps->data;
     186          38 :   PetscInt       i,j,m = *M,n,nritz=0,nritzo;
     187          38 :   Vec            vj1,av;
     188          38 :   Mat            Op;
     189          38 :   PetscReal      *d,*e,*ritz,norm;
     190          38 :   PetscScalar    *Y,*hwork;
     191          38 :   PetscBool      *which;
     192             : 
     193          38 :   PetscFunctionBegin;
     194          38 :   PetscCall(PetscCalloc6(m+1,&d,m,&e,m,&ritz,m*m,&Y,m,&which,m,&hwork));
     195          84 :   for (i=0;i<k;i++) which[i] = PETSC_TRUE;
     196          38 :   PetscCall(STGetOperator(eps->st,&Op));
     197             : 
     198         714 :   for (j=k;j<m;j++) {
     199         676 :     PetscCall(BVSetActiveColumns(eps->V,0,m));
     200             : 
     201             :     /* Lanczos step */
     202         676 :     PetscCall(BVMatMultColumn(eps->V,Op,j));
     203         676 :     which[j] = PETSC_TRUE;
     204         676 :     if (j-2>=k) which[j-2] = PETSC_FALSE;
     205         676 :     PetscCall(BVOrthogonalizeSomeColumn(eps->V,j+1,which,hwork,&norm,breakdown));
     206         676 :     alpha[j] = PetscRealPart(hwork[j]);
     207         676 :     beta[j] = norm;
     208         676 :     if (PetscUnlikely(*breakdown)) {
     209           0 :       *M = j+1;
     210           0 :       break;
     211             :     }
     212             : 
     213             :     /* Compute eigenvalues and eigenvectors Y of the tridiagonal block */
     214         676 :     n = j-k+1;
     215        7053 :     for (i=0;i<n;i++) {
     216        6377 :       d[i] = alpha[i+k];
     217        6377 :       e[i] = beta[i+k];
     218             :     }
     219         676 :     PetscCall(DenseTridiagonal(n,d,e,ritz,Y));
     220             : 
     221             :     /* Estimate ||A|| */
     222        7053 :     for (i=0;i<n;i++)
     223        6377 :       if (PetscAbsReal(ritz[i]) > anorm) anorm = PetscAbsReal(ritz[i]);
     224             : 
     225             :     /* Compute nearly converged Ritz vectors */
     226             :     nritzo = 0;
     227        7053 :     for (i=0;i<n;i++) {
     228        6377 :       if (norm*PetscAbsScalar(Y[i*n+n-1]) < PETSC_SQRT_MACHINE_EPSILON*anorm) nritzo++;
     229             :     }
     230         676 :     if (nritzo>nritz) {
     231             :       nritz = 0;
     232         160 :       for (i=0;i<n;i++) {
     233         138 :         if (norm*PetscAbsScalar(Y[i*n+n-1]) < PETSC_SQRT_MACHINE_EPSILON*anorm) {
     234          32 :           PetscCall(BVSetActiveColumns(eps->V,k,k+n));
     235          32 :           PetscCall(BVGetColumn(lanczos->AV,nritz,&av));
     236          32 :           PetscCall(BVMultVec(eps->V,1.0,0.0,av,Y+i*n));
     237          32 :           PetscCall(BVRestoreColumn(lanczos->AV,nritz,&av));
     238          32 :           nritz++;
     239             :         }
     240             :       }
     241             :     }
     242         676 :     if (nritz > 0) {
     243         255 :       PetscCall(BVGetColumn(eps->V,j+1,&vj1));
     244         255 :       PetscCall(BVSetActiveColumns(lanczos->AV,0,nritz));
     245         255 :       PetscCall(BVOrthogonalizeVec(lanczos->AV,vj1,hwork,&norm,breakdown));
     246         255 :       PetscCall(BVRestoreColumn(eps->V,j+1,&vj1));
     247         255 :       if (PetscUnlikely(*breakdown)) {
     248           0 :         *M = j+1;
     249           0 :         break;
     250             :       }
     251             :     }
     252         676 :     PetscCall(BVScaleColumn(eps->V,j+1,1.0/norm));
     253             :   }
     254             : 
     255          38 :   PetscCall(STRestoreOperator(eps->st,&Op));
     256          38 :   PetscCall(PetscFree6(d,e,ritz,Y,which,hwork));
     257          38 :   PetscFunctionReturn(PETSC_SUCCESS);
     258             : }
     259             : 
     260         842 : static void update_omega(PetscReal *omega,PetscReal *omega_old,PetscInt j,PetscReal *alpha,PetscReal *beta,PetscReal eps1,PetscReal anorm)
     261             : {
     262         842 :   PetscInt  k;
     263         842 :   PetscReal T,binv;
     264             : 
     265         842 :   PetscFunctionBegin;
     266             :   /* Estimate of contribution to roundoff errors from A*v
     267             :        fl(A*v) = A*v + f,
     268             :      where ||f|| \approx eps1*||A||.
     269             :      For a full matrix A, a rule-of-thumb estimate is eps1 = sqrt(n)*eps */
     270         842 :   T = eps1*anorm;
     271         842 :   binv = 1.0/beta[j+1];
     272             : 
     273             :   /* Update omega(1) using omega(0)==0 */
     274         842 :   omega_old[0]= beta[1]*omega[1] + (alpha[0]-alpha[j])*omega[0] - beta[j]*omega_old[0];
     275         842 :   if (omega_old[0] > 0) omega_old[0] = binv*(omega_old[0] + T);
     276         506 :   else omega_old[0] = binv*(omega_old[0] - T);
     277             : 
     278             :   /* Update remaining components */
     279        7632 :   for (k=1;k<j-1;k++) {
     280        6790 :     omega_old[k] = beta[k+1]*omega[k+1] + (alpha[k]-alpha[j])*omega[k] + beta[k]*omega[k-1] - beta[j]*omega_old[k];
     281        6790 :     if (omega_old[k] > 0) omega_old[k] = binv*(omega_old[k] + T);
     282        3594 :     else omega_old[k] = binv*(omega_old[k] - T);
     283             :   }
     284         842 :   omega_old[j-1] = binv*T;
     285             : 
     286             :   /* Swap omega and omega_old */
     287        9296 :   for (k=0;k<j;k++) {
     288        8454 :     omega[k] = omega_old[k];
     289        8454 :     omega_old[k] = omega[k];
     290             :   }
     291         842 :   omega[j] = eps1;
     292         842 :   PetscFunctionReturnVoid();
     293             : }
     294             : 
     295          53 : static void compute_int(PetscBool *which,PetscReal *mu,PetscInt j,PetscReal delta,PetscReal eta)
     296             : {
     297          53 :   PetscInt  i,k,maxpos;
     298          53 :   PetscReal max;
     299          53 :   PetscBool found;
     300             : 
     301          53 :   PetscFunctionBegin;
     302             :   /* initialize which */
     303          53 :   found = PETSC_FALSE;
     304          53 :   maxpos = 0;
     305          53 :   max = 0.0;
     306         843 :   for (i=0;i<j;i++) {
     307         790 :     if (PetscAbsReal(mu[i]) >= delta) {
     308         189 :       which[i] = PETSC_TRUE;
     309         189 :       found = PETSC_TRUE;
     310         601 :     } else which[i] = PETSC_FALSE;
     311         790 :     if (PetscAbsReal(mu[i]) > max) {
     312          88 :       maxpos = i;
     313          88 :       max = PetscAbsReal(mu[i]);
     314             :     }
     315             :   }
     316          53 :   if (!found) which[maxpos] = PETSC_TRUE;
     317             : 
     318         843 :   for (i=0;i<j;i++) {
     319         790 :     if (which[i]) {
     320             :       /* find left interval */
     321         689 :       for (k=i;k>=0;k--) {
     322         689 :         if (PetscAbsReal(mu[k])<eta || which[k]) break;
     323           0 :         else which[k] = PETSC_TRUE;
     324             :       }
     325             :       /* find right interval */
     326        1189 :       for (k=i+1;k<j;k++) {
     327        1159 :         if (PetscAbsReal(mu[k])<eta || which[k]) break;
     328         500 :         else which[k] = PETSC_TRUE;
     329             :       }
     330             :     }
     331             :   }
     332          53 :   PetscFunctionReturnVoid();
     333             : }
     334             : 
     335             : /*
     336             :    EPSPartialLanczos - Partial reorthogonalization.
     337             : */
     338          76 : static PetscErrorCode EPSPartialLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,PetscInt k,PetscInt *M,PetscBool *breakdown,PetscReal anorm)
     339             : {
     340          76 :   EPS_LANCZOS    *lanczos = (EPS_LANCZOS*)eps->data;
     341          76 :   PetscInt       i,j,m = *M;
     342          76 :   Mat            Op;
     343          76 :   PetscReal      norm,*omega,lomega[100],*omega_old,lomega_old[100],eps1,delta,eta;
     344          76 :   PetscBool      *which,lwhich[100],*which2,lwhich2[100];
     345          76 :   PetscBool      reorth = PETSC_FALSE,force_reorth = PETSC_FALSE;
     346          76 :   PetscBool      fro = PETSC_FALSE,estimate_anorm = PETSC_FALSE;
     347          76 :   PetscScalar    *hwork,lhwork[100];
     348             : 
     349          76 :   PetscFunctionBegin;
     350          76 :   if (m>100) PetscCall(PetscMalloc5(m,&omega,m,&omega_old,m,&which,m,&which2,m,&hwork));
     351             :   else {
     352          76 :     omega     = lomega;
     353          76 :     omega_old = lomega_old;
     354          76 :     which     = lwhich;
     355          76 :     which2    = lwhich2;
     356          76 :     hwork     = lhwork;
     357             :   }
     358             : 
     359          76 :   eps1 = PetscSqrtReal((PetscReal)eps->n)*PETSC_MACHINE_EPSILON/2;
     360          76 :   delta = PETSC_SQRT_MACHINE_EPSILON/PetscSqrtReal((PetscReal)eps->ncv);
     361          76 :   eta = PetscPowReal(PETSC_MACHINE_EPSILON,3.0/4.0)/PetscSqrtReal((PetscReal)eps->ncv);
     362          76 :   if (anorm < 0.0) {
     363           6 :     anorm = 1.0;
     364           6 :     estimate_anorm = PETSC_TRUE;
     365             :   }
     366        7676 :   for (i=0;i<PetscMax(100,m);i++) omega[i] = omega_old[i] = 0.0;
     367         168 :   for (i=0;i<k;i++) which[i] = PETSC_TRUE;
     368             : 
     369          76 :   PetscCall(BVSetActiveColumns(eps->V,0,m));
     370          76 :   PetscCall(STGetOperator(eps->st,&Op));
     371        1428 :   for (j=k;j<m;j++) {
     372        1352 :     PetscCall(BVMatMultColumn(eps->V,Op,j));
     373        1352 :     if (fro) {
     374             :       /* Lanczos step with full reorthogonalization */
     375         434 :       PetscCall(BVOrthogonalizeColumn(eps->V,j+1,hwork,&norm,breakdown));
     376         434 :       alpha[j] = PetscRealPart(hwork[j]);
     377             :     } else {
     378             :       /* Lanczos step */
     379         918 :       which[j] = PETSC_TRUE;
     380         918 :       if (j-2>=k) which[j-2] = PETSC_FALSE;
     381         918 :       PetscCall(BVOrthogonalizeSomeColumn(eps->V,j+1,which,hwork,&norm,breakdown));
     382         918 :       alpha[j] = PetscRealPart(hwork[j]);
     383         918 :       beta[j] = norm;
     384             : 
     385             :       /* Estimate ||A|| if needed */
     386         918 :       if (estimate_anorm) {
     387         114 :         if (j>k) anorm = PetscMax(anorm,PetscAbsReal(alpha[j])+norm+beta[j-1]);
     388           6 :         else anorm = PetscMax(anorm,PetscAbsReal(alpha[j])+norm);
     389             :       }
     390             : 
     391             :       /* Check if reorthogonalization is needed */
     392         918 :       reorth = PETSC_FALSE;
     393         918 :       if (j>k) {
     394         842 :         update_omega(omega,omega_old,j,alpha,beta-1,eps1,anorm);
     395        9228 :         for (i=0;i<j-k;i++) {
     396        7544 :           if (PetscAbsReal(omega[i]) > delta) reorth = PETSC_TRUE;
     397             :         }
     398             :       }
     399         918 :       if (reorth || force_reorth) {
     400         298 :         for (i=0;i<k;i++) which2[i] = PETSC_FALSE;
     401        2905 :         for (i=k;i<=j;i++) which2[i] = PETSC_TRUE;
     402         173 :         if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_PERIODIC) {
     403             :           /* Periodic reorthogonalization */
     404          85 :           if (force_reorth) force_reorth = PETSC_FALSE;
     405          50 :           else force_reorth = PETSC_TRUE;
     406        1338 :           for (i=0;i<j-k;i++) omega[i] = eps1;
     407             :         } else {
     408             :           /* Partial reorthogonalization */
     409          88 :           if (force_reorth) force_reorth = PETSC_FALSE;
     410             :           else {
     411          53 :             force_reorth = PETSC_TRUE;
     412          53 :             compute_int(which2+k,omega,j-k,delta,eta);
     413         896 :             for (i=0;i<j-k;i++) {
     414         790 :               if (which2[i+k]) omega[i] = eps1;
     415             :             }
     416             :           }
     417             :         }
     418         173 :         PetscCall(BVOrthogonalizeSomeColumn(eps->V,j+1,which2,hwork,&norm,breakdown));
     419             :       }
     420             :     }
     421             : 
     422        1352 :     if (PetscUnlikely(*breakdown || norm < eps->n*anorm*PETSC_MACHINE_EPSILON)) {
     423           0 :       *M = j+1;
     424           0 :       break;
     425             :     }
     426        1352 :     if (!fro && norm*delta < anorm*eps1) {
     427          26 :       fro = PETSC_TRUE;
     428          26 :       PetscCall(PetscInfo(eps,"Switching to full reorthogonalization at iteration %" PetscInt_FMT "\n",eps->its));
     429             :     }
     430        1352 :     beta[j] = norm;
     431        1352 :     PetscCall(BVScaleColumn(eps->V,j+1,1.0/norm));
     432             :   }
     433             : 
     434          76 :   PetscCall(STRestoreOperator(eps->st,&Op));
     435          76 :   if (m>100) PetscCall(PetscFree5(omega,omega_old,which,which2,hwork));
     436          76 :   PetscFunctionReturn(PETSC_SUCCESS);
     437             : }
     438             : 
     439             : /*
     440             :    EPSBasicLanczos - Computes an m-step Lanczos factorization. The first k
     441             :    columns are assumed to be locked and therefore they are not modified. On
     442             :    exit, the following relation is satisfied:
     443             : 
     444             :                     OP * V - V * T = f * e_m^T
     445             : 
     446             :    where the columns of V are the Lanczos vectors, T is a tridiagonal matrix,
     447             :    f is the residual vector and e_m is the m-th vector of the canonical basis.
     448             :    The Lanczos vectors (together with vector f) are B-orthogonal (to working
     449             :    accuracy) if full reorthogonalization is being used, otherwise they are
     450             :    (B-)semi-orthogonal. On exit, beta contains the B-norm of f and the next
     451             :    Lanczos vector can be computed as v_{m+1} = f / beta.
     452             : 
     453             :    This function simply calls another function which depends on the selected
     454             :    reorthogonalization strategy.
     455             : */
     456         943 : static PetscErrorCode EPSBasicLanczos(EPS eps,PetscInt k,PetscInt *m,PetscReal *betam,PetscBool *breakdown,PetscReal anorm)
     457             : {
     458         943 :   EPS_LANCZOS        *lanczos = (EPS_LANCZOS*)eps->data;
     459         943 :   PetscScalar        *T;
     460         943 :   PetscInt           i,n=*m,ld;
     461         943 :   PetscReal          *alpha,*beta;
     462         943 :   BVOrthogRefineType orthog_ref;
     463         943 :   Mat                Op,M;
     464             : 
     465         943 :   PetscFunctionBegin;
     466         943 :   PetscCall(DSGetLeadingDimension(eps->ds,&ld));
     467         943 :   switch (lanczos->reorthog) {
     468         520 :     case EPS_LANCZOS_REORTHOG_LOCAL:
     469         520 :       PetscCall(DSGetArrayReal(eps->ds,DS_MAT_T,&alpha));
     470         520 :       beta = alpha + ld;
     471         520 :       PetscCall(EPSLocalLanczos(eps,alpha,beta,k,m,breakdown));
     472         520 :       *betam = beta[*m-1];
     473         520 :       PetscCall(DSRestoreArrayReal(eps->ds,DS_MAT_T,&alpha));
     474             :       break;
     475         286 :     case EPS_LANCZOS_REORTHOG_FULL:
     476         286 :       PetscCall(STGetOperator(eps->st,&Op));
     477         286 :       PetscCall(DSGetMat(eps->ds,DS_MAT_T,&M));
     478         286 :       PetscCall(BVMatLanczos(eps->V,Op,M,k,m,betam,breakdown));
     479         286 :       PetscCall(DSRestoreMat(eps->ds,DS_MAT_T,&M));
     480         286 :       PetscCall(STRestoreOperator(eps->st,&Op));
     481             :       break;
     482          38 :     case EPS_LANCZOS_REORTHOG_SELECTIVE:
     483          38 :       PetscCall(DSGetArrayReal(eps->ds,DS_MAT_T,&alpha));
     484          38 :       beta = alpha + ld;
     485          38 :       PetscCall(EPSSelectiveLanczos(eps,alpha,beta,k,m,breakdown,anorm));
     486          38 :       *betam = beta[*m-1];
     487          38 :       PetscCall(DSRestoreArrayReal(eps->ds,DS_MAT_T,&alpha));
     488             :       break;
     489          76 :     case EPS_LANCZOS_REORTHOG_PERIODIC:
     490             :     case EPS_LANCZOS_REORTHOG_PARTIAL:
     491          76 :       PetscCall(DSGetArrayReal(eps->ds,DS_MAT_T,&alpha));
     492          76 :       beta = alpha + ld;
     493          76 :       PetscCall(EPSPartialLanczos(eps,alpha,beta,k,m,breakdown,anorm));
     494          76 :       *betam = beta[*m-1];
     495          76 :       PetscCall(DSRestoreArrayReal(eps->ds,DS_MAT_T,&alpha));
     496             :       break;
     497          23 :     case EPS_LANCZOS_REORTHOG_DELAYED:
     498          23 :       PetscCall(PetscMalloc1(n*n,&T));
     499          23 :       PetscCall(BVGetOrthogonalization(eps->V,NULL,&orthog_ref,NULL,NULL));
     500          23 :       if (orthog_ref == BV_ORTHOG_REFINE_NEVER) PetscCall(EPSDelayedArnoldi1(eps,T,n,k,m,betam,breakdown));
     501          23 :       else PetscCall(EPSDelayedArnoldi(eps,T,n,k,m,betam,breakdown));
     502          23 :       n = *m;
     503          23 :       PetscCall(DSGetArrayReal(eps->ds,DS_MAT_T,&alpha));
     504          23 :       beta = alpha + ld;
     505         403 :       for (i=k;i<n-1;i++) {
     506         380 :         alpha[i] = PetscRealPart(T[n*i+i]);
     507         380 :         beta[i] = PetscRealPart(T[n*i+i+1]);
     508             :       }
     509          23 :       alpha[n-1] = PetscRealPart(T[n*(n-1)+n-1]);
     510          23 :       beta[n-1] = *betam;
     511          23 :       PetscCall(DSRestoreArrayReal(eps->ds,DS_MAT_T,&alpha));
     512          23 :       PetscCall(PetscFree(T));
     513             :       break;
     514             :   }
     515         943 :   PetscFunctionReturn(PETSC_SUCCESS);
     516             : }
     517             : 
     518          36 : static PetscErrorCode EPSSolve_Lanczos(EPS eps)
     519             : {
     520          36 :   EPS_LANCZOS    *lanczos = (EPS_LANCZOS*)eps->data;
     521          36 :   PetscInt       nconv,i,j,k,l,x,n,*perm,restart,ncv=eps->ncv,r,ld;
     522          36 :   Vec            vi,vj,w;
     523          36 :   Mat            U;
     524          36 :   PetscScalar    *Y,*ritz,stmp;
     525          36 :   PetscReal      *bnd,anorm,beta,norm,rtmp,resnorm;
     526          36 :   PetscBool      breakdown;
     527          36 :   char           *conv,ctmp;
     528             : 
     529          36 :   PetscFunctionBegin;
     530          36 :   PetscCall(DSGetLeadingDimension(eps->ds,&ld));
     531          36 :   PetscCall(PetscMalloc4(ncv,&ritz,ncv,&bnd,ncv,&perm,ncv,&conv));
     532             : 
     533             :   /* The first Lanczos vector is the normalized initial vector */
     534          36 :   PetscCall(EPSGetStartVector(eps,0,NULL));
     535             : 
     536             :   anorm = -1.0;
     537             :   nconv = 0;
     538             : 
     539             :   /* Restart loop */
     540         979 :   while (eps->reason == EPS_CONVERGED_ITERATING) {
     541         943 :     eps->its++;
     542             : 
     543             :     /* Compute an ncv-step Lanczos factorization */
     544         943 :     n = PetscMin(nconv+eps->mpd,ncv);
     545         943 :     PetscCall(DSSetDimensions(eps->ds,n,nconv,PETSC_DETERMINE));
     546         943 :     PetscCall(EPSBasicLanczos(eps,nconv,&n,&beta,&breakdown,anorm));
     547         943 :     PetscCall(DSSetDimensions(eps->ds,n,nconv,0));
     548         943 :     PetscCall(DSSetState(eps->ds,DS_STATE_INTERMEDIATE));
     549         943 :     PetscCall(BVSetActiveColumns(eps->V,nconv,n));
     550             : 
     551             :     /* Solve projected problem */
     552         943 :     PetscCall(DSSolve(eps->ds,ritz,NULL));
     553         943 :     PetscCall(DSSort(eps->ds,ritz,NULL,NULL,NULL,NULL));
     554         943 :     PetscCall(DSSynchronize(eps->ds,ritz,NULL));
     555             : 
     556             :     /* Estimate ||A|| */
     557       13384 :     for (i=nconv;i<n;i++)
     558       12868 :       anorm = PetscMax(anorm,PetscAbsReal(PetscRealPart(ritz[i])));
     559             : 
     560             :     /* Compute residual norm estimates as beta*abs(Y(m,:)) + eps*||A|| */
     561         943 :     PetscCall(DSGetArray(eps->ds,DS_MAT_Q,&Y));
     562       13384 :     for (i=nconv;i<n;i++) {
     563       12441 :       resnorm = beta*PetscAbsScalar(Y[n-1+i*ld]) + PETSC_MACHINE_EPSILON*anorm;
     564       12441 :       PetscCall((*eps->converged)(eps,ritz[i],eps->eigi[i],resnorm,&bnd[i],eps->convergedctx));
     565       12441 :       if (bnd[i]<eps->tol) conv[i] = 'C';
     566       12274 :       else conv[i] = 'N';
     567             :     }
     568         943 :     PetscCall(DSRestoreArray(eps->ds,DS_MAT_Q,&Y));
     569             : 
     570             :     /* purge repeated ritz values */
     571         943 :     if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL) {
     572        7016 :       for (i=nconv+1;i<n;i++) {
     573        6496 :         if (conv[i] == 'C' && PetscAbsScalar((ritz[i]-ritz[i-1])/ritz[i]) < eps->tol) conv[i] = 'R';
     574             :       }
     575             :     }
     576             : 
     577             :     /* Compute restart vector */
     578         943 :     if (breakdown) PetscCall(PetscInfo(eps,"Breakdown in Lanczos method (it=%" PetscInt_FMT " norm=%g)\n",eps->its,(double)beta));
     579             :     else {
     580             :       restart = nconv;
     581        1089 :       while (restart<n && conv[restart] != 'N') restart++;
     582         942 :       if (restart >= n) {
     583           0 :         breakdown = PETSC_TRUE;
     584             :       } else {
     585       12276 :         for (i=restart+1;i<n;i++) {
     586       11334 :           if (conv[i] == 'N') {
     587       11332 :             PetscCall(SlepcSCCompare(eps->sc,ritz[restart],0.0,ritz[i],0.0,&r));
     588       11332 :             if (r>0) restart = i;
     589             :           }
     590             :         }
     591         942 :         PetscCall(DSGetArray(eps->ds,DS_MAT_Q,&Y));
     592         942 :         PetscCall(BVMultColumn(eps->V,1.0,0.0,n,Y+restart*ld+nconv));
     593         942 :         PetscCall(DSRestoreArray(eps->ds,DS_MAT_Q,&Y));
     594             :       }
     595             :     }
     596             : 
     597             :     /* Count and put converged eigenvalues first */
     598       13384 :     for (i=nconv;i<n;i++) perm[i] = i;
     599        1109 :     for (k=nconv;k<n;k++) {
     600        1108 :       if (conv[perm[k]] != 'C') {
     601         944 :         j = k + 1;
     602       12279 :         while (j<n && conv[perm[j]] != 'C') j++;
     603         944 :         if (j>=n) break;
     604           2 :         l = perm[k]; perm[k] = perm[j]; perm[j] = l;
     605             :       }
     606             :     }
     607             : 
     608             :     /* Sort eigenvectors according to permutation */
     609         943 :     PetscCall(DSGetArray(eps->ds,DS_MAT_Q,&Y));
     610        1109 :     for (i=nconv;i<k;i++) {
     611         166 :       x = perm[i];
     612         166 :       if (x != i) {
     613           2 :         j = i + 1;
     614           4 :         while (perm[j] != i) j++;
     615             :         /* swap eigenvalues i and j */
     616           2 :         stmp = ritz[x]; ritz[x] = ritz[i]; ritz[i] = stmp;
     617           2 :         rtmp = bnd[x]; bnd[x] = bnd[i]; bnd[i] = rtmp;
     618           2 :         ctmp = conv[x]; conv[x] = conv[i]; conv[i] = ctmp;
     619           2 :         perm[j] = x; perm[i] = i;
     620             :         /* swap eigenvectors i and j */
     621          40 :         for (l=0;l<n;l++) {
     622          38 :           stmp = Y[l+x*ld]; Y[l+x*ld] = Y[l+i*ld]; Y[l+i*ld] = stmp;
     623             :         }
     624             :       }
     625             :     }
     626         943 :     PetscCall(DSRestoreArray(eps->ds,DS_MAT_Q,&Y));
     627             : 
     628             :     /* compute converged eigenvectors */
     629         943 :     PetscCall(DSGetMat(eps->ds,DS_MAT_Q,&U));
     630         943 :     PetscCall(BVMultInPlace(eps->V,U,nconv,k));
     631         943 :     PetscCall(DSRestoreMat(eps->ds,DS_MAT_Q,&U));
     632             : 
     633             :     /* purge spurious ritz values */
     634         943 :     if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL) {
     635         595 :       for (i=nconv;i<k;i++) {
     636          75 :         PetscCall(BVGetColumn(eps->V,i,&vi));
     637          75 :         PetscCall(VecNorm(vi,NORM_2,&norm));
     638          75 :         PetscCall(VecScale(vi,1.0/norm));
     639          75 :         w = eps->work[0];
     640          75 :         PetscCall(STApply(eps->st,vi,w));
     641          75 :         PetscCall(VecAXPY(w,-ritz[i],vi));
     642          75 :         PetscCall(BVRestoreColumn(eps->V,i,&vi));
     643          75 :         PetscCall(VecNorm(w,NORM_2,&norm));
     644          75 :         PetscCall((*eps->converged)(eps,ritz[i],eps->eigi[i],norm,&bnd[i],eps->convergedctx));
     645          75 :         if (bnd[i]>=eps->tol) conv[i] = 'S';
     646             :       }
     647         594 :       for (i=nconv;i<k;i++) {
     648          75 :         if (conv[i] != 'C') {
     649           1 :           j = i + 1;
     650           1 :           while (j<k && conv[j] != 'C') j++;
     651           1 :           if (j>=k) break;
     652             :           /* swap eigenvalues i and j */
     653           0 :           stmp = ritz[j]; ritz[j] = ritz[i]; ritz[i] = stmp;
     654           0 :           rtmp = bnd[j]; bnd[j] = bnd[i]; bnd[i] = rtmp;
     655           0 :           ctmp = conv[j]; conv[j] = conv[i]; conv[i] = ctmp;
     656             :           /* swap eigenvectors i and j */
     657           0 :           PetscCall(BVGetColumn(eps->V,i,&vi));
     658           0 :           PetscCall(BVGetColumn(eps->V,j,&vj));
     659           0 :           PetscCall(VecSwap(vi,vj));
     660           0 :           PetscCall(BVRestoreColumn(eps->V,i,&vi));
     661          74 :           PetscCall(BVRestoreColumn(eps->V,j,&vj));
     662             :         }
     663             :       }
     664             :       k = i;
     665             :     }
     666             : 
     667             :     /* store ritz values and estimated errors */
     668       13384 :     for (i=nconv;i<n;i++) {
     669       12441 :       eps->eigr[i] = ritz[i];
     670       12441 :       eps->errest[i] = bnd[i];
     671             :     }
     672         943 :     nconv = k;
     673         943 :     PetscCall(EPSMonitor(eps,eps->its,nconv,eps->eigr,eps->eigi,eps->errest,n));
     674         943 :     PetscCall((*eps->stopping)(eps,eps->its,eps->max_it,nconv,eps->nev,&eps->reason,eps->stoppingctx));
     675             : 
     676         943 :     if (eps->reason == EPS_CONVERGED_ITERATING) { /* copy restart vector */
     677         907 :       PetscCall(BVCopyColumn(eps->V,n,nconv));
     678         907 :       if (lanczos->reorthog == EPS_LANCZOS_REORTHOG_LOCAL && !breakdown) {
     679             :         /* Reorthonormalize restart vector */
     680         502 :         PetscCall(BVOrthonormalizeColumn(eps->V,nconv,PETSC_FALSE,NULL,&breakdown));
     681             :       }
     682         907 :       if (breakdown) {
     683             :         /* Use random vector for restarting */
     684           0 :         PetscCall(PetscInfo(eps,"Using random vector for restart\n"));
     685           0 :         PetscCall(EPSGetStartVector(eps,nconv,&breakdown));
     686             :       }
     687         907 :       if (PetscUnlikely(breakdown)) { /* give up */
     688           0 :         eps->reason = EPS_DIVERGED_BREAKDOWN;
     689         979 :         PetscCall(PetscInfo(eps,"Unable to generate more start vectors\n"));
     690             :       }
     691             :     }
     692             :   }
     693          36 :   eps->nconv = nconv;
     694             : 
     695          36 :   PetscCall(PetscFree4(ritz,bnd,perm,conv));
     696          36 :   PetscFunctionReturn(PETSC_SUCCESS);
     697             : }
     698             : 
     699          18 : static PetscErrorCode EPSSetFromOptions_Lanczos(EPS eps,PetscOptionItems *PetscOptionsObject)
     700             : {
     701          18 :   EPS_LANCZOS            *lanczos = (EPS_LANCZOS*)eps->data;
     702          18 :   PetscBool              flg;
     703          18 :   EPSLanczosReorthogType reorthog=EPS_LANCZOS_REORTHOG_LOCAL,curval;
     704             : 
     705          18 :   PetscFunctionBegin;
     706          18 :   PetscOptionsHeadBegin(PetscOptionsObject,"EPS Lanczos Options");
     707             : 
     708          18 :     curval = (lanczos->reorthog==(EPSLanczosReorthogType)-1)? EPS_LANCZOS_REORTHOG_LOCAL: lanczos->reorthog;
     709          18 :     PetscCall(PetscOptionsEnum("-eps_lanczos_reorthog","Lanczos reorthogonalization","EPSLanczosSetReorthog",EPSLanczosReorthogTypes,(PetscEnum)curval,(PetscEnum*)&reorthog,&flg));
     710          18 :     if (flg) PetscCall(EPSLanczosSetReorthog(eps,reorthog));
     711             : 
     712          18 :   PetscOptionsHeadEnd();
     713          18 :   PetscFunctionReturn(PETSC_SUCCESS);
     714             : }
     715             : 
     716          19 : static PetscErrorCode EPSLanczosSetReorthog_Lanczos(EPS eps,EPSLanczosReorthogType reorthog)
     717             : {
     718          19 :   EPS_LANCZOS *lanczos = (EPS_LANCZOS*)eps->data;
     719             : 
     720          19 :   PetscFunctionBegin;
     721          19 :   switch (reorthog) {
     722          19 :     case EPS_LANCZOS_REORTHOG_LOCAL:
     723             :     case EPS_LANCZOS_REORTHOG_FULL:
     724             :     case EPS_LANCZOS_REORTHOG_DELAYED:
     725             :     case EPS_LANCZOS_REORTHOG_SELECTIVE:
     726             :     case EPS_LANCZOS_REORTHOG_PERIODIC:
     727             :     case EPS_LANCZOS_REORTHOG_PARTIAL:
     728          19 :       if (lanczos->reorthog != reorthog) {
     729          19 :         lanczos->reorthog = reorthog;
     730          19 :         eps->state = EPS_STATE_INITIAL;
     731             :       }
     732          19 :       break;
     733           0 :     default:
     734           0 :       SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid reorthogonalization type");
     735             :   }
     736          19 :   PetscFunctionReturn(PETSC_SUCCESS);
     737             : }
     738             : 
     739             : /*@
     740             :    EPSLanczosSetReorthog - Sets the type of reorthogonalization used during the Lanczos
     741             :    iteration.
     742             : 
     743             :    Logically Collective
     744             : 
     745             :    Input Parameters:
     746             : +  eps - the eigenproblem solver context
     747             : -  reorthog - the type of reorthogonalization
     748             : 
     749             :    Options Database Key:
     750             : .  -eps_lanczos_reorthog - Sets the reorthogonalization type (either 'local', 'selective',
     751             :                          'periodic', 'partial', 'full' or 'delayed')
     752             : 
     753             :    Level: advanced
     754             : 
     755             : .seealso: EPSLanczosGetReorthog(), EPSLanczosReorthogType
     756             : @*/
     757          19 : PetscErrorCode EPSLanczosSetReorthog(EPS eps,EPSLanczosReorthogType reorthog)
     758             : {
     759          19 :   PetscFunctionBegin;
     760          19 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     761          57 :   PetscValidLogicalCollectiveEnum(eps,reorthog,2);
     762          19 :   PetscTryMethod(eps,"EPSLanczosSetReorthog_C",(EPS,EPSLanczosReorthogType),(eps,reorthog));
     763          19 :   PetscFunctionReturn(PETSC_SUCCESS);
     764             : }
     765             : 
     766           5 : static PetscErrorCode EPSLanczosGetReorthog_Lanczos(EPS eps,EPSLanczosReorthogType *reorthog)
     767             : {
     768           5 :   EPS_LANCZOS *lanczos = (EPS_LANCZOS*)eps->data;
     769             : 
     770           5 :   PetscFunctionBegin;
     771           5 :   *reorthog = lanczos->reorthog;
     772           5 :   PetscFunctionReturn(PETSC_SUCCESS);
     773             : }
     774             : 
     775             : /*@
     776             :    EPSLanczosGetReorthog - Gets the type of reorthogonalization used during
     777             :    the Lanczos iteration.
     778             : 
     779             :    Not Collective
     780             : 
     781             :    Input Parameter:
     782             : .  eps - the eigenproblem solver context
     783             : 
     784             :    Output Parameter:
     785             : .  reorthog - the type of reorthogonalization
     786             : 
     787             :    Level: advanced
     788             : 
     789             : .seealso: EPSLanczosSetReorthog(), EPSLanczosReorthogType
     790             : @*/
     791           5 : PetscErrorCode EPSLanczosGetReorthog(EPS eps,EPSLanczosReorthogType *reorthog)
     792             : {
     793           5 :   PetscFunctionBegin;
     794           5 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     795           5 :   PetscAssertPointer(reorthog,2);
     796           5 :   PetscUseMethod(eps,"EPSLanczosGetReorthog_C",(EPS,EPSLanczosReorthogType*),(eps,reorthog));
     797           5 :   PetscFunctionReturn(PETSC_SUCCESS);
     798             : }
     799             : 
     800          22 : static PetscErrorCode EPSReset_Lanczos(EPS eps)
     801             : {
     802          22 :   EPS_LANCZOS    *lanczos = (EPS_LANCZOS*)eps->data;
     803             : 
     804          22 :   PetscFunctionBegin;
     805          22 :   PetscCall(BVDestroy(&lanczos->AV));
     806          22 :   lanczos->allocsize = 0;
     807          22 :   PetscFunctionReturn(PETSC_SUCCESS);
     808             : }
     809             : 
     810          19 : static PetscErrorCode EPSDestroy_Lanczos(EPS eps)
     811             : {
     812          19 :   PetscFunctionBegin;
     813          19 :   PetscCall(PetscFree(eps->data));
     814          19 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSLanczosSetReorthog_C",NULL));
     815          19 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSLanczosGetReorthog_C",NULL));
     816          19 :   PetscFunctionReturn(PETSC_SUCCESS);
     817             : }
     818             : 
     819           0 : static PetscErrorCode EPSView_Lanczos(EPS eps,PetscViewer viewer)
     820             : {
     821           0 :   EPS_LANCZOS    *lanczos = (EPS_LANCZOS*)eps->data;
     822           0 :   PetscBool      isascii;
     823             : 
     824           0 :   PetscFunctionBegin;
     825           0 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     826           0 :   if (isascii) {
     827           0 :     if (lanczos->reorthog != (EPSLanczosReorthogType)-1) PetscCall(PetscViewerASCIIPrintf(viewer,"  %s reorthogonalization\n",EPSLanczosReorthogTypes[lanczos->reorthog]));
     828             :   }
     829           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     830             : }
     831             : 
     832          19 : SLEPC_EXTERN PetscErrorCode EPSCreate_Lanczos(EPS eps)
     833             : {
     834          19 :   EPS_LANCZOS    *ctx;
     835             : 
     836          19 :   PetscFunctionBegin;
     837          19 :   PetscCall(PetscNew(&ctx));
     838          19 :   eps->data = (void*)ctx;
     839          19 :   ctx->reorthog = (EPSLanczosReorthogType)-1;
     840             : 
     841          19 :   eps->useds = PETSC_TRUE;
     842             : 
     843          19 :   eps->ops->solve          = EPSSolve_Lanczos;
     844          19 :   eps->ops->setup          = EPSSetUp_Lanczos;
     845          19 :   eps->ops->setupsort      = EPSSetUpSort_Default;
     846          19 :   eps->ops->setfromoptions = EPSSetFromOptions_Lanczos;
     847          19 :   eps->ops->destroy        = EPSDestroy_Lanczos;
     848          19 :   eps->ops->reset          = EPSReset_Lanczos;
     849          19 :   eps->ops->view           = EPSView_Lanczos;
     850          19 :   eps->ops->backtransform  = EPSBackTransform_Default;
     851          19 :   eps->ops->computevectors = EPSComputeVectors_Hermitian;
     852             : 
     853          19 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSLanczosSetReorthog_C",EPSLanczosSetReorthog_Lanczos));
     854          19 :   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSLanczosGetReorthog_C",EPSLanczosGetReorthog_Lanczos));
     855          19 :   PetscFunctionReturn(PETSC_SUCCESS);
     856             : }

Generated by: LCOV version 1.14