LCOV - code coverage report
Current view: top level - pep/impls/jd - pjd.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 1215 1247 97.4 %
Date: 2024-11-23 00:34:26 Functions: 44 45 97.8 %
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 polynomial eigensolver: "jd"
      12             : 
      13             :    Method: Jacobi-Davidson
      14             : 
      15             :    Algorithm:
      16             : 
      17             :        Jacobi-Davidson for polynomial eigenvalue problems.
      18             : 
      19             :    References:
      20             : 
      21             :        [1] C. Campos and J.E. Roman, "A polynomial Jacobi-Davidson solver
      22             :            with support for non-monomial bases and deflation", BIT Numer.
      23             :            Math. 60:295-318, 2020.
      24             : 
      25             :        [2] G.L.G. Sleijpen et al., "Jacobi-Davidson type methods for
      26             :            generalized eigenproblems and polynomial eigenproblems", BIT
      27             :            36(3):595-633, 1996.
      28             : 
      29             :        [3] Feng-Nan Hwang, Zih-Hao Wei, Tsung-Ming Huang, Weichung Wang,
      30             :            "A Parallel Additive Schwarz Preconditioned Jacobi-Davidson
      31             :            Algorithm for Polynomial Eigenvalue Problems in Quantum Dot
      32             :            Simulation", J. Comput. Phys. 229(8):2932-2947, 2010.
      33             : */
      34             : 
      35             : #include <slepc/private/pepimpl.h>    /*I "slepcpep.h" I*/
      36             : #include <slepcblaslapack.h>
      37             : 
      38             : static PetscBool  cited = PETSC_FALSE;
      39             : static const char citation[] =
      40             :   "@Article{slepc-slice-qep,\n"
      41             :   "   author = \"C. Campos and J. E. Roman\",\n"
      42             :   "   title = \"A polynomial {Jacobi-Davidson} solver with support for non-monomial bases and deflation\",\n"
      43             :   "   journal = \"{BIT} Numer. Math.\",\n"
      44             :   "   volume = \"60\",\n"
      45             :   "   pages = \"295--318\",\n"
      46             :   "   year = \"2020,\"\n"
      47             :   "   doi = \"https://doi.org/10.1007/s10543-019-00778-z\"\n"
      48             :   "}\n";
      49             : 
      50             : typedef struct {
      51             :   PetscReal   keep;          /* restart parameter */
      52             :   PetscReal   fix;           /* fix parameter */
      53             :   PetscBool   reusepc;       /* flag indicating whether pc is rebuilt or not */
      54             :   BV          V;             /* work basis vectors to store the search space */
      55             :   BV          W;             /* work basis vectors to store the test space */
      56             :   BV          *TV;           /* work basis vectors to store T*V (each TV[i] is the coefficient for \lambda^i of T*V for the extended T) */
      57             :   BV          *AX;           /* work basis vectors to store A_i*X for locked eigenvectors */
      58             :   BV          N[2];          /* auxiliary work BVs */
      59             :   BV          X;             /* locked eigenvectors */
      60             :   PetscScalar *T;            /* matrix of the invariant pair */
      61             :   PetscScalar *Tj;           /* matrix containing the powers of the invariant pair matrix */
      62             :   PetscScalar *XpX;          /* X^H*X */
      63             :   PetscInt    ld;            /* leading dimension for Tj and XpX */
      64             :   PC          pcshell;       /* preconditioner including basic precond+projector */
      65             :   Mat         Pshell;        /* auxiliary shell matrix */
      66             :   PetscInt    nlock;         /* number of locked vectors in the invariant pair */
      67             :   Vec         vtempl;        /* reference nested vector */
      68             :   PetscInt    midx;          /* minimality index */
      69             :   PetscInt    mmidx;         /* maximum allowed minimality index */
      70             :   PEPJDProjection proj;      /* projection type (orthogonal, harmonic) */
      71             : } PEP_JD;
      72             : 
      73             : typedef struct {
      74             :   PEP         pep;
      75             :   PC          pc;            /* basic preconditioner */
      76             :   Vec         Bp[2];         /* preconditioned residual of derivative polynomial, B\p */
      77             :   Vec         u[2];          /* Ritz vector */
      78             :   PetscScalar gamma[2];      /* precomputed scalar u'*B\p */
      79             :   PetscScalar theta;
      80             :   PetscScalar *M;
      81             :   PetscScalar *ps;
      82             :   PetscInt    ld;
      83             :   Vec         *work;
      84             :   Mat         PPr;
      85             :   BV          X;
      86             :   PetscInt    n;
      87             : } PEP_JD_PCSHELL;
      88             : 
      89             : typedef struct {
      90             :   Mat         Pr,Pi;         /* matrix polynomial evaluated at theta */
      91             :   PEP         pep;
      92             :   Vec         *work;
      93             :   PetscScalar theta[2];
      94             : } PEP_JD_MATSHELL;
      95             : 
      96             : /*
      97             :    Duplicate and resize auxiliary basis
      98             : */
      99          55 : static PetscErrorCode PEPJDDuplicateBasis(PEP pep,BV *basis)
     100             : {
     101          55 :   PEP_JD             *pjd = (PEP_JD*)pep->data;
     102          55 :   PetscInt           nloc,m;
     103          55 :   BVType             type;
     104          55 :   BVOrthogType       otype;
     105          55 :   BVOrthogRefineType oref;
     106          55 :   PetscReal          oeta;
     107          55 :   BVOrthogBlockType  oblock;
     108          55 :   VecType            vtype;
     109             : 
     110          55 :   PetscFunctionBegin;
     111          55 :   if (pjd->ld>1) {
     112          55 :     PetscCall(BVCreate(PetscObjectComm((PetscObject)pep),basis));
     113          55 :     PetscCall(BVGetSizes(pep->V,&nloc,NULL,&m));
     114          55 :     nloc += pjd->ld-1;
     115          55 :     PetscCall(BVSetSizes(*basis,nloc,PETSC_DECIDE,m));
     116          55 :     PetscCall(BVGetType(pep->V,&type));
     117          55 :     PetscCall(BVSetType(*basis,type));
     118          55 :     PetscCall(BVGetVecType(pep->V,&vtype));
     119          55 :     PetscCall(BVSetVecType(*basis,vtype));
     120          55 :     PetscCall(BVGetOrthogonalization(pep->V,&otype,&oref,&oeta,&oblock));
     121          55 :     PetscCall(BVSetOrthogonalization(*basis,otype,oref,oeta,oblock));
     122          55 :     PetscCall(PetscObjectStateIncrease((PetscObject)*basis));
     123           0 :   } else PetscCall(BVDuplicate(pep->V,basis));
     124          55 :   PetscFunctionReturn(PETSC_SUCCESS);
     125             : }
     126             : 
     127          11 : static PetscErrorCode PEPSetUp_JD(PEP pep)
     128             : {
     129          11 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
     130          11 :   PetscBool      isprecond,flg;
     131          11 :   PetscRandom    rand;
     132          11 :   PetscInt       i;
     133             : 
     134          11 :   PetscFunctionBegin;
     135          11 :   PetscCall(PEPSetDimensions_Default(pep,pep->nev,&pep->ncv,&pep->mpd));
     136          11 :   if (pep->max_it==PETSC_DETERMINE) pep->max_it = PetscMax(100,2*pep->n/pep->ncv);
     137          11 :   if (!pep->which) pep->which = PEP_TARGET_MAGNITUDE;
     138          11 :   PetscCheck(pep->which==PEP_TARGET_MAGNITUDE || pep->which==PEP_TARGET_REAL || pep->which==PEP_TARGET_IMAGINARY,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"The JD solver supports only target which, see PEPSetWhichEigenpairs()");
     139             : 
     140          11 :   PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STPRECOND,&isprecond));
     141          11 :   PetscCheck(isprecond,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"The JD solver only works with PRECOND spectral transformation");
     142             : 
     143          11 :   PetscCall(STGetTransform(pep->st,&flg));
     144          11 :   PetscCheck(!flg,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"The JD solver requires the ST transform flag unset, see STSetTransform()");
     145          11 :   PEPCheckIgnored(pep,PEP_FEATURE_EXTRACT);
     146             : 
     147          11 :   if (!pjd->mmidx) pjd->mmidx = pep->nmat-1;
     148          11 :   pjd->mmidx = PetscMin(pjd->mmidx,pep->nmat-1);
     149          11 :   if (!pjd->keep) pjd->keep = 0.5;
     150          11 :   PetscCall(PEPBasisCoefficients(pep,pep->pbc));
     151          11 :   PetscCall(PEPAllocateSolution(pep,0));
     152          11 :   PetscCall(BVGetRandomContext(pep->V,&rand));  /* make sure the random context is available when duplicating */
     153          11 :   PetscCall(PEPSetWorkVecs(pep,5));
     154          11 :   pjd->ld = pep->nev;
     155             : #if !defined (PETSC_USE_COMPLEX)
     156          11 :   pjd->ld++;
     157             : #endif
     158          11 :   PetscCall(PetscMalloc2(pep->nmat,&pjd->TV,pep->nmat,&pjd->AX));
     159          46 :   for (i=0;i<pep->nmat;i++) PetscCall(PEPJDDuplicateBasis(pep,pjd->TV+i));
     160          11 :   if (pjd->ld>1) {
     161          11 :     PetscCall(PEPJDDuplicateBasis(pep,&pjd->V));
     162          11 :     PetscCall(BVSetFromOptions(pjd->V));
     163          46 :     for (i=0;i<pep->nmat;i++) PetscCall(BVDuplicateResize(pep->V,pjd->ld-1,pjd->AX+i));
     164          11 :     PetscCall(BVDuplicateResize(pep->V,pjd->ld-1,pjd->N));
     165          11 :     PetscCall(BVDuplicateResize(pep->V,pjd->ld-1,pjd->N+1));
     166          11 :     pjd->X = pep->V;
     167          11 :     PetscCall(PetscCalloc3(pjd->ld*pjd->ld,&pjd->XpX,pep->ncv*pep->ncv,&pjd->T,pjd->ld*pjd->ld*pep->nmat,&pjd->Tj));
     168           0 :   } else pjd->V = pep->V;
     169          11 :   if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) PetscCall(PEPJDDuplicateBasis(pep,&pjd->W));
     170           2 :   else pjd->W = pjd->V;
     171          11 :   PetscCall(DSSetType(pep->ds,DSPEP));
     172          11 :   PetscCall(DSPEPSetDegree(pep->ds,pep->nmat-1));
     173          11 :   if (pep->basis!=PEP_BASIS_MONOMIAL) PetscCall(DSPEPSetCoefficients(pep->ds,pep->pbc));
     174          11 :   PetscCall(DSAllocate(pep->ds,pep->ncv));
     175          11 :   PetscFunctionReturn(PETSC_SUCCESS);
     176             : }
     177             : 
     178             : /*
     179             :    Updates columns (low to (high-1)) of TV[i]
     180             : */
     181         264 : static PetscErrorCode PEPJDUpdateTV(PEP pep,PetscInt low,PetscInt high,Vec *w)
     182             : {
     183         264 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
     184         264 :   PetscInt       pp,col,i,nloc,nconv;
     185         264 :   Vec            v1,v2,t1,t2;
     186         264 :   PetscScalar    *array1,*array2,*x2,*xx,*N,*Np,*y2=NULL,zero=0.0,sone=1.0,*pT,fact,*psc;
     187         264 :   PetscReal      *cg,*ca,*cb;
     188         264 :   PetscMPIInt    rk,np;
     189         264 :   PetscBLASInt   n_,ld_,one=1;
     190         264 :   Mat            T;
     191         264 :   BV             pbv;
     192             : 
     193         264 :   PetscFunctionBegin;
     194         264 :   ca = pep->pbc; cb = ca+pep->nmat; cg = cb + pep->nmat;
     195         264 :   nconv = pjd->nlock;
     196         264 :   PetscCall(PetscMalloc5(nconv,&x2,nconv,&xx,nconv*nconv,&pT,nconv*nconv,&N,nconv*nconv,&Np));
     197         264 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rk));
     198         264 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np));
     199         264 :   PetscCall(BVGetSizes(pep->V,&nloc,NULL,NULL));
     200         264 :   t1 = w[0];
     201         264 :   t2 = w[1];
     202         264 :   PetscCall(PetscBLASIntCast(pjd->nlock,&n_));
     203         264 :   PetscCall(PetscBLASIntCast(pjd->ld,&ld_));
     204         264 :   if (nconv) {
     205         189 :     for (i=0;i<nconv;i++) PetscCall(PetscArraycpy(pT+i*nconv,pjd->T+i*pep->ncv,nconv));
     206          68 :     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,nconv,nconv,pT,&T));
     207             :   }
     208         835 :   for (col=low;col<high;col++) {
     209         571 :     PetscCall(BVGetColumn(pjd->V,col,&v1));
     210         571 :     PetscCall(VecGetArray(v1,&array1));
     211         571 :     if (nconv>0) {
     212         792 :       for (i=0;i<nconv;i++) x2[i] = array1[nloc+i]* PetscSqrtReal(np);
     213             :     }
     214         571 :     PetscCall(VecPlaceArray(t1,array1));
     215         571 :     if (nconv) {
     216         258 :       PetscCall(BVSetActiveColumns(pjd->N[0],0,nconv));
     217         258 :       PetscCall(BVSetActiveColumns(pjd->N[1],0,nconv));
     218         258 :       PetscCall(BVDotVec(pjd->X,t1,xx));
     219             :     }
     220        2325 :     for (pp=pep->nmat-1;pp>=0;pp--) {
     221        1754 :       PetscCall(BVGetColumn(pjd->TV[pp],col,&v2));
     222        1754 :       PetscCall(VecGetArray(v2,&array2));
     223        1754 :       PetscCall(VecPlaceArray(t2,array2));
     224        1754 :       PetscCall(MatMult(pep->A[pp],t1,t2));
     225        1754 :       if (nconv) {
     226         800 :         if (pp<pep->nmat-3) {
     227          26 :           PetscCall(BVMult(pjd->N[0],1.0,-cg[pp+2],pjd->AX[pp+1],NULL));
     228          26 :           PetscCall(MatShift(T,-cb[pp+1]));
     229          26 :           PetscCall(BVMult(pjd->N[0],1.0/ca[pp],1.0/ca[pp],pjd->N[1],T));
     230          26 :           pbv = pjd->N[0]; pjd->N[0] = pjd->N[1]; pjd->N[1] = pbv;
     231          26 :           PetscCall(BVMultVec(pjd->N[1],1.0,1.0,t2,x2));
     232          26 :           PetscCall(MatShift(T,cb[pp+1]));
     233         774 :         } else if (pp==pep->nmat-3) {
     234         258 :           PetscCall(BVCopy(pjd->AX[pp+2],pjd->N[0]));
     235         258 :           PetscCall(BVScale(pjd->N[0],1/ca[pp+1]));
     236         258 :           PetscCall(BVCopy(pjd->AX[pp+1],pjd->N[1]));
     237         258 :           PetscCall(MatShift(T,-cb[pp+1]));
     238         258 :           PetscCall(BVMult(pjd->N[1],1.0/ca[pp],1.0/ca[pp],pjd->N[0],T));
     239         258 :           PetscCall(BVMultVec(pjd->N[1],1.0,1.0,t2,x2));
     240         258 :           PetscCall(MatShift(T,cb[pp+1]));
     241         516 :         } else if (pp==pep->nmat-2) PetscCall(BVMultVec(pjd->AX[pp+1],1.0/ca[pp],1.0,t2,x2));
     242         800 :         if (pp<pjd->midx) {
     243         397 :           y2 = array2+nloc;
     244         397 :           PetscCallBLAS("BLASgemv",BLASgemv_("C",&n_,&n_,&sone,pjd->Tj+pjd->ld*pjd->ld*pp,&ld_,xx,&one,&zero,y2,&one));
     245         397 :           if (pp<pjd->midx-2) {
     246           0 :             fact = -cg[pp+2];
     247           0 :             PetscCallBLAS("BLASgemm",BLASgemm_("C","N",&n_,&n_,&n_,&sone,pjd->Tj+(pp+1)*pjd->ld*pjd->ld,&ld_,pjd->XpX,&ld_,&fact,Np,&n_));
     248           0 :             fact = 1/ca[pp];
     249           0 :             PetscCall(MatShift(T,-cb[pp+1]));
     250           0 :             PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&fact,N,&n_,pT,&n_,&fact,Np,&n_));
     251           0 :             PetscCall(MatShift(T,cb[pp+1]));
     252           0 :             psc = Np; Np = N; N = psc;
     253           0 :             PetscCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,N,&n_,x2,&one,&sone,y2,&one));
     254         397 :           } else if (pp==pjd->midx-2) {
     255         139 :             fact = 1/ca[pp];
     256         139 :             PetscCallBLAS("BLASgemm",BLASgemm_("C","N",&n_,&n_,&n_,&fact,pjd->Tj+(pp+1)*pjd->ld*pjd->ld,&ld_,pjd->XpX,&ld_,&zero,N,&n_));
     257         139 :             PetscCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,N,&n_,x2,&one,&sone,y2,&one));
     258         258 :           } else if (pp==pjd->midx-1) PetscCall(PetscArrayzero(Np,nconv*nconv));
     259             :         }
     260        2428 :         for (i=0;i<nconv;i++) array2[nloc+i] /= PetscSqrtReal(np);
     261             :       }
     262        1754 :       PetscCall(VecResetArray(t2));
     263        1754 :       PetscCall(VecRestoreArray(v2,&array2));
     264        1754 :       PetscCall(BVRestoreColumn(pjd->TV[pp],col,&v2));
     265             :     }
     266         571 :     PetscCall(VecResetArray(t1));
     267         571 :     PetscCall(VecRestoreArray(v1,&array1));
     268         571 :     PetscCall(BVRestoreColumn(pjd->V,col,&v1));
     269             :   }
     270         264 :   if (nconv) PetscCall(MatDestroy(&T));
     271         264 :   PetscCall(PetscFree5(x2,xx,pT,N,Np));
     272         264 :   PetscFunctionReturn(PETSC_SUCCESS);
     273             : }
     274             : 
     275             : /*
     276             :    RRQR of X. Xin*P=Xou*R. Rank of R is rk
     277             : */
     278          47 : static PetscErrorCode PEPJDOrthogonalize(PetscInt row,PetscInt col,PetscScalar *X,PetscInt ldx,PetscInt *rk,PetscInt *P,PetscScalar *R,PetscInt ldr)
     279             : {
     280          47 :   PetscInt       i,j,n,r;
     281          47 :   PetscBLASInt   row_,col_,ldx_,*p,lwork,info,n_;
     282          47 :   PetscScalar    *tau,*work;
     283          47 :   PetscReal      tol,*rwork;
     284             : 
     285          47 :   PetscFunctionBegin;
     286          47 :   PetscCall(PetscBLASIntCast(row,&row_));
     287          47 :   PetscCall(PetscBLASIntCast(col,&col_));
     288          47 :   PetscCall(PetscBLASIntCast(ldx,&ldx_));
     289          47 :   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
     290          47 :   n = PetscMin(row,col);
     291          47 :   PetscCall(PetscBLASIntCast(n,&n_));
     292          47 :   lwork = 3*col_+1;
     293          47 :   PetscCall(PetscMalloc4(col,&p,n,&tau,lwork,&work,2*col,&rwork));
     294         442 :   for (i=1;i<col;i++) p[i] = 0;
     295          47 :   p[0] = 1;
     296             : 
     297             :   /* rank revealing QR */
     298             : #if defined(PETSC_USE_COMPLEX)
     299             :   PetscCallBLAS("LAPACKgeqp3",LAPACKgeqp3_(&row_,&col_,X,&ldx_,p,tau,work,&lwork,rwork,&info));
     300             : #else
     301          47 :   PetscCallBLAS("LAPACKgeqp3",LAPACKgeqp3_(&row_,&col_,X,&ldx_,p,tau,work,&lwork,&info));
     302             : #endif
     303          47 :   SlepcCheckLapackInfo("geqp3",info);
     304         241 :   if (P) for (i=0;i<col;i++) P[i] = p[i]-1;
     305             : 
     306             :   /* rank computation */
     307          47 :   tol = PetscMax(row,col)*PETSC_MACHINE_EPSILON*PetscAbsScalar(X[0]);
     308          47 :   r = 1;
     309         442 :   for (i=1;i<n;i++) {
     310         395 :     if (PetscAbsScalar(X[i+ldx*i])>tol) r++;
     311             :     else break;
     312             :   }
     313          47 :   if (rk) *rk=r;
     314             : 
     315             :   /* copy upper triangular matrix if requested */
     316          47 :   if (R) {
     317         209 :      for (i=0;i<r;i++) {
     318         194 :        PetscCall(PetscArrayzero(R+i*ldr,r));
     319        1703 :        for (j=0;j<=i;j++) R[i*ldr+j] = X[i*ldx+j];
     320             :      }
     321             :   }
     322          47 :   PetscCallBLAS("LAPACKorgqr",LAPACKorgqr_(&row_,&n_,&n_,X,&ldx_,tau,work,&lwork,&info));
     323          47 :   SlepcCheckLapackInfo("orgqr",info);
     324          47 :   PetscCall(PetscFPTrapPop());
     325          47 :   PetscCall(PetscFree4(p,tau,work,rwork));
     326          47 :   PetscFunctionReturn(PETSC_SUCCESS);
     327             : }
     328             : 
     329             : /*
     330             :    Application of extended preconditioner
     331             : */
     332        4925 : static PetscErrorCode PEPJDExtendedPCApply(PC pc,Vec x,Vec y)
     333             : {
     334        4925 :   PetscInt          i,j,nloc,n,ld=0;
     335        4925 :   PetscMPIInt       np;
     336        4925 :   Vec               tx,ty;
     337        4925 :   PEP_JD_PCSHELL    *ctx;
     338        4925 :   const PetscScalar *array1;
     339        4925 :   PetscScalar       *x2=NULL,*t=NULL,*ps=NULL,*array2,zero=0.0,sone=1.0;
     340        4925 :   PetscBLASInt      one=1,ld_,n_,ncv_;
     341        4925 :   PEP_JD            *pjd=NULL;
     342             : 
     343        4925 :   PetscFunctionBegin;
     344        4925 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&np));
     345        4925 :   PetscCall(PCShellGetContext(pc,&ctx));
     346        4925 :   n  = ctx->n;
     347        4925 :   if (n) {
     348        2196 :     pjd = (PEP_JD*)ctx->pep->data;
     349        2196 :     ps = ctx->ps;
     350        2196 :     ld = pjd->ld;
     351        2196 :     PetscCall(PetscMalloc2(n,&x2,n,&t));
     352        2196 :     PetscCall(VecGetLocalSize(ctx->work[0],&nloc));
     353        2196 :     PetscCall(VecGetArrayRead(x,&array1));
     354        4982 :     for (i=0;i<n;i++) x2[i] = array1[nloc+i]* PetscSqrtReal(np);
     355        2196 :     PetscCall(VecRestoreArrayRead(x,&array1));
     356             :   }
     357             : 
     358             :   /* y = B\x apply PC */
     359        4925 :   tx = ctx->work[0];
     360        4925 :   ty = ctx->work[1];
     361        4925 :   PetscCall(VecGetArrayRead(x,&array1));
     362        4925 :   PetscCall(VecPlaceArray(tx,array1));
     363        4925 :   PetscCall(VecGetArray(y,&array2));
     364        4925 :   PetscCall(VecPlaceArray(ty,array2));
     365        4925 :   PetscCall(PCApply(ctx->pc,tx,ty));
     366        4925 :   if (n) {
     367        2196 :     PetscCall(PetscBLASIntCast(ld,&ld_));
     368        2196 :     PetscCall(PetscBLASIntCast(n,&n_));
     369        4982 :     for (i=0;i<n;i++) {
     370        2786 :       t[i] = 0.0;
     371        7096 :       for (j=0;j<n;j++) t[i] += ctx->M[i+j*ld]*x2[j];
     372             :     }
     373        2196 :     if (pjd->midx==1) {
     374        1808 :       PetscCall(PetscBLASIntCast(ctx->pep->ncv,&ncv_));
     375        3664 :       for (i=0;i<n;i++) pjd->T[i*(1+ctx->pep->ncv)] -= ctx->theta;
     376        1808 :       PetscCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,pjd->T,&ncv_,t,&one,&zero,x2,&one));
     377        3664 :       for (i=0;i<n;i++) pjd->T[i*(1+ctx->pep->ncv)] += ctx->theta;
     378        3664 :       for (i=0;i<n;i++) array2[nloc+i] = x2[i];
     379        3664 :       for (i=0;i<n;i++) x2[i] = -t[i];
     380             :     } else {
     381        1318 :       for (i=0;i<n;i++) array2[nloc+i] = t[i];
     382         388 :       PetscCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,ps,&ld_,t,&one,&zero,x2,&one));
     383             :     }
     384        4982 :     for (i=0;i<n;i++) array2[nloc+i] /= PetscSqrtReal(np);
     385        2196 :     PetscCall(BVSetActiveColumns(pjd->X,0,n));
     386        2196 :     PetscCall(BVMultVec(pjd->X,-1.0,1.0,ty,x2));
     387        2196 :     PetscCall(PetscFree2(x2,t));
     388             :   }
     389        4925 :   PetscCall(VecResetArray(tx));
     390        4925 :   PetscCall(VecResetArray(ty));
     391        4925 :   PetscCall(VecRestoreArrayRead(x,&array1));
     392        4925 :   PetscCall(VecRestoreArray(y,&array2));
     393        4925 :   PetscFunctionReturn(PETSC_SUCCESS);
     394             : }
     395             : 
     396             : /*
     397             :    Application of shell preconditioner:
     398             :       y = B\x - eta*B\p,  with eta = (u'*B\x)/(u'*B\p)
     399             : */
     400        4437 : static PetscErrorCode PCShellApply_PEPJD(PC pc,Vec x,Vec y)
     401             : {
     402        4437 :   PetscScalar    rr,eta;
     403        4437 :   PEP_JD_PCSHELL *ctx;
     404        4437 :   PetscInt       sz;
     405        4437 :   const Vec      *xs,*ys;
     406             : #if !defined(PETSC_USE_COMPLEX)
     407        4437 :   PetscScalar    rx,xr,xx;
     408             : #endif
     409             : 
     410        4437 :   PetscFunctionBegin;
     411        4437 :   PetscCall(PCShellGetContext(pc,&ctx));
     412        4437 :   PetscCall(VecCompGetSubVecs(x,&sz,&xs));
     413        4437 :   PetscCall(VecCompGetSubVecs(y,NULL,&ys));
     414             :   /* y = B\x apply extended PC */
     415        4437 :   PetscCall(PEPJDExtendedPCApply(pc,xs[0],ys[0]));
     416             : #if !defined(PETSC_USE_COMPLEX)
     417        4437 :   if (sz==2) PetscCall(PEPJDExtendedPCApply(pc,xs[1],ys[1]));
     418             : #endif
     419             : 
     420             :   /* Compute eta = u'*y / u'*Bp */
     421        4437 :   PetscCall(VecDot(ys[0],ctx->u[0],&rr));
     422        4437 :   eta  = -rr*ctx->gamma[0];
     423             : #if !defined(PETSC_USE_COMPLEX)
     424        4437 :   if (sz==2) {
     425         227 :     PetscCall(VecDot(ys[0],ctx->u[1],&xr));
     426         227 :     PetscCall(VecDot(ys[1],ctx->u[0],&rx));
     427         227 :     PetscCall(VecDot(ys[1],ctx->u[1],&xx));
     428         227 :     eta += -ctx->gamma[0]*xx-ctx->gamma[1]*(-xr+rx);
     429             :   }
     430             : #endif
     431        4437 :   eta /= ctx->gamma[0]*ctx->gamma[0]+ctx->gamma[1]*ctx->gamma[1];
     432             : 
     433             :   /* y = y - eta*Bp */
     434        4437 :   PetscCall(VecAXPY(ys[0],eta,ctx->Bp[0]));
     435             : #if !defined(PETSC_USE_COMPLEX)
     436        4437 :   if (sz==2) {
     437         227 :     PetscCall(VecAXPY(ys[1],eta,ctx->Bp[1]));
     438         227 :     eta = -ctx->gamma[1]*(rr+xx)+ctx->gamma[0]*(-xr+rx);
     439         227 :     eta /= ctx->gamma[0]*ctx->gamma[0]+ctx->gamma[1]*ctx->gamma[1];
     440         227 :     PetscCall(VecAXPY(ys[0],eta,ctx->Bp[1]));
     441         227 :     PetscCall(VecAXPY(ys[1],-eta,ctx->Bp[0]));
     442             :   }
     443             : #endif
     444        4437 :   PetscFunctionReturn(PETSC_SUCCESS);
     445             : }
     446             : 
     447         219 : static PetscErrorCode PEPJDCopyToExtendedVec(PEP pep,Vec v,PetscScalar *a,PetscInt na,PetscInt off,Vec vex,PetscBool back)
     448             : {
     449         219 :   PetscMPIInt    np,rk,count;
     450         219 :   PetscScalar    *array1,*array2;
     451         219 :   PetscInt       nloc;
     452             : 
     453         219 :   PetscFunctionBegin;
     454         219 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rk));
     455         219 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np));
     456         219 :   PetscCall(BVGetSizes(pep->V,&nloc,NULL,NULL));
     457         219 :   if (v) {
     458          33 :     PetscCall(VecGetArray(v,&array1));
     459          33 :     PetscCall(VecGetArray(vex,&array2));
     460          33 :     if (back) PetscCall(PetscArraycpy(array1,array2,nloc));
     461           0 :     else PetscCall(PetscArraycpy(array2,array1,nloc));
     462          33 :     PetscCall(VecRestoreArray(v,&array1));
     463          33 :     PetscCall(VecRestoreArray(vex,&array2));
     464             :   }
     465         219 :   if (a) {
     466         219 :     PetscCall(VecGetArray(vex,&array2));
     467         219 :     if (back) {
     468          33 :       PetscCall(PetscArraycpy(a,array2+nloc+off,na));
     469          33 :       PetscCall(PetscMPIIntCast(na,&count));
     470          66 :       PetscCallMPI(MPI_Bcast(a,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep)));
     471             :     } else {
     472         186 :       PetscCall(PetscArraycpy(array2+nloc+off,a,na));
     473         186 :       PetscCall(PetscMPIIntCast(na,&count));
     474         372 :       PetscCallMPI(MPI_Bcast(array2+nloc+off,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep)));
     475             :     }
     476         219 :     PetscCall(VecRestoreArray(vex,&array2));
     477             :   }
     478         219 :   PetscFunctionReturn(PETSC_SUCCESS);
     479             : }
     480             : 
     481             : /* Computes Phi^hat(lambda) times a vector or its derivative (depends on beval)
     482             :      if no vector is provided returns a matrix
     483             :  */
     484        9293 : static PetscErrorCode PEPJDEvaluateHatBasis(PEP pep,PetscInt n,PetscScalar *H,PetscInt ldh,PetscScalar *beval,PetscScalar *t,PetscInt idx,PetscScalar *qpp,PetscScalar *qp,PetscScalar *q)
     485             : {
     486        9293 :   PetscInt       j,i;
     487        9293 :   PetscBLASInt   n_,ldh_,one=1;
     488        9293 :   PetscReal      *a,*b,*g;
     489        9293 :   PetscScalar    sone=1.0,zero=0.0;
     490             : 
     491        9293 :   PetscFunctionBegin;
     492        9293 :   a = pep->pbc; b=a+pep->nmat; g=b+pep->nmat;
     493        9293 :   PetscCall(PetscBLASIntCast(n,&n_));
     494        9293 :   PetscCall(PetscBLASIntCast(ldh,&ldh_));
     495        9293 :   if (idx<1) PetscCall(PetscArrayzero(q,t?n:n*n));
     496        6730 :   else if (idx==1) {
     497        6107 :     if (t) {for (j=0;j<n;j++) q[j] = t[j]*beval[idx-1]/a[0];}
     498             :     else {
     499           0 :       PetscCall(PetscArrayzero(q,n*n));
     500           0 :       for (j=0;j<n;j++) q[(j+1)*n] = beval[idx-1]/a[0];
     501             :     }
     502             :   } else {
     503        4167 :     if (t) {
     504        4144 :       PetscCallBLAS("BLASgemv",BLASgemv_("N",&n_,&n_,&sone,H,&ldh_,qp,&one,&zero,q,&one));
     505        9269 :       for (j=0;j<n;j++) {
     506        5125 :         q[j] += beval[idx-1]*t[j]-b[idx-1]*qp[j]-g[idx-1]*qpp[j];
     507        5125 :         q[j] /= a[idx-1];
     508             :       }
     509             :     } else {
     510          23 :       PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&sone,H,&ldh_,qp,&n_,&zero,q,&n_));
     511          81 :       for (j=0;j<n;j++) {
     512          58 :         q[j+n*j] += beval[idx-1];
     513         210 :         for (i=0;i<n;i++) {
     514         152 :           q[i+n*j] += -b[idx-1]*qp[j*n+i]-g[idx-1]*qpp[j*n+i];
     515         152 :           q[i+n*j] /= a[idx-1];
     516             :         }
     517             :       }
     518             :     }
     519             :   }
     520        9293 :   PetscFunctionReturn(PETSC_SUCCESS);
     521             : }
     522             : 
     523         705 : static PetscErrorCode PEPJDComputeResidual(PEP pep,PetscBool derivative,PetscInt sz,Vec *u,PetscScalar *theta,Vec *p,Vec *work)
     524             : {
     525         705 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
     526         705 :   PetscMPIInt    rk,np,count;
     527         705 :   Vec            tu,tp,w;
     528         705 :   PetscScalar    *dval,*dvali,*array1,*array2,*x2=NULL,*y2,*qj=NULL,*tt=NULL,*xx=NULL,*xxi=NULL,sone=1.0;
     529         705 :   PetscInt       i,j,nconv,nloc;
     530         705 :   PetscBLASInt   n,ld,one=1;
     531             : #if !defined(PETSC_USE_COMPLEX)
     532         705 :   Vec            tui=NULL,tpi=NULL;
     533         705 :   PetscScalar    *x2i=NULL,*qji=NULL,*qq,*y2i,*arrayi1,*arrayi2;
     534             : #endif
     535             : 
     536         705 :   PetscFunctionBegin;
     537         705 :   nconv = pjd->nlock;
     538         705 :   if (!nconv) PetscCall(PetscMalloc1(2*sz*pep->nmat,&dval));
     539             :   else {
     540         623 :     PetscCall(PetscMalloc5(2*pep->nmat,&dval,2*nconv,&xx,nconv,&tt,sz*nconv,&x2,(sz==2?3:1)*nconv*pep->nmat,&qj));
     541         316 :     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rk));
     542         316 :     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np));
     543         316 :     PetscCall(BVGetSizes(pep->V,&nloc,NULL,NULL));
     544         316 :     PetscCall(VecGetArray(u[0],&array1));
     545         942 :     for (i=0;i<nconv;i++) x2[i] = array1[nloc+i]*PetscSqrtReal(np);
     546         316 :     PetscCall(VecRestoreArray(u[0],&array1));
     547             : #if !defined(PETSC_USE_COMPLEX)
     548         316 :     if (sz==2) {
     549           9 :       x2i = x2+nconv;
     550           9 :       PetscCall(VecGetArray(u[1],&arrayi1));
     551          27 :       for (i=0;i<nconv;i++) x2i[i] = arrayi1[nloc+i]*PetscSqrtReal(np);
     552           9 :       PetscCall(VecRestoreArray(u[1],&arrayi1));
     553             :     }
     554             : #endif
     555             :   }
     556         705 :   dvali = dval+pep->nmat;
     557         705 :   tu = work[0];
     558         705 :   tp = work[1];
     559         705 :   w  = work[2];
     560         705 :   PetscCall(VecGetArray(u[0],&array1));
     561         705 :   PetscCall(VecPlaceArray(tu,array1));
     562         705 :   PetscCall(VecGetArray(p[0],&array2));
     563         705 :   PetscCall(VecPlaceArray(tp,array2));
     564         705 :   PetscCall(VecSet(tp,0.0));
     565             : #if !defined(PETSC_USE_COMPLEX)
     566         705 :   if (sz==2) {
     567          57 :     tui = work[3];
     568          57 :     tpi = work[4];
     569          57 :     PetscCall(VecGetArray(u[1],&arrayi1));
     570          57 :     PetscCall(VecPlaceArray(tui,arrayi1));
     571          57 :     PetscCall(VecGetArray(p[1],&arrayi2));
     572          57 :     PetscCall(VecPlaceArray(tpi,arrayi2));
     573          57 :     PetscCall(VecSet(tpi,0.0));
     574             :   }
     575             : #endif
     576         705 :   if (derivative) PetscCall(PEPEvaluateBasisDerivative(pep,theta[0],theta[1],dval,dvali));
     577         459 :   else PetscCall(PEPEvaluateBasis(pep,theta[0],theta[1],dval,dvali));
     578        2647 :   for (i=derivative?1:0;i<pep->nmat;i++) {
     579        1942 :     PetscCall(MatMult(pep->A[i],tu,w));
     580        1942 :     PetscCall(VecAXPY(tp,dval[i],w));
     581             : #if !defined(PETSC_USE_COMPLEX)
     582        1942 :     if (sz==2) {
     583         147 :       PetscCall(VecAXPY(tpi,dvali[i],w));
     584         147 :       PetscCall(MatMult(pep->A[i],tui,w));
     585         147 :       PetscCall(VecAXPY(tpi,dval[i],w));
     586        1942 :       PetscCall(VecAXPY(tp,-dvali[i],w));
     587             :     }
     588             : #endif
     589             :   }
     590         705 :   if (nconv) {
     591        1305 :     for (i=0;i<pep->nmat;i++) PetscCall(PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dval,x2,i,i>1?qj+(i-2)*nconv:NULL,i>0?qj+(i-1)*nconv:NULL,qj+i*nconv));
     592             : #if !defined(PETSC_USE_COMPLEX)
     593         316 :     if (sz==2) {
     594           9 :       qji = qj+nconv*pep->nmat;
     595           9 :       qq = qji+nconv*pep->nmat;
     596          36 :       for (i=0;i<pep->nmat;i++) PetscCall(PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dvali,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv));
     597          63 :       for (i=0;i<nconv*pep->nmat;i++) qj[i] -= qji[i];
     598          36 :       for (i=0;i<pep->nmat;i++) {
     599          27 :         PetscCall(PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dval,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv));
     600          27 :         PetscCall(PEPJDEvaluateHatBasis(pep,nconv,pjd->T,pep->ncv,dvali,x2,i,i>1?qq+(i-2)*nconv:NULL,i>0?qq+(i-1)*nconv:NULL,qq+i*nconv));
     601             :       }
     602          63 :       for (i=0;i<nconv*pep->nmat;i++) qji[i] += qq[i];
     603          32 :       for (i=derivative?2:1;i<pep->nmat;i++) PetscCall(BVMultVec(pjd->AX[i],1.0,1.0,tpi,qji+i*nconv));
     604             :     }
     605             : #endif
     606        1241 :     for (i=derivative?2:1;i<pep->nmat;i++) PetscCall(BVMultVec(pjd->AX[i],1.0,1.0,tp,qj+i*nconv));
     607             : 
     608             :     /* extended vector part */
     609         316 :     PetscCall(BVSetActiveColumns(pjd->X,0,nconv));
     610         316 :     PetscCall(BVDotVec(pjd->X,tu,xx));
     611         316 :     xxi = xx+nconv;
     612             : #if !defined(PETSC_USE_COMPLEX)
     613         316 :     if (sz==2) PetscCall(BVDotVec(pjd->X,tui,xxi));
     614             : #endif
     615         316 :     if (sz==1) PetscCall(PetscArrayzero(xxi,nconv));
     616         316 :     if (rk==np-1) {
     617         277 :       PetscCall(PetscBLASIntCast(nconv,&n));
     618         277 :       PetscCall(PetscBLASIntCast(pjd->ld,&ld));
     619         277 :       y2  = array2+nloc;
     620         277 :       PetscCall(PetscArrayzero(y2,nconv));
     621         619 :       for (j=derivative?1:0;j<pjd->midx;j++) {
     622        1081 :         for (i=0;i<nconv;i++) tt[i] = dval[j]*xx[i]-dvali[j]*xxi[i];
     623         342 :         PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qj+j*nconv,&one,&sone,tt,&one));
     624         342 :         PetscCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2,&one));
     625             :       }
     626         805 :       for (i=0;i<nconv;i++) array2[nloc+i] /= PetscSqrtReal(np);
     627             : #if !defined(PETSC_USE_COMPLEX)
     628         277 :       if (sz==2) {
     629           9 :         y2i = arrayi2+nloc;
     630           9 :         PetscCall(PetscArrayzero(y2i,nconv));
     631          23 :         for (j=derivative?1:0;j<pjd->midx;j++) {
     632          42 :           for (i=0;i<nconv;i++) tt[i] = dval[j]*xxi[i]+dvali[j]*xx[i];
     633          14 :           PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qji+j*nconv,&one,&sone,tt,&one));
     634          14 :           PetscCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2i,&one));
     635             :         }
     636          27 :         for (i=0;i<nconv;i++) arrayi2[nloc+i] /= PetscSqrtReal(np);
     637             :       }
     638             : #endif
     639             :     }
     640         316 :     PetscCall(PetscMPIIntCast(nconv,&count));
     641         632 :     PetscCallMPI(MPI_Bcast(array2+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep)));
     642             : #if !defined(PETSC_USE_COMPLEX)
     643         325 :     if (sz==2) PetscCallMPI(MPI_Bcast(arrayi2+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep)));
     644             : #endif
     645             :   }
     646         705 :   if (nconv) PetscCall(PetscFree5(dval,xx,tt,x2,qj));
     647         389 :   else PetscCall(PetscFree(dval));
     648         705 :   PetscCall(VecResetArray(tu));
     649         705 :   PetscCall(VecRestoreArray(u[0],&array1));
     650         705 :   PetscCall(VecResetArray(tp));
     651         705 :   PetscCall(VecRestoreArray(p[0],&array2));
     652             : #if !defined(PETSC_USE_COMPLEX)
     653         705 :   if (sz==2) {
     654          57 :     PetscCall(VecResetArray(tui));
     655          57 :     PetscCall(VecRestoreArray(u[1],&arrayi1));
     656          57 :     PetscCall(VecResetArray(tpi));
     657          57 :     PetscCall(VecRestoreArray(p[1],&arrayi2));
     658             :   }
     659             : #endif
     660         705 :   PetscFunctionReturn(PETSC_SUCCESS);
     661             : }
     662             : 
     663          11 : static PetscErrorCode PEPJDProcessInitialSpace(PEP pep,Vec *w)
     664             : {
     665          11 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
     666          11 :   PetscScalar    *tt,target[2];
     667          11 :   Vec            vg,wg;
     668          11 :   PetscInt       i;
     669          11 :   PetscReal      norm;
     670             : 
     671          11 :   PetscFunctionBegin;
     672          11 :   PetscCall(PetscMalloc1(pjd->ld-1,&tt));
     673          11 :   PetscCheck(pep->nini==0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Support for initial vectors not implemented yet");
     674          11 :   PetscCall(BVSetRandomColumn(pjd->V,0));
     675          44 :   for (i=0;i<pjd->ld-1;i++) tt[i] = 0.0;
     676          11 :   PetscCall(BVGetColumn(pjd->V,0,&vg));
     677          11 :   PetscCall(PEPJDCopyToExtendedVec(pep,NULL,tt,pjd->ld-1,0,vg,PETSC_FALSE));
     678          11 :   PetscCall(BVRestoreColumn(pjd->V,0,&vg));
     679          11 :   PetscCall(BVNormColumn(pjd->V,0,NORM_2,&norm));
     680          11 :   PetscCall(BVScaleColumn(pjd->V,0,1.0/norm));
     681          11 :   if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
     682           9 :     PetscCall(BVGetColumn(pjd->V,0,&vg));
     683           9 :     PetscCall(BVGetColumn(pjd->W,0,&wg));
     684           9 :     PetscCall(VecSet(wg,0.0));
     685           9 :     target[0] = pep->target; target[1] = 0.0;
     686           9 :     PetscCall(PEPJDComputeResidual(pep,PETSC_TRUE,1,&vg,target,&wg,w));
     687           9 :     PetscCall(BVRestoreColumn(pjd->W,0,&wg));
     688           9 :     PetscCall(BVRestoreColumn(pjd->V,0,&vg));
     689           9 :     PetscCall(BVNormColumn(pjd->W,0,NORM_2,&norm));
     690           9 :     PetscCall(BVScaleColumn(pjd->W,0,1.0/norm));
     691             :   }
     692          11 :   PetscCall(PetscFree(tt));
     693          11 :   PetscFunctionReturn(PETSC_SUCCESS);
     694             : }
     695             : 
     696        4200 : static PetscErrorCode MatMult_PEPJD(Mat P,Vec x,Vec y)
     697             : {
     698        4200 :   PEP_JD_MATSHELL *matctx;
     699        4200 :   PEP_JD          *pjd;
     700        4200 :   PetscInt        i,j,nconv,nloc,nmat,ldt,ncv,sz;
     701        4200 :   Vec             tx,ty;
     702        4200 :   const Vec       *xs,*ys;
     703        4200 :   PetscScalar     *array1,*array2,*x2=NULL,*y2,*tt=NULL,*xx=NULL,*xxi,theta[2],sone=1.0,*qj,*val,*vali=NULL;
     704        4200 :   PetscBLASInt    n,ld,one=1;
     705        4200 :   PetscMPIInt     np;
     706             : #if !defined(PETSC_USE_COMPLEX)
     707        4200 :   Vec             txi=NULL,tyi=NULL;
     708        4200 :   PetscScalar     *x2i=NULL,*qji=NULL,*qq,*y2i,*arrayi1,*arrayi2;
     709             : #endif
     710             : 
     711        4200 :   PetscFunctionBegin;
     712        4200 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)P),&np));
     713        4200 :   PetscCall(MatShellGetContext(P,&matctx));
     714        4200 :   pjd   = (PEP_JD*)matctx->pep->data;
     715        4200 :   nconv = pjd->nlock;
     716        4200 :   nmat  = matctx->pep->nmat;
     717        4200 :   ncv   = matctx->pep->ncv;
     718        4200 :   ldt   = pjd->ld;
     719        4200 :   PetscCall(VecCompGetSubVecs(x,&sz,&xs));
     720        4200 :   PetscCall(VecCompGetSubVecs(y,NULL,&ys));
     721        4200 :   theta[0] = matctx->theta[0];
     722        4200 :   theta[1] = (sz==2)?matctx->theta[1]:0.0;
     723        4200 :   if (nconv>0) {
     724        3880 :     PetscCall(PetscMalloc5(nconv,&tt,sz*nconv,&x2,(sz==2?3:1)*nconv*nmat,&qj,2*nconv,&xx,2*nmat,&val));
     725        1980 :     PetscCall(BVGetSizes(matctx->pep->V,&nloc,NULL,NULL));
     726        1980 :     PetscCall(VecGetArray(xs[0],&array1));
     727        4364 :     for (i=0;i<nconv;i++) x2[i] = array1[nloc+i]* PetscSqrtReal(np);
     728        1980 :     PetscCall(VecRestoreArray(xs[0],&array1));
     729             : #if !defined(PETSC_USE_COMPLEX)
     730        1980 :     if (sz==2) {
     731          80 :       x2i = x2+nconv;
     732          80 :       PetscCall(VecGetArray(xs[1],&arrayi1));
     733         240 :       for (i=0;i<nconv;i++) x2i[i] = arrayi1[nloc+i]* PetscSqrtReal(np);
     734          80 :       PetscCall(VecRestoreArray(xs[1],&arrayi1));
     735             :     }
     736             : #endif
     737        1980 :     vali = val+nmat;
     738             :   }
     739        4200 :   tx = matctx->work[0];
     740        4200 :   ty = matctx->work[1];
     741        4200 :   PetscCall(VecGetArray(xs[0],&array1));
     742        4200 :   PetscCall(VecPlaceArray(tx,array1));
     743        4200 :   PetscCall(VecGetArray(ys[0],&array2));
     744        4200 :   PetscCall(VecPlaceArray(ty,array2));
     745        4200 :   PetscCall(MatMult(matctx->Pr,tx,ty));
     746             : #if !defined(PETSC_USE_COMPLEX)
     747        4200 :   if (sz==2) {
     748         203 :     txi = matctx->work[2];
     749         203 :     tyi = matctx->work[3];
     750         203 :     PetscCall(VecGetArray(xs[1],&arrayi1));
     751         203 :     PetscCall(VecPlaceArray(txi,arrayi1));
     752         203 :     PetscCall(VecGetArray(ys[1],&arrayi2));
     753         203 :     PetscCall(VecPlaceArray(tyi,arrayi2));
     754         203 :     PetscCall(MatMult(matctx->Pr,txi,tyi));
     755         203 :     if (theta[1]!=0.0) {
     756         144 :       PetscCall(MatMult(matctx->Pi,txi,matctx->work[4]));
     757         144 :       PetscCall(VecAXPY(ty,-1.0,matctx->work[4]));
     758         144 :       PetscCall(MatMult(matctx->Pi,tx,matctx->work[4]));
     759         144 :       PetscCall(VecAXPY(tyi,1.0,matctx->work[4]));
     760             :     }
     761             :   }
     762             : #endif
     763        4200 :   if (nconv>0) {
     764        1980 :     PetscCall(PEPEvaluateBasis(matctx->pep,theta[0],theta[1],val,vali));
     765        9460 :     for (i=0;i<nmat;i++) PetscCall(PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,ncv,val,x2,i,i>1?qj+(i-2)*nconv:NULL,i>0?qj+(i-1)*nconv:NULL,qj+i*nconv));
     766             : #if !defined(PETSC_USE_COMPLEX)
     767        1980 :     if (sz==2) {
     768          80 :       qji = qj+nconv*nmat;
     769          80 :       qq = qji+nconv*nmat;
     770         320 :       for (i=0;i<nmat;i++) PetscCall(PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,matctx->pep->ncv,vali,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv));
     771         560 :       for (i=0;i<nconv*nmat;i++) qj[i] -= qji[i];
     772         320 :       for (i=0;i<nmat;i++) {
     773         240 :         PetscCall(PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,matctx->pep->ncv,val,x2i,i,i>1?qji+(i-2)*nconv:NULL,i>0?qji+(i-1)*nconv:NULL,qji+i*nconv));
     774         240 :         PetscCall(PEPJDEvaluateHatBasis(matctx->pep,nconv,pjd->T,matctx->pep->ncv,vali,x2,i,i>1?qq+(i-2)*nconv:NULL,i>0?qq+(i-1)*nconv:NULL,qq+i*nconv));
     775             :       }
     776         560 :       for (i=0;i<nconv*nmat;i++) qji[i] += qq[i];
     777         240 :       for (i=1;i<matctx->pep->nmat;i++) PetscCall(BVMultVec(pjd->AX[i],1.0,1.0,tyi,qji+i*nconv));
     778             :     }
     779             : #endif
     780        7480 :     for (i=1;i<nmat;i++) PetscCall(BVMultVec(pjd->AX[i],1.0,1.0,ty,qj+i*nconv));
     781             : 
     782             :     /* extended vector part */
     783        1980 :     PetscCall(BVSetActiveColumns(pjd->X,0,nconv));
     784        1980 :     PetscCall(BVDotVec(pjd->X,tx,xx));
     785        1980 :     xxi = xx+nconv;
     786             : #if !defined(PETSC_USE_COMPLEX)
     787        1980 :     if (sz==2) PetscCall(BVDotVec(pjd->X,txi,xxi));
     788             : #endif
     789        1980 :     if (sz==1) PetscCall(PetscArrayzero(xxi,nconv));
     790        1980 :     PetscCall(PetscBLASIntCast(pjd->nlock,&n));
     791        1980 :     PetscCall(PetscBLASIntCast(ldt,&ld));
     792        1980 :     y2 = array2+nloc;
     793        1980 :     PetscCall(PetscArrayzero(y2,nconv));
     794        4208 :     for (j=0;j<pjd->midx;j++) {
     795        5232 :       for (i=0;i<nconv;i++) tt[i] = val[j]*xx[i]-vali[j]*xxi[i];
     796        2228 :       PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qj+j*nconv,&one,&sone,tt,&one));
     797        2228 :       PetscCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2,&one));
     798             :     }
     799             : #if !defined(PETSC_USE_COMPLEX)
     800        1980 :     if (sz==2) {
     801          80 :       y2i = arrayi2+nloc;
     802          80 :       PetscCall(PetscArrayzero(y2i,nconv));
     803         240 :       for (j=0;j<pjd->midx;j++) {
     804         480 :         for (i=0;i<nconv;i++) tt[i] = val[j]*xxi[i]+vali[j]*xx[i];
     805         160 :         PetscCallBLAS("BLASgemv",BLASgemv_("N",&n,&n,&sone,pjd->XpX,&ld,qji+j*nconv,&one,&sone,tt,&one));
     806         160 :         PetscCallBLAS("BLASgemv",BLASgemv_("C",&n,&n,&sone,pjd->Tj+j*ld*ld,&ld,tt,&one,&sone,y2i,&one));
     807             :       }
     808         240 :       for (i=0;i<nconv;i++) arrayi2[nloc+i] /= PetscSqrtReal(np);
     809             :     }
     810             : #endif
     811        4364 :     for (i=0;i<nconv;i++) array2[nloc+i] /= PetscSqrtReal(np);
     812        1980 :     PetscCall(PetscFree5(tt,x2,qj,xx,val));
     813             :   }
     814        4200 :   PetscCall(VecResetArray(tx));
     815        4200 :   PetscCall(VecRestoreArray(xs[0],&array1));
     816        4200 :   PetscCall(VecResetArray(ty));
     817        4200 :   PetscCall(VecRestoreArray(ys[0],&array2));
     818             : #if !defined(PETSC_USE_COMPLEX)
     819        4200 :   if (sz==2) {
     820         203 :     PetscCall(VecResetArray(txi));
     821         203 :     PetscCall(VecRestoreArray(xs[1],&arrayi1));
     822         203 :     PetscCall(VecResetArray(tyi));
     823         203 :     PetscCall(VecRestoreArray(ys[1],&arrayi2));
     824             :   }
     825             : #endif
     826        4200 :   PetscFunctionReturn(PETSC_SUCCESS);
     827             : }
     828             : 
     829          11 : static PetscErrorCode MatCreateVecs_PEPJD(Mat A,Vec *right,Vec *left)
     830             : {
     831          11 :   PEP_JD_MATSHELL *matctx;
     832          11 :   PEP_JD          *pjd;
     833          11 :   PetscInt        kspsf=1,i;
     834          11 :   Vec             v[2];
     835             : 
     836          11 :   PetscFunctionBegin;
     837          11 :   PetscCall(MatShellGetContext(A,&matctx));
     838          11 :   pjd   = (PEP_JD*)matctx->pep->data;
     839             : #if !defined (PETSC_USE_COMPLEX)
     840          11 :   kspsf = 2;
     841             : #endif
     842          33 :   for (i=0;i<kspsf;i++) PetscCall(BVCreateVec(pjd->V,v+i));
     843          11 :   if (right) PetscCall(VecCreateCompWithVecs(v,kspsf,pjd->vtempl,right));
     844          11 :   if (left) PetscCall(VecCreateCompWithVecs(v,kspsf,pjd->vtempl,left));
     845          33 :   for (i=0;i<kspsf;i++) PetscCall(VecDestroy(&v[i]));
     846          11 :   PetscFunctionReturn(PETSC_SUCCESS);
     847             : }
     848             : 
     849         119 : static PetscErrorCode PEPJDUpdateExtendedPC(PEP pep,PetscScalar theta)
     850             : {
     851         119 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
     852         119 :   PEP_JD_PCSHELL *pcctx;
     853         119 :   PetscInt       i,j,k,n=pjd->nlock,ld=pjd->ld,deg=pep->nmat-1;
     854         119 :   PetscScalar    *M,*ps,*work,*U,*V,*S,*Sp,*Spp,snone=-1.0,sone=1.0,zero=0.0,*val;
     855         119 :   PetscReal      tol,maxeig=0.0,*sg,*rwork;
     856         119 :   PetscBLASInt   n_,info,ld_,*p,lw_,rk=0;
     857             : 
     858         119 :   PetscFunctionBegin;
     859         119 :   if (n) {
     860          48 :     PetscCall(PCShellGetContext(pjd->pcshell,&pcctx));
     861          48 :     pcctx->theta = theta;
     862          48 :     pcctx->n = n;
     863          48 :     M  = pcctx->M;
     864          48 :     PetscCall(PetscBLASIntCast(n,&n_));
     865          48 :     PetscCall(PetscBLASIntCast(ld,&ld_));
     866          48 :     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
     867          48 :     if (pjd->midx==1) {
     868          25 :       PetscCall(PetscArraycpy(M,pjd->XpX,ld*ld));
     869          25 :       PetscCall(PetscCalloc2(10*n,&work,n,&p));
     870             :     } else {
     871          23 :       ps = pcctx->ps;
     872          23 :       PetscCall(PetscCalloc7(2*n*n,&U,3*n*n,&S,n,&sg,10*n,&work,5*n,&rwork,n,&p,deg+1,&val));
     873          23 :       V = U+n*n;
     874             :       /* pseudo-inverse */
     875          81 :       for (j=0;j<n;j++) {
     876         210 :         for (i=0;i<n;i++) S[n*j+i] = -pjd->T[pep->ncv*j+i];
     877          58 :         S[n*j+j] += theta;
     878             :       }
     879          23 :       lw_ = 10*n_;
     880             : #if !defined (PETSC_USE_COMPLEX)
     881          23 :       PetscCallBLAS("LAPACKgesvd",LAPACKgesvd_("S","S",&n_,&n_,S,&n_,sg,U,&n_,V,&n_,work,&lw_,&info));
     882             : #else
     883             :       PetscCallBLAS("LAPACKgesvd",LAPACKgesvd_("S","S",&n_,&n_,S,&n_,sg,U,&n_,V,&n_,work,&lw_,rwork,&info));
     884             : #endif
     885          23 :       SlepcCheckLapackInfo("gesvd",info);
     886          81 :       for (i=0;i<n;i++) maxeig = PetscMax(maxeig,sg[i]);
     887          23 :       tol = 10*PETSC_MACHINE_EPSILON*n*maxeig;
     888          81 :       for (j=0;j<n;j++) {
     889          58 :         if (sg[j]>tol) {
     890         210 :           for (i=0;i<n;i++) U[j*n+i] /= sg[j];
     891          58 :           rk++;
     892             :         } else break;
     893             :       }
     894          23 :       PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&rk,&sone,U,&n_,V,&n_,&zero,ps,&ld_));
     895             : 
     896             :       /* compute M */
     897          23 :       PetscCall(PEPEvaluateBasis(pep,theta,0.0,val,NULL));
     898          23 :       PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&snone,pjd->XpX,&ld_,ps,&ld_,&zero,M,&ld_));
     899          23 :       PetscCall(PetscArrayzero(S,2*n*n));
     900          23 :       Sp = S+n*n;
     901          81 :       for (j=0;j<n;j++) S[j*(n+1)] = 1.0;
     902          46 :       for (k=1;k<pjd->midx;k++) {
     903         233 :         for (j=0;j<n;j++) for (i=0;i<n;i++) V[j*n+i] = S[j*n+i] - ps[j*ld+i]*val[k];
     904          23 :         PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n_,&n_,&n_,&sone,pjd->XpX,&ld_,V,&n_,&zero,U,&n_));
     905          23 :         PetscCallBLAS("BLASgemm",BLASgemm_("C","N",&n_,&n_,&n_,&sone,pjd->Tj+k*ld*ld,&ld_,U,&n_,&sone,M,&ld_));
     906          23 :         Spp = Sp; Sp = S;
     907          23 :         PetscCall(PEPJDEvaluateHatBasis(pep,n,pjd->T,pep->ncv,val,NULL,k+1,Spp,Sp,S));
     908             :       }
     909             :     }
     910             :     /* inverse */
     911          48 :     PetscCallBLAS("LAPACKgetrf",LAPACKgetrf_(&n_,&n_,M,&ld_,p,&info));
     912          48 :     SlepcCheckLapackInfo("getrf",info);
     913          48 :     PetscCallBLAS("LAPACKgetri",LAPACKgetri_(&n_,M,&ld_,p,work,&n_,&info));
     914          48 :     SlepcCheckLapackInfo("getri",info);
     915          48 :     PetscCall(PetscFPTrapPop());
     916          48 :     if (pjd->midx==1) PetscCall(PetscFree2(work,p));
     917          23 :     else PetscCall(PetscFree7(U,S,sg,work,rwork,p,val));
     918             :   }
     919         119 :   PetscFunctionReturn(PETSC_SUCCESS);
     920             : }
     921             : 
     922         248 : static PetscErrorCode PEPJDMatSetUp(PEP pep,PetscInt sz,PetscScalar *theta)
     923             : {
     924         248 :   PEP_JD          *pjd = (PEP_JD*)pep->data;
     925         248 :   PEP_JD_MATSHELL *matctx;
     926         248 :   PEP_JD_PCSHELL  *pcctx;
     927         248 :   MatStructure    str;
     928         248 :   PetscScalar     *vals,*valsi;
     929         248 :   PetscBool       skipmat=PETSC_FALSE;
     930         248 :   PetscInt        i;
     931         248 :   Mat             Pr=NULL;
     932             : 
     933         248 :   PetscFunctionBegin;
     934         248 :   if (sz==2 && theta[1]==0.0) sz = 1;
     935         248 :   PetscCall(MatShellGetContext(pjd->Pshell,&matctx));
     936         248 :   PetscCall(PCShellGetContext(pjd->pcshell,&pcctx));
     937         248 :   if (matctx->Pr && matctx->theta[0]==theta[0] && ((!matctx->Pi && sz==1) || (sz==2 && matctx->theta[1]==theta[1]))) {
     938         127 :     if (pcctx->n == pjd->nlock) PetscFunctionReturn(PETSC_SUCCESS);
     939             :     skipmat = PETSC_TRUE;
     940             :   }
     941             :   if (!skipmat) {
     942         121 :     PetscCall(PetscMalloc2(pep->nmat,&vals,pep->nmat,&valsi));
     943         121 :     PetscCall(STGetMatStructure(pep->st,&str));
     944         121 :     PetscCall(PEPEvaluateBasis(pep,theta[0],theta[1],vals,valsi));
     945         121 :     if (!matctx->Pr) PetscCall(MatDuplicate(pep->A[0],MAT_COPY_VALUES,&matctx->Pr));
     946         110 :     else PetscCall(MatCopy(pep->A[0],matctx->Pr,str));
     947         374 :     for (i=1;i<pep->nmat;i++) PetscCall(MatAXPY(matctx->Pr,vals[i],pep->A[i],str));
     948         121 :     if (!pjd->reusepc) {
     949         118 :       if (pcctx->PPr && sz==2) {
     950           6 :         PetscCall(MatCopy(matctx->Pr,pcctx->PPr,str));
     951           6 :         Pr = pcctx->PPr;
     952         112 :       } else Pr = matctx->Pr;
     953             :     }
     954         121 :     matctx->theta[0] = theta[0];
     955             : #if !defined(PETSC_USE_COMPLEX)
     956         121 :     if (sz==2) {
     957           8 :       if (!matctx->Pi) PetscCall(MatDuplicate(pep->A[0],MAT_COPY_VALUES,&matctx->Pi));
     958           5 :       else PetscCall(MatCopy(pep->A[1],matctx->Pi,str));
     959           8 :       PetscCall(MatScale(matctx->Pi,valsi[1]));
     960          16 :       for (i=2;i<pep->nmat;i++) PetscCall(MatAXPY(matctx->Pi,valsi[i],pep->A[i],str));
     961           8 :       matctx->theta[1] = theta[1];
     962             :     }
     963             : #endif
     964         121 :     PetscCall(PetscFree2(vals,valsi));
     965             :   }
     966         122 :   if (!pjd->reusepc) {
     967         119 :     if (!skipmat) {
     968         118 :       PetscCall(PCSetOperators(pcctx->pc,Pr,Pr));
     969         118 :       PetscCall(PCSetUp(pcctx->pc));
     970             :     }
     971         119 :     PetscCall(PEPJDUpdateExtendedPC(pep,theta[0]));
     972             :   }
     973         122 :   PetscFunctionReturn(PETSC_SUCCESS);
     974             : }
     975             : 
     976          11 : static PetscErrorCode PEPJDCreateShellPC(PEP pep,Vec *ww)
     977             : {
     978          11 :   PEP_JD          *pjd = (PEP_JD*)pep->data;
     979          11 :   PEP_JD_PCSHELL  *pcctx;
     980          11 :   PEP_JD_MATSHELL *matctx;
     981          11 :   KSP             ksp;
     982          11 :   PetscInt        nloc,mloc,kspsf=1;
     983          11 :   Vec             v[2];
     984          11 :   PetscScalar     target[2];
     985          11 :   Mat             Pr;
     986             : 
     987          11 :   PetscFunctionBegin;
     988             :   /* Create the reference vector */
     989          11 :   PetscCall(BVGetColumn(pjd->V,0,&v[0]));
     990          11 :   v[1] = v[0];
     991             : #if !defined (PETSC_USE_COMPLEX)
     992          11 :   kspsf = 2;
     993             : #endif
     994          11 :   PetscCall(VecCreateCompWithVecs(v,kspsf,NULL,&pjd->vtempl));
     995          11 :   PetscCall(BVRestoreColumn(pjd->V,0,&v[0]));
     996             : 
     997             :   /* Replace preconditioner with one containing projectors */
     998          11 :   PetscCall(PCCreate(PetscObjectComm((PetscObject)pep),&pjd->pcshell));
     999          11 :   PetscCall(PCSetType(pjd->pcshell,PCSHELL));
    1000          11 :   PetscCall(PCShellSetName(pjd->pcshell,"PCPEPJD"));
    1001          11 :   PetscCall(PCShellSetApply(pjd->pcshell,PCShellApply_PEPJD));
    1002          11 :   PetscCall(PetscNew(&pcctx));
    1003          11 :   PetscCall(PCShellSetContext(pjd->pcshell,pcctx));
    1004          11 :   PetscCall(STGetKSP(pep->st,&ksp));
    1005          11 :   PetscCall(BVCreateVec(pjd->V,&pcctx->Bp[0]));
    1006          11 :   PetscCall(VecDuplicate(pcctx->Bp[0],&pcctx->Bp[1]));
    1007          11 :   PetscCall(KSPGetPC(ksp,&pcctx->pc));
    1008          11 :   PetscCall(PetscObjectReference((PetscObject)pcctx->pc));
    1009          11 :   PetscCall(MatGetLocalSize(pep->A[0],&mloc,&nloc));
    1010          11 :   if (pjd->ld>1) {
    1011          11 :     nloc += pjd->ld-1; mloc += pjd->ld-1;
    1012             :   }
    1013          11 :   PetscCall(PetscNew(&matctx));
    1014          11 :   PetscCall(MatCreateShell(PetscObjectComm((PetscObject)pep),kspsf*nloc,kspsf*mloc,PETSC_DETERMINE,PETSC_DETERMINE,matctx,&pjd->Pshell));
    1015          11 :   PetscCall(MatShellSetOperation(pjd->Pshell,MATOP_MULT,(void(*)(void))MatMult_PEPJD));
    1016          11 :   PetscCall(MatShellSetOperation(pjd->Pshell,MATOP_CREATE_VECS,(void(*)(void))MatCreateVecs_PEPJD));
    1017          11 :   matctx->pep = pep;
    1018          11 :   target[0] = pep->target; target[1] = 0.0;
    1019          11 :   PetscCall(PEPJDMatSetUp(pep,1,target));
    1020          11 :   Pr = matctx->Pr;
    1021          11 :   pcctx->PPr = NULL;
    1022             : #if !defined(PETSC_USE_COMPLEX)
    1023          11 :   if (!pjd->reusepc) {
    1024          10 :     PetscCall(MatDuplicate(matctx->Pr,MAT_COPY_VALUES,&pcctx->PPr));
    1025          10 :     Pr = pcctx->PPr;
    1026             :   }
    1027             : #endif
    1028          11 :   PetscCall(PCSetOperators(pcctx->pc,Pr,Pr));
    1029          11 :   PetscCall(PCSetErrorIfFailure(pcctx->pc,PETSC_TRUE));
    1030          11 :   PetscCall(KSPSetPC(ksp,pjd->pcshell));
    1031          11 :   if (pjd->reusepc) {
    1032           1 :     PetscCall(PCSetReusePreconditioner(pcctx->pc,PETSC_TRUE));
    1033           1 :     PetscCall(KSPSetReusePreconditioner(ksp,PETSC_TRUE));
    1034             :   }
    1035          11 :   PetscCall(PEP_KSPSetOperators(ksp,pjd->Pshell,pjd->Pshell));
    1036          11 :   PetscCall(KSPSetUp(ksp));
    1037          11 :   if (pjd->ld>1) {
    1038          11 :     PetscCall(PetscMalloc2(pjd->ld*pjd->ld,&pcctx->M,pjd->ld*pjd->ld,&pcctx->ps));
    1039          11 :     pcctx->pep = pep;
    1040             :   }
    1041          11 :   matctx->work = ww;
    1042          11 :   pcctx->work  = ww;
    1043          11 :   PetscFunctionReturn(PETSC_SUCCESS);
    1044             : }
    1045             : 
    1046          11 : static PetscErrorCode PEPJDEigenvectors(PEP pep)
    1047             : {
    1048          11 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
    1049          11 :   PetscBLASInt   ld,nconv,info,nc;
    1050          11 :   PetscScalar    *Z;
    1051          11 :   PetscReal      *wr;
    1052          11 :   Mat            U;
    1053             : #if defined(PETSC_USE_COMPLEX)
    1054             :   PetscScalar    *w;
    1055             : #endif
    1056             : 
    1057          11 :   PetscFunctionBegin;
    1058          11 :   PetscCall(PetscBLASIntCast(pep->ncv,&ld));
    1059          11 :   PetscCall(PetscBLASIntCast(pep->nconv,&nconv));
    1060          11 :   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
    1061             : #if !defined(PETSC_USE_COMPLEX)
    1062          11 :   PetscCall(PetscMalloc2(pep->nconv*pep->nconv,&Z,3*pep->ncv,&wr));
    1063          11 :   PetscCallBLAS("LAPACKtrevc",LAPACKtrevc_("R","A",NULL,&nconv,pjd->T,&ld,NULL,&nconv,Z,&nconv,&nconv,&nc,wr,&info));
    1064             : #else
    1065             :   PetscCall(PetscMalloc3(pep->nconv*pep->nconv,&Z,3*pep->ncv,&wr,2*pep->ncv,&w));
    1066             :   PetscCallBLAS("LAPACKtrevc",LAPACKtrevc_("R","A",NULL,&nconv,pjd->T,&ld,NULL,&nconv,Z,&nconv,&nconv,&nc,w,wr,&info));
    1067             : #endif
    1068          11 :   PetscCall(PetscFPTrapPop());
    1069          11 :   SlepcCheckLapackInfo("trevc",info);
    1070          11 :   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,nconv,nconv,Z,&U));
    1071          11 :   PetscCall(BVSetActiveColumns(pjd->X,0,pep->nconv));
    1072          11 :   PetscCall(BVMultInPlace(pjd->X,U,0,pep->nconv));
    1073          11 :   PetscCall(BVNormalize(pjd->X,pep->eigi));
    1074          11 :   PetscCall(MatDestroy(&U));
    1075             : #if !defined(PETSC_USE_COMPLEX)
    1076          11 :   PetscCall(PetscFree2(Z,wr));
    1077             : #else
    1078             :   PetscCall(PetscFree3(Z,wr,w));
    1079             : #endif
    1080          11 :   PetscFunctionReturn(PETSC_SUCCESS);
    1081             : }
    1082             : 
    1083          15 : static PetscErrorCode PEPJDLockConverged(PEP pep,PetscInt *nv,PetscInt sz)
    1084             : {
    1085          15 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
    1086          15 :   PetscInt       j,i,*P,ldds,rk=0,nvv=*nv;
    1087          15 :   Vec            v,x,w;
    1088          15 :   PetscScalar    *R,*r,*pX,target[2];
    1089          15 :   Mat            X;
    1090          15 :   PetscBLASInt   sz_,rk_,nv_,info;
    1091          15 :   PetscMPIInt    np;
    1092             : 
    1093          15 :   PetscFunctionBegin;
    1094             :   /* update AX and XpX */
    1095          34 :   for (i=sz;i>0;i--) {
    1096          19 :     PetscCall(BVGetColumn(pjd->X,pjd->nlock-i,&x));
    1097          78 :     for (j=0;j<pep->nmat;j++) {
    1098          59 :       PetscCall(BVGetColumn(pjd->AX[j],pjd->nlock-i,&v));
    1099          59 :       PetscCall(MatMult(pep->A[j],x,v));
    1100          59 :       PetscCall(BVRestoreColumn(pjd->AX[j],pjd->nlock-i,&v));
    1101          59 :       PetscCall(BVSetActiveColumns(pjd->AX[j],0,pjd->nlock-i+1));
    1102             :     }
    1103          19 :     PetscCall(BVRestoreColumn(pjd->X,pjd->nlock-i,&x));
    1104          19 :     PetscCall(BVDotColumn(pjd->X,(pjd->nlock-i),pjd->XpX+(pjd->nlock-i)*pjd->ld));
    1105          19 :     pjd->XpX[(pjd->nlock-i)*(1+pjd->ld)] = 1.0;
    1106          35 :     for (j=0;j<pjd->nlock-i;j++) pjd->XpX[j*pjd->ld+pjd->nlock-i] = PetscConj(pjd->XpX[(pjd->nlock-i)*pjd->ld+j]);
    1107             :   }
    1108             : 
    1109             :   /* minimality index */
    1110          15 :   pjd->midx = PetscMin(pjd->mmidx,pjd->nlock);
    1111             : 
    1112             :   /* evaluate the polynomial basis in T */
    1113          15 :   PetscCall(PetscArrayzero(pjd->Tj,pjd->ld*pjd->ld*pep->nmat));
    1114          62 :   for (j=0;j<pep->nmat;j++) PetscCall(PEPEvaluateBasisMat(pep,pjd->nlock,pjd->T,pep->ncv,j,(j>1)?pjd->Tj+(j-2)*pjd->ld*pjd->ld:NULL,pjd->ld,j?pjd->Tj+(j-1)*pjd->ld*pjd->ld:NULL,pjd->ld,pjd->Tj+j*pjd->ld*pjd->ld,pjd->ld));
    1115             : 
    1116             :   /* Extend search space */
    1117          15 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np));
    1118          15 :   PetscCall(PetscCalloc3(nvv,&P,nvv*nvv,&R,nvv*sz,&r));
    1119          15 :   PetscCall(DSGetLeadingDimension(pep->ds,&ldds));
    1120          15 :   PetscCall(DSGetArray(pep->ds,DS_MAT_X,&pX));
    1121          15 :   PetscCall(PEPJDOrthogonalize(nvv,nvv,pX,ldds,&rk,P,R,nvv));
    1122          34 :   for (j=0;j<sz;j++) {
    1123         262 :     for (i=0;i<rk;i++) r[i*sz+j] = PetscConj(R[nvv*i+j]*pep->eigr[P[i]]); /* first row scaled with permuted diagonal */
    1124             :   }
    1125          15 :   PetscCall(PetscBLASIntCast(rk,&rk_));
    1126          15 :   PetscCall(PetscBLASIntCast(sz,&sz_));
    1127          15 :   PetscCall(PetscBLASIntCast(nvv,&nv_));
    1128          15 :   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
    1129          15 :   PetscCallBLAS("LAPACKtrtri",LAPACKtrtri_("U","N",&rk_,R,&nv_,&info));
    1130          15 :   PetscCall(PetscFPTrapPop());
    1131          15 :   SlepcCheckLapackInfo("trtri",info);
    1132          34 :   for (i=0;i<sz;i++) PetscCallBLAS("BLAStrmv",BLAStrmv_("U","C","N",&rk_,R,&nv_,r+i,&sz_));
    1133         258 :   for (i=0;i<sz*rk;i++) r[i] = PetscConj(r[i])/PetscSqrtReal(np); /* revert */
    1134          15 :   PetscCall(BVSetActiveColumns(pjd->V,0,nvv));
    1135          15 :   rk -= sz;
    1136         190 :   for (j=0;j<rk;j++) PetscCall(PetscArraycpy(R+j*nvv,pX+(j+sz)*ldds,nvv));
    1137          15 :   PetscCall(DSRestoreArray(pep->ds,DS_MAT_X,&pX));
    1138          15 :   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,nvv,rk,R,&X));
    1139          15 :   PetscCall(BVMultInPlace(pjd->V,X,0,rk));
    1140          15 :   PetscCall(MatDestroy(&X));
    1141          15 :   PetscCall(BVSetActiveColumns(pjd->V,0,rk));
    1142         190 :   for (j=0;j<rk;j++) {
    1143         175 :     PetscCall(BVGetColumn(pjd->V,j,&v));
    1144         175 :     PetscCall(PEPJDCopyToExtendedVec(pep,NULL,r+sz*(j+sz),sz,pjd->nlock-sz,v,PETSC_FALSE));
    1145         175 :     PetscCall(BVRestoreColumn(pjd->V,j,&v));
    1146             :   }
    1147          15 :   PetscCall(BVOrthogonalize(pjd->V,NULL));
    1148             : 
    1149          15 :   if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
    1150         181 :     for (j=0;j<rk;j++) {
    1151             :       /* W = P(target)*V */
    1152         168 :       PetscCall(BVGetColumn(pjd->W,j,&w));
    1153         168 :       PetscCall(BVGetColumn(pjd->V,j,&v));
    1154         168 :       target[0] = pep->target; target[1] = 0.0;
    1155         168 :       PetscCall(PEPJDComputeResidual(pep,PETSC_FALSE,1,&v,target,&w,pep->work));
    1156         168 :       PetscCall(BVRestoreColumn(pjd->V,j,&v));
    1157         168 :       PetscCall(BVRestoreColumn(pjd->W,j,&w));
    1158             :     }
    1159          13 :     PetscCall(BVSetActiveColumns(pjd->W,0,rk));
    1160          13 :     PetscCall(BVOrthogonalize(pjd->W,NULL));
    1161             :   }
    1162          15 :   *nv = rk;
    1163          15 :   PetscCall(PetscFree3(P,R,r));
    1164          15 :   PetscFunctionReturn(PETSC_SUCCESS);
    1165             : }
    1166             : 
    1167         237 : static PetscErrorCode PEPJDSystemSetUp(PEP pep,PetscInt sz,PetscScalar *theta,Vec *u,Vec *p,Vec *ww)
    1168             : {
    1169         237 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
    1170         237 :   PEP_JD_PCSHELL *pcctx;
    1171             : #if !defined(PETSC_USE_COMPLEX)
    1172         237 :   PetscScalar    s[2];
    1173             : #endif
    1174             : 
    1175         237 :   PetscFunctionBegin;
    1176         237 :   PetscCall(PCShellGetContext(pjd->pcshell,&pcctx));
    1177         237 :   PetscCall(PEPJDMatSetUp(pep,sz,theta));
    1178         237 :   pcctx->u[0] = u[0]; pcctx->u[1] = u[1];
    1179             :   /* Compute r'. p is a work space vector */
    1180         237 :   PetscCall(PEPJDComputeResidual(pep,PETSC_TRUE,sz,u,theta,p,ww));
    1181         237 :   PetscCall(PEPJDExtendedPCApply(pjd->pcshell,p[0],pcctx->Bp[0]));
    1182         237 :   PetscCall(VecDot(pcctx->Bp[0],u[0],pcctx->gamma));
    1183             : #if !defined(PETSC_USE_COMPLEX)
    1184         237 :   if (sz==2) {
    1185          24 :     PetscCall(PEPJDExtendedPCApply(pjd->pcshell,p[1],pcctx->Bp[1]));
    1186          24 :     PetscCall(VecDot(pcctx->Bp[0],u[1],pcctx->gamma+1));
    1187          24 :     PetscCall(VecMDot(pcctx->Bp[1],2,u,s));
    1188          24 :     pcctx->gamma[0] += s[1];
    1189          24 :     pcctx->gamma[1] = -pcctx->gamma[1]+s[0];
    1190             :   }
    1191             : #endif
    1192         237 :   if (sz==1) {
    1193         213 :     PetscCall(VecZeroEntries(pcctx->Bp[1]));
    1194         213 :     pcctx->gamma[1] = 0.0;
    1195             :   }
    1196         237 :   PetscFunctionReturn(PETSC_SUCCESS);
    1197             : }
    1198             : 
    1199          11 : static PetscErrorCode PEPSolve_JD(PEP pep)
    1200             : {
    1201          11 :   PEP_JD          *pjd = (PEP_JD*)pep->data;
    1202          11 :   PetscInt        k,nv,nvc,ld,minv,dim,bupdated=0,sz=1,kspsf=1,idx,off,maxits,nloc;
    1203          11 :   PetscMPIInt     np,count;
    1204          11 :   PetscScalar     theta[2]={0.0,0.0},ritz[2]={0.0,0.0},*pX,*eig,*eigi,*array;
    1205          11 :   PetscReal       norm,*res,tol=0.0,rtol,abstol, dtol;
    1206          11 :   PetscBool       lindep,ini=PETSC_TRUE;
    1207          11 :   Vec             tc,t[2]={NULL,NULL},u[2]={NULL,NULL},p[2]={NULL,NULL};
    1208          11 :   Vec             rc,rr[2],r[2]={NULL,NULL},*ww=pep->work,v[2];
    1209          11 :   Mat             G,X,Y;
    1210          11 :   KSP             ksp;
    1211          11 :   PEP_JD_PCSHELL  *pcctx;
    1212          11 :   PEP_JD_MATSHELL *matctx;
    1213             : #if !defined(PETSC_USE_COMPLEX)
    1214          11 :   PetscReal       norm1;
    1215             : #endif
    1216             : 
    1217          11 :   PetscFunctionBegin;
    1218          11 :   PetscCall(PetscCitationsRegister(citation,&cited));
    1219          11 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pep),&np));
    1220          11 :   PetscCall(BVGetSizes(pep->V,&nloc,NULL,NULL));
    1221          11 :   PetscCall(DSGetLeadingDimension(pep->ds,&ld));
    1222          11 :   PetscCall(PetscCalloc3(pep->ncv+pep->nev,&eig,pep->ncv+pep->nev,&eigi,pep->ncv+pep->nev,&res));
    1223          11 :   pjd->nlock = 0;
    1224          11 :   PetscCall(STGetKSP(pep->st,&ksp));
    1225          11 :   PetscCall(KSPGetTolerances(ksp,&rtol,&abstol,&dtol,&maxits));
    1226             : #if !defined (PETSC_USE_COMPLEX)
    1227          11 :   kspsf = 2;
    1228             : #endif
    1229          11 :   PetscCall(PEPJDProcessInitialSpace(pep,ww));
    1230          11 :   nv = (pep->nini)?pep->nini:1;
    1231             : 
    1232             :   /* Replace preconditioner with one containing projectors */
    1233          11 :   PetscCall(PEPJDCreateShellPC(pep,ww));
    1234          11 :   PetscCall(PCShellGetContext(pjd->pcshell,&pcctx));
    1235             : 
    1236             :   /* Create auxiliary vectors */
    1237          11 :   PetscCall(BVCreateVec(pjd->V,&u[0]));
    1238          11 :   PetscCall(VecDuplicate(u[0],&p[0]));
    1239          11 :   PetscCall(VecDuplicate(u[0],&r[0]));
    1240             : #if !defined (PETSC_USE_COMPLEX)
    1241          11 :   PetscCall(VecDuplicate(u[0],&u[1]));
    1242          11 :   PetscCall(VecDuplicate(u[0],&p[1]));
    1243          11 :   PetscCall(VecDuplicate(u[0],&r[1]));
    1244             : #endif
    1245             : 
    1246             :   /* Restart loop */
    1247         275 :   while (pep->reason == PEP_CONVERGED_ITERATING) {
    1248         264 :     pep->its++;
    1249         264 :     PetscCall(DSSetDimensions(pep->ds,nv,0,0));
    1250         264 :     PetscCall(BVSetActiveColumns(pjd->V,bupdated,nv));
    1251         264 :     PetscCall(PEPJDUpdateTV(pep,bupdated,nv,ww));
    1252         264 :     if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) PetscCall(BVSetActiveColumns(pjd->W,bupdated,nv));
    1253        1084 :     for (k=0;k<pep->nmat;k++) {
    1254         820 :       PetscCall(BVSetActiveColumns(pjd->TV[k],bupdated,nv));
    1255         820 :       PetscCall(DSGetMat(pep->ds,DSMatExtra[k],&G));
    1256         820 :       PetscCall(BVMatProject(pjd->TV[k],NULL,pjd->W,G));
    1257         820 :       PetscCall(DSRestoreMat(pep->ds,DSMatExtra[k],&G));
    1258             :     }
    1259         264 :     PetscCall(BVSetActiveColumns(pjd->V,0,nv));
    1260         264 :     PetscCall(BVSetActiveColumns(pjd->W,0,nv));
    1261             : 
    1262             :     /* Solve projected problem */
    1263         264 :     PetscCall(DSSetState(pep->ds,DS_STATE_RAW));
    1264         264 :     PetscCall(DSSolve(pep->ds,pep->eigr,pep->eigi));
    1265         264 :     PetscCall(DSSort(pep->ds,pep->eigr,pep->eigi,NULL,NULL,NULL));
    1266         264 :     PetscCall(DSSynchronize(pep->ds,pep->eigr,pep->eigi));
    1267             :     idx = 0;
    1268         291 :     do {
    1269         291 :       ritz[0] = pep->eigr[idx];
    1270             : #if !defined(PETSC_USE_COMPLEX)
    1271         291 :       ritz[1] = pep->eigi[idx];
    1272         291 :       sz = (ritz[1]==0.0)?1:2;
    1273             : #endif
    1274             :       /* Compute Ritz vector u=V*X(:,1) */
    1275         291 :       PetscCall(DSGetArray(pep->ds,DS_MAT_X,&pX));
    1276         291 :       PetscCall(BVSetActiveColumns(pjd->V,0,nv));
    1277         291 :       PetscCall(BVMultVec(pjd->V,1.0,0.0,u[0],pX+idx*ld));
    1278             : #if !defined(PETSC_USE_COMPLEX)
    1279         291 :       if (sz==2) PetscCall(BVMultVec(pjd->V,1.0,0.0,u[1],pX+(idx+1)*ld));
    1280             : #endif
    1281         291 :       PetscCall(DSRestoreArray(pep->ds,DS_MAT_X,&pX));
    1282         291 :       PetscCall(PEPJDComputeResidual(pep,PETSC_FALSE,sz,u,ritz,r,ww));
    1283             :       /* Check convergence */
    1284         291 :       PetscCall(VecNorm(r[0],NORM_2,&norm));
    1285             : #if !defined(PETSC_USE_COMPLEX)
    1286         291 :       if (sz==2) {
    1287          33 :         PetscCall(VecNorm(r[1],NORM_2,&norm1));
    1288          33 :         norm = SlepcAbs(norm,norm1);
    1289             :       }
    1290             : #endif
    1291         291 :       PetscCall((*pep->converged)(pep,ritz[0],ritz[1],norm,&pep->errest[pep->nconv],pep->convergedctx));
    1292         291 :       if (sz==2) pep->errest[pep->nconv+1] = pep->errest[pep->nconv];
    1293         291 :       if (ini) {
    1294          40 :         tol = PetscMin(.1,pep->errest[pep->nconv]); ini = PETSC_FALSE;
    1295         251 :       } else tol = PetscMin(pep->errest[pep->nconv],tol/2);
    1296         291 :       PetscCall((*pep->stopping)(pep,pep->its,pep->max_it,(pep->errest[pep->nconv]<pep->tol)?pep->nconv+sz:pep->nconv,pep->nev,&pep->reason,pep->stoppingctx));
    1297         291 :       if (pep->errest[pep->nconv]<pep->tol) {
    1298             :         /* Ritz pair converged */
    1299          29 :         ini = PETSC_TRUE;
    1300          29 :         minv = PetscMin(nv,(PetscInt)(pjd->keep*pep->ncv));
    1301          29 :         if (pjd->ld>1) {
    1302          29 :           PetscCall(BVGetColumn(pjd->X,pep->nconv,&v[0]));
    1303          29 :           PetscCall(PEPJDCopyToExtendedVec(pep,v[0],pjd->T+pep->ncv*pep->nconv,pjd->ld-1,0,u[0],PETSC_TRUE));
    1304          29 :           PetscCall(BVRestoreColumn(pjd->X,pep->nconv,&v[0]));
    1305          29 :           PetscCall(BVSetActiveColumns(pjd->X,0,pep->nconv+1));
    1306          29 :           PetscCall(BVNormColumn(pjd->X,pep->nconv,NORM_2,&norm));
    1307          29 :           PetscCall(BVScaleColumn(pjd->X,pep->nconv,1.0/norm));
    1308          63 :           for (k=0;k<pep->nconv;k++) pjd->T[pep->ncv*pep->nconv+k] *= PetscSqrtReal(np)/norm;
    1309          29 :           pjd->T[(pep->ncv+1)*pep->nconv] = ritz[0];
    1310          29 :           eig[pep->nconv] = ritz[0];
    1311          29 :           idx++;
    1312             : #if !defined(PETSC_USE_COMPLEX)
    1313          29 :           if (sz==2) {
    1314           4 :             PetscCall(BVGetColumn(pjd->X,pep->nconv+1,&v[0]));
    1315           4 :             PetscCall(PEPJDCopyToExtendedVec(pep,v[0],pjd->T+pep->ncv*(pep->nconv+1),pjd->ld-1,0,u[1],PETSC_TRUE));
    1316           4 :             PetscCall(BVRestoreColumn(pjd->X,pep->nconv+1,&v[0]));
    1317           4 :             PetscCall(BVSetActiveColumns(pjd->X,0,pep->nconv+2));
    1318           4 :             PetscCall(BVNormColumn(pjd->X,pep->nconv+1,NORM_2,&norm1));
    1319           4 :             PetscCall(BVScaleColumn(pjd->X,pep->nconv+1,1.0/norm1));
    1320           6 :             for (k=0;k<pep->nconv;k++) pjd->T[pep->ncv*(pep->nconv+1)+k] *= PetscSqrtReal(np)/norm1;
    1321           4 :             pjd->T[(pep->ncv+1)*(pep->nconv+1)] = ritz[0];
    1322           4 :             pjd->T[(pep->ncv+1)*pep->nconv+1] = -ritz[1]*norm1/norm;
    1323           4 :             pjd->T[(pep->ncv+1)*(pep->nconv+1)-1] = ritz[1]*norm/norm1;
    1324           4 :             eig[pep->nconv+1] = ritz[0];
    1325           4 :             eigi[pep->nconv] = ritz[1]; eigi[pep->nconv+1] = -ritz[1];
    1326           4 :             idx++;
    1327             :           }
    1328             : #endif
    1329           0 :         } else PetscCall(BVInsertVec(pep->V,pep->nconv,u[0]));
    1330          29 :         pep->nconv += sz;
    1331             :       }
    1332         291 :     } while (pep->errest[pep->nconv]<pep->tol && pep->nconv<nv);
    1333             : 
    1334         264 :     if (pep->reason==PEP_CONVERGED_ITERATING) {
    1335         253 :       nvc = nv;
    1336         253 :       if (idx) {
    1337          15 :         pjd->nlock +=idx;
    1338          15 :         PetscCall(PEPJDLockConverged(pep,&nv,idx));
    1339             :       }
    1340         253 :       if (nv+sz>=pep->ncv-1) {
    1341             :         /* Basis full, force restart */
    1342          16 :         minv = PetscMin(nv,(PetscInt)(pjd->keep*pep->ncv));
    1343          16 :         PetscCall(DSGetDimensions(pep->ds,&dim,NULL,NULL,NULL));
    1344          16 :         PetscCall(DSGetArray(pep->ds,DS_MAT_X,&pX));
    1345          16 :         PetscCall(PEPJDOrthogonalize(dim,minv,pX,ld,&minv,NULL,NULL,ld));
    1346          16 :         PetscCall(DSRestoreArray(pep->ds,DS_MAT_X,&pX));
    1347          16 :         PetscCall(DSGetArray(pep->ds,DS_MAT_Y,&pX));
    1348          16 :         PetscCall(PEPJDOrthogonalize(dim,minv,pX,ld,&minv,NULL,NULL,ld));
    1349          16 :         PetscCall(DSRestoreArray(pep->ds,DS_MAT_Y,&pX));
    1350          16 :         PetscCall(DSGetMat(pep->ds,DS_MAT_X,&X));
    1351          16 :         PetscCall(BVMultInPlace(pjd->V,X,0,minv));
    1352          16 :         PetscCall(DSRestoreMat(pep->ds,DS_MAT_X,&X));
    1353          16 :         if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
    1354          12 :          PetscCall(DSGetMat(pep->ds,DS_MAT_Y,&Y));
    1355          12 :          PetscCall(BVMultInPlace(pjd->W,Y,pep->nconv,minv));
    1356          12 :          PetscCall(DSRestoreMat(pep->ds,DS_MAT_Y,&Y));
    1357             :         }
    1358          16 :         nv = minv;
    1359          16 :         bupdated = 0;
    1360             :       } else {
    1361         237 :         if (!idx && pep->errest[pep->nconv]<pjd->fix) {theta[0] = ritz[0]; theta[1] = ritz[1];}
    1362         153 :         else {theta[0] = pep->target; theta[1] = 0.0;}
    1363             :         /* Update system mat */
    1364         237 :         PetscCall(PEPJDSystemSetUp(pep,sz,theta,u,p,ww));
    1365             :         /* Solve correction equation to expand basis */
    1366         237 :         PetscCall(BVGetColumn(pjd->V,nv,&t[0]));
    1367         237 :         rr[0] = r[0];
    1368         237 :         if (sz==2) {
    1369          24 :           PetscCall(BVGetColumn(pjd->V,nv+1,&t[1]));
    1370          24 :           rr[1] = r[1];
    1371             :         } else {
    1372         213 :           t[1] = NULL;
    1373         213 :           rr[1] = NULL;
    1374             :         }
    1375         237 :         PetscCall(VecCreateCompWithVecs(t,kspsf,pjd->vtempl,&tc));
    1376         237 :         PetscCall(VecCreateCompWithVecs(rr,kspsf,pjd->vtempl,&rc));
    1377         237 :         PetscCall(VecCompSetSubVecs(pjd->vtempl,sz,NULL));
    1378         237 :         tol  = PetscMax(rtol,tol/2);
    1379         237 :         PetscCall(KSPSetTolerances(ksp,tol,abstol,dtol,maxits));
    1380         237 :         PetscCall(KSPSolve(ksp,rc,tc));
    1381         237 :         PetscCall(VecDestroy(&tc));
    1382         237 :         PetscCall(VecDestroy(&rc));
    1383         237 :         PetscCall(VecGetArray(t[0],&array));
    1384         237 :         PetscCall(PetscMPIIntCast(pep->nconv,&count));
    1385         474 :         PetscCallMPI(MPI_Bcast(array+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep)));
    1386         237 :         PetscCall(VecRestoreArray(t[0],&array));
    1387         237 :         PetscCall(BVRestoreColumn(pjd->V,nv,&t[0]));
    1388         237 :         PetscCall(BVOrthogonalizeColumn(pjd->V,nv,NULL,&norm,&lindep));
    1389         237 :         if (lindep || norm==0.0) {
    1390           0 :           PetscCheck(sz!=1,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"Linearly dependent continuation vector");
    1391             :           off = 1;
    1392             :         } else {
    1393         237 :           off = 0;
    1394         237 :           PetscCall(BVScaleColumn(pjd->V,nv,1.0/norm));
    1395             :         }
    1396             : #if !defined(PETSC_USE_COMPLEX)
    1397         237 :         if (sz==2) {
    1398          24 :           PetscCall(VecGetArray(t[1],&array));
    1399          48 :           PetscCallMPI(MPI_Bcast(array+nloc,count,MPIU_SCALAR,np-1,PetscObjectComm((PetscObject)pep)));
    1400          24 :           PetscCall(VecRestoreArray(t[1],&array));
    1401          24 :           PetscCall(BVRestoreColumn(pjd->V,nv+1,&t[1]));
    1402          24 :           if (off) PetscCall(BVCopyColumn(pjd->V,nv+1,nv));
    1403          24 :           PetscCall(BVOrthogonalizeColumn(pjd->V,nv+1-off,NULL,&norm,&lindep));
    1404          24 :           if (lindep || norm==0.0) {
    1405           0 :             PetscCheck(off==0,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"Linearly dependent continuation vector");
    1406             :             off = 1;
    1407          24 :           } else PetscCall(BVScaleColumn(pjd->V,nv+1-off,1.0/norm));
    1408             :         }
    1409             : #endif
    1410         237 :         if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) {
    1411         204 :           PetscCall(BVInsertVec(pjd->W,nv,r[0]));
    1412         204 :           if (sz==2 && !off) PetscCall(BVInsertVec(pjd->W,nv+1,r[1]));
    1413         204 :           PetscCall(BVOrthogonalizeColumn(pjd->W,nv,NULL,&norm,&lindep));
    1414         204 :           PetscCheck(!lindep && norm>0.0,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"Linearly dependent continuation vector");
    1415         204 :           PetscCall(BVScaleColumn(pjd->W,nv,1.0/norm));
    1416         204 :           if (sz==2 && !off) {
    1417          18 :             PetscCall(BVOrthogonalizeColumn(pjd->W,nv+1,NULL,&norm,&lindep));
    1418          18 :             PetscCheck(!lindep && norm>0.0,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"Linearly dependent continuation vector");
    1419          18 :             PetscCall(BVScaleColumn(pjd->W,nv+1,1.0/norm));
    1420             :           }
    1421             :         }
    1422         237 :         bupdated = idx?0:nv;
    1423         237 :         nv += sz-off;
    1424             :       }
    1425        2745 :       for (k=0;k<nvc;k++) {
    1426        2492 :         eig[pep->nconv-idx+k] = pep->eigr[k];
    1427             : #if !defined(PETSC_USE_COMPLEX)
    1428        2492 :         eigi[pep->nconv-idx+k] = pep->eigi[k];
    1429             : #endif
    1430             :       }
    1431         528 :       PetscCall(PEPMonitor(pep,pep->its,pep->nconv,eig,eigi,pep->errest,pep->nconv+1));
    1432             :     }
    1433             :   }
    1434          11 :   if (pjd->ld>1) {
    1435          44 :     for (k=0;k<pep->nconv;k++) {
    1436          33 :       pep->eigr[k] = eig[k];
    1437          33 :       pep->eigi[k] = eigi[k];
    1438             :     }
    1439          11 :     if (pep->nconv>0) PetscCall(PEPJDEigenvectors(pep));
    1440          11 :     PetscCall(PetscFree2(pcctx->M,pcctx->ps));
    1441             :   }
    1442          11 :   PetscCall(VecDestroy(&u[0]));
    1443          11 :   PetscCall(VecDestroy(&r[0]));
    1444          11 :   PetscCall(VecDestroy(&p[0]));
    1445             : #if !defined (PETSC_USE_COMPLEX)
    1446          11 :   PetscCall(VecDestroy(&u[1]));
    1447          11 :   PetscCall(VecDestroy(&r[1]));
    1448          11 :   PetscCall(VecDestroy(&p[1]));
    1449             : #endif
    1450          11 :   PetscCall(KSPSetTolerances(ksp,rtol,abstol,dtol,maxits));
    1451          11 :   PetscCall(KSPSetPC(ksp,pcctx->pc));
    1452          11 :   PetscCall(VecDestroy(&pcctx->Bp[0]));
    1453          11 :   PetscCall(VecDestroy(&pcctx->Bp[1]));
    1454          11 :   PetscCall(MatShellGetContext(pjd->Pshell,&matctx));
    1455          11 :   PetscCall(MatDestroy(&matctx->Pr));
    1456          11 :   PetscCall(MatDestroy(&matctx->Pi));
    1457          11 :   PetscCall(MatDestroy(&pjd->Pshell));
    1458          11 :   PetscCall(MatDestroy(&pcctx->PPr));
    1459          11 :   PetscCall(PCDestroy(&pcctx->pc));
    1460          11 :   PetscCall(PetscFree(pcctx));
    1461          11 :   PetscCall(PetscFree(matctx));
    1462          11 :   PetscCall(PCDestroy(&pjd->pcshell));
    1463          11 :   PetscCall(PetscFree3(eig,eigi,res));
    1464          11 :   PetscCall(VecDestroy(&pjd->vtempl));
    1465          11 :   PetscFunctionReturn(PETSC_SUCCESS);
    1466             : }
    1467             : 
    1468           3 : static PetscErrorCode PEPJDSetRestart_JD(PEP pep,PetscReal keep)
    1469             : {
    1470           3 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1471             : 
    1472           3 :   PetscFunctionBegin;
    1473           3 :   if (keep==(PetscReal)PETSC_DEFAULT || keep==(PetscReal)PETSC_DECIDE) pjd->keep = 0.5;
    1474             :   else {
    1475           3 :     PetscCheck(keep>=0.1 && keep<=0.9,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"The keep argument must be in the range [0.1,0.9]");
    1476           3 :     pjd->keep = keep;
    1477             :   }
    1478           3 :   PetscFunctionReturn(PETSC_SUCCESS);
    1479             : }
    1480             : 
    1481             : /*@
    1482             :    PEPJDSetRestart - Sets the restart parameter for the Jacobi-Davidson
    1483             :    method, in particular the proportion of basis vectors that must be kept
    1484             :    after restart.
    1485             : 
    1486             :    Logically Collective
    1487             : 
    1488             :    Input Parameters:
    1489             : +  pep  - the eigenproblem solver context
    1490             : -  keep - the number of vectors to be kept at restart
    1491             : 
    1492             :    Options Database Key:
    1493             : .  -pep_jd_restart - Sets the restart parameter
    1494             : 
    1495             :    Notes:
    1496             :    Allowed values are in the range [0.1,0.9]. The default is 0.5.
    1497             : 
    1498             :    Level: advanced
    1499             : 
    1500             : .seealso: PEPJDGetRestart()
    1501             : @*/
    1502           3 : PetscErrorCode PEPJDSetRestart(PEP pep,PetscReal keep)
    1503             : {
    1504           3 :   PetscFunctionBegin;
    1505           3 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1506           9 :   PetscValidLogicalCollectiveReal(pep,keep,2);
    1507           3 :   PetscTryMethod(pep,"PEPJDSetRestart_C",(PEP,PetscReal),(pep,keep));
    1508           3 :   PetscFunctionReturn(PETSC_SUCCESS);
    1509             : }
    1510             : 
    1511           2 : static PetscErrorCode PEPJDGetRestart_JD(PEP pep,PetscReal *keep)
    1512             : {
    1513           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1514             : 
    1515           2 :   PetscFunctionBegin;
    1516           2 :   *keep = pjd->keep;
    1517           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1518             : }
    1519             : 
    1520             : /*@
    1521             :    PEPJDGetRestart - Gets the restart parameter used in the Jacobi-Davidson method.
    1522             : 
    1523             :    Not Collective
    1524             : 
    1525             :    Input Parameter:
    1526             : .  pep - the eigenproblem solver context
    1527             : 
    1528             :    Output Parameter:
    1529             : .  keep - the restart parameter
    1530             : 
    1531             :    Level: advanced
    1532             : 
    1533             : .seealso: PEPJDSetRestart()
    1534             : @*/
    1535           2 : PetscErrorCode PEPJDGetRestart(PEP pep,PetscReal *keep)
    1536             : {
    1537           2 :   PetscFunctionBegin;
    1538           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1539           2 :   PetscAssertPointer(keep,2);
    1540           2 :   PetscUseMethod(pep,"PEPJDGetRestart_C",(PEP,PetscReal*),(pep,keep));
    1541           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1542             : }
    1543             : 
    1544           2 : static PetscErrorCode PEPJDSetFix_JD(PEP pep,PetscReal fix)
    1545             : {
    1546           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1547             : 
    1548           2 :   PetscFunctionBegin;
    1549           2 :   if (fix == (PetscReal)PETSC_DEFAULT || fix == (PetscReal)PETSC_DECIDE) pjd->fix = 0.01;
    1550             :   else {
    1551           2 :     PetscCheck(fix>=0.0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid fix value, must be >0");
    1552           2 :     pjd->fix = fix;
    1553             :   }
    1554           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1555             : }
    1556             : 
    1557             : /*@
    1558             :    PEPJDSetFix - Sets the threshold for changing the target in the correction
    1559             :    equation.
    1560             : 
    1561             :    Logically Collective
    1562             : 
    1563             :    Input Parameters:
    1564             : +  pep - the eigenproblem solver context
    1565             : -  fix - threshold for changing the target
    1566             : 
    1567             :    Options Database Key:
    1568             : .  -pep_jd_fix - the fix value
    1569             : 
    1570             :    Note:
    1571             :    The target in the correction equation is fixed at the first iterations.
    1572             :    When the norm of the residual vector is lower than the fix value,
    1573             :    the target is set to the corresponding eigenvalue.
    1574             : 
    1575             :    Level: advanced
    1576             : 
    1577             : .seealso: PEPJDGetFix()
    1578             : @*/
    1579           2 : PetscErrorCode PEPJDSetFix(PEP pep,PetscReal fix)
    1580             : {
    1581           2 :   PetscFunctionBegin;
    1582           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1583           6 :   PetscValidLogicalCollectiveReal(pep,fix,2);
    1584           2 :   PetscTryMethod(pep,"PEPJDSetFix_C",(PEP,PetscReal),(pep,fix));
    1585           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1586             : }
    1587             : 
    1588           2 : static PetscErrorCode PEPJDGetFix_JD(PEP pep,PetscReal *fix)
    1589             : {
    1590           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1591             : 
    1592           2 :   PetscFunctionBegin;
    1593           2 :   *fix = pjd->fix;
    1594           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1595             : }
    1596             : 
    1597             : /*@
    1598             :    PEPJDGetFix - Returns the threshold for changing the target in the correction
    1599             :    equation.
    1600             : 
    1601             :    Not Collective
    1602             : 
    1603             :    Input Parameter:
    1604             : .  pep - the eigenproblem solver context
    1605             : 
    1606             :    Output Parameter:
    1607             : .  fix - threshold for changing the target
    1608             : 
    1609             :    Note:
    1610             :    The target in the correction equation is fixed at the first iterations.
    1611             :    When the norm of the residual vector is lower than the fix value,
    1612             :    the target is set to the corresponding eigenvalue.
    1613             : 
    1614             :    Level: advanced
    1615             : 
    1616             : .seealso: PEPJDSetFix()
    1617             : @*/
    1618           2 : PetscErrorCode PEPJDGetFix(PEP pep,PetscReal *fix)
    1619             : {
    1620           2 :   PetscFunctionBegin;
    1621           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1622           2 :   PetscAssertPointer(fix,2);
    1623           2 :   PetscUseMethod(pep,"PEPJDGetFix_C",(PEP,PetscReal*),(pep,fix));
    1624           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1625             : }
    1626             : 
    1627           1 : static PetscErrorCode PEPJDSetReusePreconditioner_JD(PEP pep,PetscBool reusepc)
    1628             : {
    1629           1 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1630             : 
    1631           1 :   PetscFunctionBegin;
    1632           1 :   pjd->reusepc = reusepc;
    1633           1 :   PetscFunctionReturn(PETSC_SUCCESS);
    1634             : }
    1635             : 
    1636             : /*@
    1637             :    PEPJDSetReusePreconditioner - Sets a flag indicating whether the preconditioner
    1638             :    must be reused or not.
    1639             : 
    1640             :    Logically Collective
    1641             : 
    1642             :    Input Parameters:
    1643             : +  pep     - the eigenproblem solver context
    1644             : -  reusepc - the reuse flag
    1645             : 
    1646             :    Options Database Key:
    1647             : .  -pep_jd_reuse_preconditioner - the reuse flag
    1648             : 
    1649             :    Note:
    1650             :    The default value is False. If set to True, the preconditioner is built
    1651             :    only at the beginning, using the target value. Otherwise, it may be rebuilt
    1652             :    (depending on the fix parameter) at each iteration from the Ritz value.
    1653             : 
    1654             :    Level: advanced
    1655             : 
    1656             : .seealso: PEPJDGetReusePreconditioner(), PEPJDSetFix()
    1657             : @*/
    1658           1 : PetscErrorCode PEPJDSetReusePreconditioner(PEP pep,PetscBool reusepc)
    1659             : {
    1660           1 :   PetscFunctionBegin;
    1661           1 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1662           3 :   PetscValidLogicalCollectiveBool(pep,reusepc,2);
    1663           1 :   PetscTryMethod(pep,"PEPJDSetReusePreconditioner_C",(PEP,PetscBool),(pep,reusepc));
    1664           1 :   PetscFunctionReturn(PETSC_SUCCESS);
    1665             : }
    1666             : 
    1667           2 : static PetscErrorCode PEPJDGetReusePreconditioner_JD(PEP pep,PetscBool *reusepc)
    1668             : {
    1669           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1670             : 
    1671           2 :   PetscFunctionBegin;
    1672           2 :   *reusepc = pjd->reusepc;
    1673           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1674             : }
    1675             : 
    1676             : /*@
    1677             :    PEPJDGetReusePreconditioner - Returns the flag for reusing the preconditioner.
    1678             : 
    1679             :    Not Collective
    1680             : 
    1681             :    Input Parameter:
    1682             : .  pep - the eigenproblem solver context
    1683             : 
    1684             :    Output Parameter:
    1685             : .  reusepc - the reuse flag
    1686             : 
    1687             :    Level: advanced
    1688             : 
    1689             : .seealso: PEPJDSetReusePreconditioner()
    1690             : @*/
    1691           2 : PetscErrorCode PEPJDGetReusePreconditioner(PEP pep,PetscBool *reusepc)
    1692             : {
    1693           2 :   PetscFunctionBegin;
    1694           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1695           2 :   PetscAssertPointer(reusepc,2);
    1696           2 :   PetscUseMethod(pep,"PEPJDGetReusePreconditioner_C",(PEP,PetscBool*),(pep,reusepc));
    1697           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1698             : }
    1699             : 
    1700           2 : static PetscErrorCode PEPJDSetMinimalityIndex_JD(PEP pep,PetscInt mmidx)
    1701             : {
    1702           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1703             : 
    1704           2 :   PetscFunctionBegin;
    1705           2 :   if (mmidx == PETSC_DEFAULT || mmidx == PETSC_DECIDE) {
    1706           0 :     if (pjd->mmidx != 1) pep->state = PEP_STATE_INITIAL;
    1707           0 :     pjd->mmidx = 1;
    1708             :   } else {
    1709           2 :     PetscCheck(mmidx>0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid mmidx value, should be >0");
    1710           2 :     if (pjd->mmidx != mmidx) pep->state = PEP_STATE_INITIAL;
    1711           2 :     pjd->mmidx = mmidx;
    1712             :   }
    1713           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1714             : }
    1715             : 
    1716             : /*@
    1717             :    PEPJDSetMinimalityIndex - Sets the maximum allowed value for the minimality index.
    1718             : 
    1719             :    Logically Collective
    1720             : 
    1721             :    Input Parameters:
    1722             : +  pep   - the eigenproblem solver context
    1723             : -  mmidx - maximum minimality index
    1724             : 
    1725             :    Options Database Key:
    1726             : .  -pep_jd_minimality_index - the minimality index value
    1727             : 
    1728             :    Note:
    1729             :    The default value is equal to the degree of the polynomial. A smaller value
    1730             :    can be used if the wanted eigenvectors are known to be linearly independent.
    1731             : 
    1732             :    Level: advanced
    1733             : 
    1734             : .seealso: PEPJDGetMinimalityIndex()
    1735             : @*/
    1736           2 : PetscErrorCode PEPJDSetMinimalityIndex(PEP pep,PetscInt mmidx)
    1737             : {
    1738           2 :   PetscFunctionBegin;
    1739           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1740           6 :   PetscValidLogicalCollectiveInt(pep,mmidx,2);
    1741           2 :   PetscTryMethod(pep,"PEPJDSetMinimalityIndex_C",(PEP,PetscInt),(pep,mmidx));
    1742           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1743             : }
    1744             : 
    1745           2 : static PetscErrorCode PEPJDGetMinimalityIndex_JD(PEP pep,PetscInt *mmidx)
    1746             : {
    1747           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1748             : 
    1749           2 :   PetscFunctionBegin;
    1750           2 :   *mmidx = pjd->mmidx;
    1751           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1752             : }
    1753             : 
    1754             : /*@
    1755             :    PEPJDGetMinimalityIndex - Returns the maximum allowed value of the minimality
    1756             :    index.
    1757             : 
    1758             :    Not Collective
    1759             : 
    1760             :    Input Parameter:
    1761             : .  pep - the eigenproblem solver context
    1762             : 
    1763             :    Output Parameter:
    1764             : .  mmidx - minimality index
    1765             : 
    1766             :    Level: advanced
    1767             : 
    1768             : .seealso: PEPJDSetMinimalityIndex()
    1769             : @*/
    1770           2 : PetscErrorCode PEPJDGetMinimalityIndex(PEP pep,PetscInt *mmidx)
    1771             : {
    1772           2 :   PetscFunctionBegin;
    1773           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1774           2 :   PetscAssertPointer(mmidx,2);
    1775           2 :   PetscUseMethod(pep,"PEPJDGetMinimalityIndex_C",(PEP,PetscInt*),(pep,mmidx));
    1776           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1777             : }
    1778             : 
    1779           2 : static PetscErrorCode PEPJDSetProjection_JD(PEP pep,PEPJDProjection proj)
    1780             : {
    1781           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1782             : 
    1783           2 :   PetscFunctionBegin;
    1784           2 :   switch (proj) {
    1785           2 :     case PEP_JD_PROJECTION_HARMONIC:
    1786             :     case PEP_JD_PROJECTION_ORTHOGONAL:
    1787           2 :       if (pjd->proj != proj) {
    1788           2 :         pep->state = PEP_STATE_INITIAL;
    1789           2 :         pjd->proj = proj;
    1790             :       }
    1791           2 :       break;
    1792           0 :     default:
    1793           0 :       SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'proj' value");
    1794             :   }
    1795           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1796             : }
    1797             : 
    1798             : /*@
    1799             :    PEPJDSetProjection - Sets the type of projection to be used in the Jacobi-Davidson solver.
    1800             : 
    1801             :    Logically Collective
    1802             : 
    1803             :    Input Parameters:
    1804             : +  pep  - the eigenproblem solver context
    1805             : -  proj - the type of projection
    1806             : 
    1807             :    Options Database Key:
    1808             : .  -pep_jd_projection - the projection type, either orthogonal or harmonic
    1809             : 
    1810             :    Level: advanced
    1811             : 
    1812             : .seealso: PEPJDGetProjection()
    1813             : @*/
    1814           2 : PetscErrorCode PEPJDSetProjection(PEP pep,PEPJDProjection proj)
    1815             : {
    1816           2 :   PetscFunctionBegin;
    1817           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1818           6 :   PetscValidLogicalCollectiveEnum(pep,proj,2);
    1819           2 :   PetscTryMethod(pep,"PEPJDSetProjection_C",(PEP,PEPJDProjection),(pep,proj));
    1820           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1821             : }
    1822             : 
    1823           2 : static PetscErrorCode PEPJDGetProjection_JD(PEP pep,PEPJDProjection *proj)
    1824             : {
    1825           2 :   PEP_JD *pjd = (PEP_JD*)pep->data;
    1826             : 
    1827           2 :   PetscFunctionBegin;
    1828           2 :   *proj = pjd->proj;
    1829           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1830             : }
    1831             : 
    1832             : /*@
    1833             :    PEPJDGetProjection - Returns the type of projection used by the Jacobi-Davidson solver.
    1834             : 
    1835             :    Not Collective
    1836             : 
    1837             :    Input Parameter:
    1838             : .  pep - the eigenproblem solver context
    1839             : 
    1840             :    Output Parameter:
    1841             : .  proj - the type of projection
    1842             : 
    1843             :    Level: advanced
    1844             : 
    1845             : .seealso: PEPJDSetProjection()
    1846             : @*/
    1847           2 : PetscErrorCode PEPJDGetProjection(PEP pep,PEPJDProjection *proj)
    1848             : {
    1849           2 :   PetscFunctionBegin;
    1850           2 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
    1851           2 :   PetscAssertPointer(proj,2);
    1852           2 :   PetscUseMethod(pep,"PEPJDGetProjection_C",(PEP,PEPJDProjection*),(pep,proj));
    1853           2 :   PetscFunctionReturn(PETSC_SUCCESS);
    1854             : }
    1855             : 
    1856          10 : static PetscErrorCode PEPSetFromOptions_JD(PEP pep,PetscOptionItems *PetscOptionsObject)
    1857             : {
    1858          10 :   PetscBool       flg,b1;
    1859          10 :   PetscReal       r1;
    1860          10 :   PetscInt        i1;
    1861          10 :   PEPJDProjection proj;
    1862             : 
    1863          10 :   PetscFunctionBegin;
    1864          10 :   PetscOptionsHeadBegin(PetscOptionsObject,"PEP JD Options");
    1865             : 
    1866          10 :     PetscCall(PetscOptionsReal("-pep_jd_restart","Proportion of vectors kept after restart","PEPJDSetRestart",0.5,&r1,&flg));
    1867          10 :     if (flg) PetscCall(PEPJDSetRestart(pep,r1));
    1868             : 
    1869          10 :     PetscCall(PetscOptionsReal("-pep_jd_fix","Tolerance for changing the target in the correction equation","PEPJDSetFix",0.01,&r1,&flg));
    1870          10 :     if (flg) PetscCall(PEPJDSetFix(pep,r1));
    1871             : 
    1872          10 :     PetscCall(PetscOptionsBool("-pep_jd_reuse_preconditioner","Whether to reuse the preconditioner","PEPJDSetReusePreconditoiner",PETSC_FALSE,&b1,&flg));
    1873          10 :     if (flg) PetscCall(PEPJDSetReusePreconditioner(pep,b1));
    1874             : 
    1875          10 :     PetscCall(PetscOptionsInt("-pep_jd_minimality_index","Maximum allowed minimality index","PEPJDSetMinimalityIndex",1,&i1,&flg));
    1876          10 :     if (flg) PetscCall(PEPJDSetMinimalityIndex(pep,i1));
    1877             : 
    1878          10 :     PetscCall(PetscOptionsEnum("-pep_jd_projection","Type of projection","PEPJDSetProjection",PEPJDProjectionTypes,(PetscEnum)PEP_JD_PROJECTION_HARMONIC,(PetscEnum*)&proj,&flg));
    1879          10 :     if (flg) PetscCall(PEPJDSetProjection(pep,proj));
    1880             : 
    1881          10 :   PetscOptionsHeadEnd();
    1882          10 :   PetscFunctionReturn(PETSC_SUCCESS);
    1883             : }
    1884             : 
    1885           0 : static PetscErrorCode PEPView_JD(PEP pep,PetscViewer viewer)
    1886             : {
    1887           0 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
    1888           0 :   PetscBool      isascii;
    1889             : 
    1890           0 :   PetscFunctionBegin;
    1891           0 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    1892           0 :   if (isascii) {
    1893           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  %d%% of basis vectors kept after restart\n",(int)(100*pjd->keep)));
    1894           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  threshold for changing the target in the correction equation (fix): %g\n",(double)pjd->fix));
    1895           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  projection type: %s\n",PEPJDProjectionTypes[pjd->proj]));
    1896           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum allowed minimality index: %" PetscInt_FMT "\n",pjd->mmidx));
    1897           0 :     if (pjd->reusepc) PetscCall(PetscViewerASCIIPrintf(viewer,"  reusing the preconditioner\n"));
    1898             :   }
    1899           0 :   PetscFunctionReturn(PETSC_SUCCESS);
    1900             : }
    1901             : 
    1902          21 : static PetscErrorCode PEPSetDefaultST_JD(PEP pep)
    1903             : {
    1904          21 :   KSP            ksp;
    1905             : 
    1906          21 :   PetscFunctionBegin;
    1907          21 :   if (!((PetscObject)pep->st)->type_name) {
    1908          10 :     PetscCall(STSetType(pep->st,STPRECOND));
    1909          10 :     PetscCall(STPrecondSetKSPHasMat(pep->st,PETSC_TRUE));
    1910             :   }
    1911          21 :   PetscCall(STSetTransform(pep->st,PETSC_FALSE));
    1912          21 :   PetscCall(STGetKSP(pep->st,&ksp));
    1913          21 :   if (!((PetscObject)ksp)->type_name) {
    1914          10 :     PetscCall(KSPSetType(ksp,KSPBCGSL));
    1915          10 :     PetscCall(KSPSetTolerances(ksp,1e-5,PETSC_CURRENT,PETSC_CURRENT,100));
    1916             :   }
    1917          21 :   PetscFunctionReturn(PETSC_SUCCESS);
    1918             : }
    1919             : 
    1920          12 : static PetscErrorCode PEPReset_JD(PEP pep)
    1921             : {
    1922          12 :   PEP_JD         *pjd = (PEP_JD*)pep->data;
    1923          12 :   PetscInt       i;
    1924             : 
    1925          12 :   PetscFunctionBegin;
    1926          47 :   for (i=0;i<pep->nmat;i++) PetscCall(BVDestroy(pjd->TV+i));
    1927          12 :   if (pjd->proj==PEP_JD_PROJECTION_HARMONIC) PetscCall(BVDestroy(&pjd->W));
    1928          12 :   if (pjd->ld>1) {
    1929          12 :     PetscCall(BVDestroy(&pjd->V));
    1930          47 :     for (i=0;i<pep->nmat;i++) PetscCall(BVDestroy(pjd->AX+i));
    1931          12 :     PetscCall(BVDestroy(&pjd->N[0]));
    1932          12 :     PetscCall(BVDestroy(&pjd->N[1]));
    1933          12 :     PetscCall(PetscFree3(pjd->XpX,pjd->T,pjd->Tj));
    1934             :   }
    1935          12 :   PetscCall(PetscFree2(pjd->TV,pjd->AX));
    1936          12 :   PetscFunctionReturn(PETSC_SUCCESS);
    1937             : }
    1938             : 
    1939          10 : static PetscErrorCode PEPDestroy_JD(PEP pep)
    1940             : {
    1941          10 :   PetscFunctionBegin;
    1942          10 :   PetscCall(PetscFree(pep->data));
    1943          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetRestart_C",NULL));
    1944          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetRestart_C",NULL));
    1945          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetFix_C",NULL));
    1946          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetFix_C",NULL));
    1947          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetReusePreconditioner_C",NULL));
    1948          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetReusePreconditioner_C",NULL));
    1949          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetMinimalityIndex_C",NULL));
    1950          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetMinimalityIndex_C",NULL));
    1951          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetProjection_C",NULL));
    1952          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetProjection_C",NULL));
    1953          10 :   PetscFunctionReturn(PETSC_SUCCESS);
    1954             : }
    1955             : 
    1956          10 : SLEPC_EXTERN PetscErrorCode PEPCreate_JD(PEP pep)
    1957             : {
    1958          10 :   PEP_JD         *pjd;
    1959             : 
    1960          10 :   PetscFunctionBegin;
    1961          10 :   PetscCall(PetscNew(&pjd));
    1962          10 :   pep->data = (void*)pjd;
    1963             : 
    1964          10 :   pep->lineariz = PETSC_FALSE;
    1965          10 :   pjd->fix      = 0.01;
    1966          10 :   pjd->mmidx    = 0;
    1967             : 
    1968          10 :   pep->ops->solve          = PEPSolve_JD;
    1969          10 :   pep->ops->setup          = PEPSetUp_JD;
    1970          10 :   pep->ops->setfromoptions = PEPSetFromOptions_JD;
    1971          10 :   pep->ops->destroy        = PEPDestroy_JD;
    1972          10 :   pep->ops->reset          = PEPReset_JD;
    1973          10 :   pep->ops->view           = PEPView_JD;
    1974          10 :   pep->ops->setdefaultst   = PEPSetDefaultST_JD;
    1975             : 
    1976          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetRestart_C",PEPJDSetRestart_JD));
    1977          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetRestart_C",PEPJDGetRestart_JD));
    1978          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetFix_C",PEPJDSetFix_JD));
    1979          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetFix_C",PEPJDGetFix_JD));
    1980          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetReusePreconditioner_C",PEPJDSetReusePreconditioner_JD));
    1981          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetReusePreconditioner_C",PEPJDGetReusePreconditioner_JD));
    1982          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetMinimalityIndex_C",PEPJDSetMinimalityIndex_JD));
    1983          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetMinimalityIndex_C",PEPJDGetMinimalityIndex_JD));
    1984          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDSetProjection_C",PEPJDSetProjection_JD));
    1985          10 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPJDGetProjection_C",PEPJDGetProjection_JD));
    1986          10 :   PetscFunctionReturn(PETSC_SUCCESS);
    1987             : }

Generated by: LCOV version 1.14