LCOV - code coverage report
Current view: top level - eps/impls/davidson - dvdcalcpairs.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 358 388 92.3 %
Date: 2024-11-21 00:40:22 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       3             :    SLEPc - Scalable Library for Eigenvalue Problem Computations
       4             :    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
       5             : 
       6             :    This file is part of SLEPc.
       7             :    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
       8             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       9             : */
      10             : /*
      11             :    SLEPc eigensolver: "davidson"
      12             : 
      13             :    Step: calculate the best eigenpairs in the subspace V
      14             : 
      15             :    For that, performs these steps:
      16             :      1) Update W <- A * V
      17             :      2) Update H <- V' * W
      18             :      3) Obtain eigenpairs of H
      19             :      4) Select some eigenpairs
      20             :      5) Compute the Ritz pairs of the selected ones
      21             : */
      22             : 
      23             : #include "davidson.h"
      24             : #include <slepcblaslapack.h>
      25             : 
      26          97 : static PetscErrorCode dvd_calcpairs_qz_start(dvdDashboard *d)
      27             : {
      28          97 :   PetscFunctionBegin;
      29          97 :   PetscCall(BVSetActiveColumns(d->eps->V,0,0));
      30          97 :   if (d->W) PetscCall(BVSetActiveColumns(d->W,0,0));
      31          97 :   PetscCall(BVSetActiveColumns(d->AX,0,0));
      32          97 :   if (d->BX) PetscCall(BVSetActiveColumns(d->BX,0,0));
      33          97 :   PetscFunctionReturn(PETSC_SUCCESS);
      34             : }
      35             : 
      36          97 : static PetscErrorCode dvd_calcpairs_qz_d(dvdDashboard *d)
      37             : {
      38          97 :   PetscFunctionBegin;
      39          97 :   PetscCall(BVDestroy(&d->W));
      40          97 :   PetscCall(BVDestroy(&d->AX));
      41          97 :   PetscCall(BVDestroy(&d->BX));
      42          97 :   PetscCall(BVDestroy(&d->auxBV));
      43          97 :   PetscCall(MatDestroy(&d->H));
      44          97 :   PetscCall(MatDestroy(&d->G));
      45          97 :   PetscCall(MatDestroy(&d->auxM));
      46          97 :   PetscCall(SlepcVecPoolDestroy(&d->auxV));
      47          97 :   PetscCall(PetscFree(d->nBds));
      48          97 :   PetscFunctionReturn(PETSC_SUCCESS);
      49             : }
      50             : 
      51             : /* in complex, d->size_H real auxiliary values are needed */
      52        9045 : static PetscErrorCode dvd_calcpairs_projeig_solve(dvdDashboard *d)
      53             : {
      54        9045 :   Vec               v;
      55        9045 :   Mat               A,B,H0,G0;
      56        9045 :   PetscScalar       *pA;
      57        9045 :   const PetscScalar *pv;
      58        9045 :   PetscInt          i,lV,kV,n,ld;
      59             : 
      60        9045 :   PetscFunctionBegin;
      61        9045 :   PetscCall(BVGetActiveColumns(d->eps->V,&lV,&kV));
      62        9045 :   n = kV-lV;
      63        9045 :   PetscCall(DSSetDimensions(d->eps->ds,n,0,0));
      64        9045 :   PetscCall(DSGetMat(d->eps->ds,DS_MAT_A,&A));
      65        9045 :   PetscCall(MatDenseGetSubMatrix(d->H,lV,lV+n,lV,lV+n,&H0));
      66        9045 :   PetscCall(MatCopy(H0,A,SAME_NONZERO_PATTERN));
      67        9045 :   PetscCall(MatDenseRestoreSubMatrix(d->H,&H0));
      68        9045 :   PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_A,&A));
      69        9045 :   if (d->G) {
      70        1536 :     PetscCall(DSGetMat(d->eps->ds,DS_MAT_B,&B));
      71        1536 :     PetscCall(MatDenseGetSubMatrix(d->G,lV,lV+n,lV,lV+n,&G0));
      72        1536 :     PetscCall(MatCopy(G0,B,SAME_NONZERO_PATTERN));
      73        1536 :     PetscCall(MatDenseRestoreSubMatrix(d->G,&G0));
      74        1536 :     PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_B,&B));
      75             :   }
      76             :   /* Set the signature on projected matrix B */
      77        9045 :   if (DVD_IS(d->sEP,DVD_EP_INDEFINITE)) {
      78           0 :     PetscCall(DSGetLeadingDimension(d->eps->ds,&ld));
      79           0 :     PetscCall(DSGetArray(d->eps->ds,DS_MAT_B,&pA));
      80           0 :     PetscCall(PetscArrayzero(pA,n*ld));
      81           0 :     PetscCall(VecCreateSeq(PETSC_COMM_SELF,kV,&v));
      82           0 :     PetscCall(BVGetSignature(d->eps->V,v));
      83           0 :     PetscCall(VecGetArrayRead(v,&pv));
      84           0 :     for (i=0;i<n;i++) {
      85           0 :       pA[i+ld*i] = d->nBds[i] = PetscRealPart(pv[lV+i]);
      86             :     }
      87           0 :     PetscCall(VecRestoreArrayRead(v,&pv));
      88           0 :     PetscCall(VecDestroy(&v));
      89           0 :     PetscCall(DSRestoreArray(d->eps->ds,DS_MAT_B,&pA));
      90             :   }
      91        9045 :   PetscCall(DSSetState(d->eps->ds,DS_STATE_RAW));
      92        9045 :   PetscCall(DSSolve(d->eps->ds,d->eigr,d->eigi));
      93        9045 :   PetscFunctionReturn(PETSC_SUCCESS);
      94             : }
      95             : 
      96             : /*
      97             :    A(lA:kA-1,lA:kA-1) <- Z(l:k-1)'*A(l:k-1,l:k-1)*Q(l,k-1), where k=l+kA-lA
      98             :  */
      99        1794 : static PetscErrorCode EPSXDUpdateProj(Mat Q,Mat Z,PetscInt l,Mat A,PetscInt lA,PetscInt kA,Mat aux)
     100             : {
     101        1794 :   PetscScalar       one=1.0,zero=0.0;
     102        1794 :   PetscInt          i,j,dA_=kA-lA,m0,n0,ldA_,ldQ_,ldZ_,nQ_;
     103        1794 :   PetscBLASInt      dA,nQ,ldA,ldQ,ldZ;
     104        1794 :   PetscScalar       *pA,*pW;
     105        1794 :   const PetscScalar *pQ,*pZ;
     106        1794 :   PetscBool         symm=PETSC_FALSE,set,flg;
     107             : 
     108        1794 :   PetscFunctionBegin;
     109        1794 :   PetscCall(MatGetSize(A,&m0,&n0));
     110        1794 :   PetscCall(MatDenseGetLDA(A,&ldA_));
     111        1794 :   PetscAssert(m0==n0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"A should be square");
     112        1794 :   PetscAssert(lA>=0 && lA<=m0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid initial row, column in A");
     113        1794 :   PetscAssert(kA>=0 && kA>=lA && kA<=m0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid final row, column in A");
     114        1794 :   PetscCall(MatIsHermitianKnown(A,&set,&flg));
     115        1794 :   symm = set? flg: PETSC_FALSE;
     116        1794 :   PetscCall(MatGetSize(Q,&m0,&n0)); nQ_=m0;
     117        1794 :   PetscCall(MatDenseGetLDA(Q,&ldQ_));
     118        1794 :   PetscAssert(l>=0 && l<=n0 && l+dA_<=n0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid initial column in Q");
     119        1794 :   PetscCall(MatGetSize(Z,&m0,&n0));
     120        1794 :   PetscCall(MatDenseGetLDA(Z,&ldZ_));
     121        1794 :   PetscAssert(l>=0 && l<=n0 && l+dA_<=n0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid initial column in Z");
     122        1794 :   PetscCall(MatGetSize(aux,&m0,&n0));
     123        1794 :   PetscAssert(m0*n0>=nQ_*dA_,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"aux should be larger");
     124        1794 :   PetscCall(PetscBLASIntCast(dA_,&dA));
     125        1794 :   PetscCall(PetscBLASIntCast(nQ_,&nQ));
     126        1794 :   PetscCall(PetscBLASIntCast(ldA_,&ldA));
     127        1794 :   PetscCall(PetscBLASIntCast(ldQ_,&ldQ));
     128        1794 :   PetscCall(PetscBLASIntCast(ldZ_,&ldZ));
     129        1794 :   PetscCall(MatDenseGetArray(A,&pA));
     130        1794 :   PetscCall(MatDenseGetArrayRead(Q,&pQ));
     131        1794 :   if (Q!=Z) PetscCall(MatDenseGetArrayRead(Z,&pZ));
     132        1322 :   else pZ = pQ;
     133        1794 :   PetscCall(MatDenseGetArrayWrite(aux,&pW));
     134             :   /* W = A*Q */
     135        1794 :   if (symm) {
     136             :     /* symmetrize before multiplying */
     137       16618 :     for (i=lA+1;i<lA+nQ;i++) {
     138      129493 :       for (j=lA;j<i;j++) pA[i+j*ldA] = PetscConj(pA[j+i*ldA]);
     139             :     }
     140             :   }
     141        1794 :   PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&nQ,&dA,&nQ,&one,&pA[ldA*lA+lA],&ldA,&pQ[ldQ*l+l],&ldQ,&zero,pW,&nQ));
     142             :   /* A = Q'*W */
     143        1794 :   PetscCallBLAS("BLASgemm",BLASgemm_("C","N",&dA,&dA,&nQ,&one,&pZ[ldZ*l+l],&ldZ,pW,&nQ,&zero,&pA[ldA*lA+lA],&ldA));
     144        1794 :   PetscCall(MatDenseRestoreArray(A,&pA));
     145        1794 :   PetscCall(MatDenseRestoreArrayRead(Q,&pQ));
     146        1794 :   if (Q!=Z) PetscCall(MatDenseRestoreArrayRead(Z,&pZ));
     147        1794 :   PetscCall(MatDenseRestoreArrayWrite(aux,&pW));
     148        1794 :   PetscFunctionReturn(PETSC_SUCCESS);
     149             : }
     150             : 
     151        1558 : static PetscErrorCode dvd_calcpairs_updateproj(dvdDashboard *d)
     152             : {
     153        1558 :   Mat            Q,Z;
     154        1558 :   PetscInt       lV,kV;
     155        1558 :   PetscBool      symm;
     156             : 
     157        1558 :   PetscFunctionBegin;
     158        1558 :   PetscCall(DSGetMat(d->eps->ds,DS_MAT_Q,&Q));
     159        1558 :   if (d->W) PetscCall(DSGetMat(d->eps->ds,DS_MAT_Z,&Z));
     160        1322 :   else Z = Q;
     161        1558 :   PetscCall(BVGetActiveColumns(d->eps->V,&lV,&kV));
     162        1558 :   PetscCall(EPSXDUpdateProj(Q,Z,0,d->H,lV,lV+d->V_tra_e,d->auxM));
     163        1558 :   if (d->G) PetscCall(EPSXDUpdateProj(Q,Z,0,d->G,lV,lV+d->V_tra_e,d->auxM));
     164        1558 :   PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_Q,&Q));
     165        1558 :   if (d->W) PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_Z,&Z));
     166             : 
     167        1558 :   PetscCall(PetscObjectTypeCompareAny((PetscObject)d->eps->ds,&symm,DSHEP,DSGHIEP,DSGHEP,""));
     168        1558 :   if (d->V_tra_s==0 || symm) PetscFunctionReturn(PETSC_SUCCESS);
     169             :   /* Compute upper part of H (and G): H(0:l-1,l:k-1) <- W(0:l-1)' * AV(l:k-1), where
     170             :      k=l+d->V_tra_s */
     171          69 :   PetscCall(BVSetActiveColumns(d->W?d->W:d->eps->V,0,lV));
     172          69 :   PetscCall(BVSetActiveColumns(d->AX,lV,lV+d->V_tra_s));
     173          69 :   PetscCall(BVDot(d->AX,d->W?d->W:d->eps->V,d->H));
     174          69 :   if (d->G) {
     175          57 :     PetscCall(BVSetActiveColumns(d->BX?d->BX:d->eps->V,lV,lV+d->V_tra_s));
     176          57 :     PetscCall(BVDot(d->BX?d->BX:d->eps->V,d->W?d->W:d->eps->V,d->G));
     177             :   }
     178          69 :   PetscCall(PetscObjectTypeCompare((PetscObject)d->eps->ds,DSGHEP,&symm));
     179          69 :   if (!symm) {
     180          69 :     PetscCall(BVSetActiveColumns(d->W?d->W:d->eps->V,lV,lV+d->V_tra_s));
     181          69 :     PetscCall(BVSetActiveColumns(d->AX,0,lV));
     182          69 :     PetscCall(BVDot(d->AX,d->W?d->W:d->eps->V,d->H));
     183          69 :     if (d->G) {
     184          57 :       PetscCall(BVSetActiveColumns(d->BX?d->BX:d->eps->V,0,lV));
     185          57 :       PetscCall(BVDot(d->BX?d->BX:d->eps->V,d->W?d->W:d->eps->V,d->G));
     186             :     }
     187             :   }
     188          69 :   PetscCall(BVSetActiveColumns(d->eps->V,lV,kV));
     189          69 :   PetscCall(BVSetActiveColumns(d->AX,lV,kV));
     190          69 :   if (d->BX) PetscCall(BVSetActiveColumns(d->BX,lV,kV));
     191          69 :   if (d->W) PetscCall(BVSetActiveColumns(d->W,lV,kV));
     192          69 :   if (d->W) PetscCall(dvd_harm_updateproj(d));
     193          69 :   PetscFunctionReturn(PETSC_SUCCESS);
     194             : }
     195             : 
     196             : /*
     197             :    BV <- BV*MT
     198             :  */
     199        3567 : static inline PetscErrorCode dvd_calcpairs_updateBV0_gen(dvdDashboard *d,BV bv,DSMatType mat)
     200             : {
     201        3567 :   PetscInt       l,k,n;
     202        3567 :   Mat            M,M0,auxM,auxM0;
     203             : 
     204        3567 :   PetscFunctionBegin;
     205        3567 :   PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
     206        3567 :   PetscCall(DSGetDimensions(d->eps->ds,&n,NULL,NULL,NULL));
     207        3567 :   PetscAssert(k-l==n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
     208        3567 :   PetscCall(DSGetMat(d->eps->ds,mat,&M));
     209        3567 :   PetscCall(MatDenseGetSubMatrix(M,0,n,0,d->V_tra_e,&M0));
     210        3567 :   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,k,k,NULL,&auxM));
     211        3567 :   PetscCall(MatDenseGetSubMatrix(auxM,l,l+n,l,l+d->V_tra_e,&auxM0));
     212        3567 :   PetscCall(MatCopy(M0,auxM0,SAME_NONZERO_PATTERN));
     213        3567 :   PetscCall(MatDenseRestoreSubMatrix(auxM,&auxM0));
     214        3567 :   PetscCall(MatDenseRestoreSubMatrix(M,&M0));
     215        3567 :   PetscCall(DSRestoreMat(d->eps->ds,mat,&M));
     216        3567 :   PetscCall(BVMultInPlace(bv,auxM,l,l+d->V_tra_e));
     217        3567 :   PetscCall(MatDestroy(&auxM));
     218        3567 :   PetscFunctionReturn(PETSC_SUCCESS);
     219             : }
     220             : 
     221        9045 : static PetscErrorCode dvd_calcpairs_proj(dvdDashboard *d)
     222             : {
     223        9045 :   PetscInt       i,l,k;
     224        9045 :   Vec            v1,v2;
     225        9045 :   PetscScalar    *pv;
     226             : 
     227        9045 :   PetscFunctionBegin;
     228        9045 :   PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
     229             :   /* Update AV, BV, W and the projected matrices */
     230             :   /* 1. S <- S*MT */
     231        9045 :   if (d->V_tra_s != d->V_tra_e || d->V_tra_e > 0) {
     232        1558 :     PetscCall(dvd_calcpairs_updateBV0_gen(d,d->eps->V,DS_MAT_Q));
     233        1558 :     if (d->W) PetscCall(dvd_calcpairs_updateBV0_gen(d,d->W,DS_MAT_Z));
     234        1558 :     PetscCall(dvd_calcpairs_updateBV0_gen(d,d->AX,DS_MAT_Q));
     235        1558 :     if (d->BX) PetscCall(dvd_calcpairs_updateBV0_gen(d,d->BX,DS_MAT_Q));
     236        1558 :     PetscCall(dvd_calcpairs_updateproj(d));
     237             :     /* Update signature */
     238        1558 :     if (d->nBds) {
     239           0 :       PetscCall(VecCreateSeq(PETSC_COMM_SELF,l+d->V_tra_e,&v1));
     240           0 :       PetscCall(BVSetActiveColumns(d->eps->V,0,l+d->V_tra_e));
     241           0 :       PetscCall(BVGetSignature(d->eps->V,v1));
     242           0 :       PetscCall(VecGetArray(v1,&pv));
     243           0 :       for (i=0;i<d->V_tra_e;i++) pv[l+i] = d->nBds[i];
     244           0 :       PetscCall(VecRestoreArray(v1,&pv));
     245           0 :       PetscCall(BVSetSignature(d->eps->V,v1));
     246           0 :       PetscCall(BVSetActiveColumns(d->eps->V,l,k));
     247           0 :       PetscCall(VecDestroy(&v1));
     248             :     }
     249        1558 :     k = l+d->V_tra_e;
     250        1558 :     l+= d->V_tra_s;
     251             :   } else {
     252             :     /* 2. V <- orth(V, V_new) */
     253        7487 :     PetscCall(dvd_orthV(d->eps->V,l+d->V_new_s,l+d->V_new_e));
     254             :     /* 3. AV <- [AV A * V(V_new_s:V_new_e-1)] */
     255             :     /* Check consistency */
     256        7487 :     PetscAssert(k-l==d->V_new_s,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
     257       18311 :     for (i=l+d->V_new_s;i<l+d->V_new_e;i++) {
     258       10824 :       PetscCall(BVGetColumn(d->eps->V,i,&v1));
     259       10824 :       PetscCall(BVGetColumn(d->AX,i,&v2));
     260       10824 :       PetscCall(MatMult(d->A,v1,v2));
     261       10824 :       PetscCall(BVRestoreColumn(d->eps->V,i,&v1));
     262       10824 :       PetscCall(BVRestoreColumn(d->AX,i,&v2));
     263             :     }
     264             :     /* 4. BV <- [BV B * V(V_new_s:V_new_e-1)] */
     265        7487 :     if (d->BX) {
     266             :       /* Check consistency */
     267        1321 :       PetscAssert(k-l==d->V_new_s,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
     268        2856 :       for (i=l+d->V_new_s;i<l+d->V_new_e;i++) {
     269        1535 :         PetscCall(BVGetColumn(d->eps->V,i,&v1));
     270        1535 :         PetscCall(BVGetColumn(d->BX,i,&v2));
     271        1535 :         PetscCall(MatMult(d->B,v1,v2));
     272        1535 :         PetscCall(BVRestoreColumn(d->eps->V,i,&v1));
     273        1535 :         PetscCall(BVRestoreColumn(d->BX,i,&v2));
     274             :       }
     275             :     }
     276             :     /* 5. W <- [W f(AV,BV)] */
     277        7487 :     if (d->W) {
     278        1300 :       PetscCall(d->calcpairs_W(d));
     279        1300 :       PetscCall(dvd_orthV(d->W,l+d->V_new_s,l+d->V_new_e));
     280             :     }
     281             :     /* 6. H <- W' * AX; G <- W' * BX */
     282        7487 :     PetscCall(BVSetActiveColumns(d->eps->V,l+d->V_new_s,l+d->V_new_e));
     283        7487 :     PetscCall(BVSetActiveColumns(d->AX,l+d->V_new_s,l+d->V_new_e));
     284        7487 :     if (d->BX) PetscCall(BVSetActiveColumns(d->BX,l+d->V_new_s,l+d->V_new_e));
     285        7487 :     if (d->W) PetscCall(BVSetActiveColumns(d->W,l+d->V_new_s,l+d->V_new_e));
     286        7487 :     PetscCall(BVMatProject(d->AX,NULL,d->W?d->W:d->eps->V,d->H));
     287        7487 :     if (d->G) PetscCall(BVMatProject(d->BX?d->BX:d->eps->V,NULL,d->W?d->W:d->eps->V,d->G));
     288        7487 :     PetscCall(BVSetActiveColumns(d->eps->V,l,k));
     289        7487 :     PetscCall(BVSetActiveColumns(d->AX,l,k));
     290        7487 :     if (d->BX) PetscCall(BVSetActiveColumns(d->BX,l,k));
     291        7487 :     if (d->W) PetscCall(BVSetActiveColumns(d->W,l,k));
     292             : 
     293             :     /* Perform the transformation on the projected problem */
     294        7487 :     if (d->W) PetscCall(d->calcpairs_proj_trans(d));
     295        7487 :     k = l+d->V_new_e;
     296             :   }
     297        9045 :   PetscCall(BVSetActiveColumns(d->eps->V,l,k));
     298        9045 :   PetscCall(BVSetActiveColumns(d->AX,l,k));
     299        9045 :   if (d->BX) PetscCall(BVSetActiveColumns(d->BX,l,k));
     300        9045 :   if (d->W) PetscCall(BVSetActiveColumns(d->W,l,k));
     301             : 
     302             :   /* Solve the projected problem */
     303        9045 :   PetscCall(dvd_calcpairs_projeig_solve(d));
     304             : 
     305        9045 :   d->V_tra_s = d->V_tra_e = 0;
     306        9045 :   d->V_new_s = d->V_new_e;
     307        9045 :   PetscFunctionReturn(PETSC_SUCCESS);
     308             : }
     309             : 
     310       10656 : static PetscErrorCode dvd_calcpairs_apply_arbitrary(dvdDashboard *d,PetscInt r_s,PetscInt r_e,PetscScalar *rr,PetscScalar *ri)
     311             : {
     312       10656 :   PetscInt       i,k,ld;
     313       10656 :   PetscScalar    *pX;
     314       10656 :   Vec            *X,xr,xi;
     315             : #if defined(PETSC_USE_COMPLEX)
     316       10656 :   PetscInt       N=1;
     317             : #else
     318             :   PetscInt       N=2,j;
     319             : #endif
     320             : 
     321       10656 :   PetscFunctionBegin;
     322             :   /* Quick exit without neither arbitrary selection nor harmonic extraction */
     323       10656 :   if (!d->eps->arbitrary && !d->calcpairs_eig_backtrans) PetscFunctionReturn(PETSC_SUCCESS);
     324             : 
     325             :   /* Quick exit without arbitrary selection, but with harmonic extraction */
     326        3416 :   if (d->calcpairs_eig_backtrans) {
     327       37126 :     for (i=r_s; i<r_e; i++) PetscCall(d->calcpairs_eig_backtrans(d,d->eigr[i],d->eigi[i],&rr[i-r_s],&ri[i-r_s]));
     328             :   }
     329        3416 :   if (!d->eps->arbitrary) PetscFunctionReturn(PETSC_SUCCESS);
     330             : 
     331        1362 :   PetscCall(SlepcVecPoolGetVecs(d->auxV,N,&X));
     332        1362 :   PetscCall(DSGetLeadingDimension(d->eps->ds,&ld));
     333       17270 :   for (i=r_s;i<r_e;i++) {
     334       15908 :     k = i;
     335       15908 :     PetscCall(DSVectors(d->eps->ds,DS_MAT_X,&k,NULL));
     336       15908 :     PetscCall(DSGetArray(d->eps->ds,DS_MAT_X,&pX));
     337       15908 :     PetscCall(dvd_improvex_compute_X(d,i,k+1,X,pX,ld));
     338       15908 :     PetscCall(DSRestoreArray(d->eps->ds,DS_MAT_X,&pX));
     339             : #if !defined(PETSC_USE_COMPLEX)
     340             :     if (d->nX[i] != 1.0) {
     341             :       for (j=i;j<k+1;j++) PetscCall(VecScale(X[j-i],1.0/d->nX[i]));
     342             :     }
     343             :     xr = X[0];
     344             :     xi = X[1];
     345             :     if (i == k) PetscCall(VecSet(xi,0.0));
     346             : #else
     347       15908 :     xr = X[0];
     348       15908 :     xi = NULL;
     349       15908 :     if (d->nX[i] != 1.0) PetscCall(VecScale(xr,1.0/d->nX[i]));
     350             : #endif
     351       15908 :     PetscCall(d->eps->arbitrary(rr[i-r_s],ri[i-r_s],xr,xi,&rr[i-r_s],&ri[i-r_s],d->eps->arbitraryctx));
     352             : #if !defined(PETSC_USE_COMPLEX)
     353             :     if (i != k) {
     354             :       rr[i+1-r_s] = rr[i-r_s];
     355             :       ri[i+1-r_s] = ri[i-r_s];
     356             :       i++;
     357             :     }
     358             : #endif
     359             :   }
     360        1362 :   PetscCall(SlepcVecPoolRestoreVecs(d->auxV,N,&X));
     361        1362 :   PetscFunctionReturn(PETSC_SUCCESS);
     362             : }
     363             : 
     364        8948 : static PetscErrorCode dvd_calcpairs_selectPairs(dvdDashboard *d,PetscInt n)
     365             : {
     366        8948 :   PetscInt       k,lV,kV,nV;
     367        8948 :   PetscScalar    *rr,*ri;
     368             : 
     369        8948 :   PetscFunctionBegin;
     370        8948 :   PetscCall(BVGetActiveColumns(d->eps->V,&lV,&kV));
     371        8948 :   nV = kV - lV;
     372        8948 :   n = PetscMin(n,nV);
     373        8948 :   if (n <= 0) PetscFunctionReturn(PETSC_SUCCESS);
     374             :   /* Put the best n pairs at the beginning. Useful for restarting */
     375        8948 :   if (d->eps->arbitrary || d->calcpairs_eig_backtrans) {
     376        1708 :     PetscCall(PetscMalloc1(nV,&rr));
     377        1708 :     PetscCall(PetscMalloc1(nV,&ri));
     378        1708 :     PetscCall(dvd_calcpairs_apply_arbitrary(d,0,nV,rr,ri));
     379             :   } else {
     380        7240 :     rr = d->eigr;
     381        7240 :     ri = d->eigi;
     382             :   }
     383        8948 :   k = n;
     384        8948 :   PetscCall(DSSort(d->eps->ds,d->eigr,d->eigi,rr,ri,&k));
     385             :   /* Put the best pair at the beginning. Useful to check its residual */
     386             : #if !defined(PETSC_USE_COMPLEX)
     387             :   if (n != 1 && (n != 2 || d->eigi[0] == 0.0))
     388             : #else
     389        8948 :   if (n != 1)
     390             : #endif
     391             :   {
     392        8948 :     PetscCall(dvd_calcpairs_apply_arbitrary(d,0,nV,rr,ri));
     393        8948 :     k = 1;
     394        8948 :     PetscCall(DSSort(d->eps->ds,d->eigr,d->eigi,rr,ri,&k));
     395             :   }
     396        8948 :   PetscCall(DSSynchronize(d->eps->ds,d->eigr,d->eigi));
     397             : 
     398        8948 :   if (d->calcpairs_eigs_trans) PetscCall(d->calcpairs_eigs_trans(d));
     399        8948 :   if (d->eps->arbitrary || d->calcpairs_eig_backtrans) {
     400        1708 :     PetscCall(PetscFree(rr));
     401        1708 :     PetscCall(PetscFree(ri));
     402             :   }
     403        8948 :   PetscFunctionReturn(PETSC_SUCCESS);
     404             : }
     405             : 
     406          97 : static PetscErrorCode EPSXDComputeDSConv(dvdDashboard *d)
     407             : {
     408          97 :   PetscInt          i,ld;
     409          97 :   Vec               v;
     410          97 :   Mat               A,B,H0,G0;
     411          97 :   PetscScalar       *pA;
     412          97 :   const PetscScalar *pv;
     413          97 :   PetscBool         symm;
     414             : 
     415          97 :   PetscFunctionBegin;
     416          97 :   PetscCall(BVSetActiveColumns(d->eps->V,0,d->eps->nconv));
     417          97 :   PetscCall(PetscObjectTypeCompare((PetscObject)d->eps->ds,DSHEP,&symm));
     418          97 :   if (symm || !d->eps->nconv) PetscFunctionReturn(PETSC_SUCCESS);
     419          26 :   PetscCall(DSSetDimensions(d->eps->ds,d->eps->nconv,0,0));
     420          26 :   PetscCall(DSGetMat(d->eps->ds,DS_MAT_A,&A));
     421          26 :   PetscCall(MatDenseGetSubMatrix(d->H,0,d->eps->nconv,0,d->eps->nconv,&H0));
     422          26 :   PetscCall(MatCopy(H0,A,SAME_NONZERO_PATTERN));
     423          26 :   PetscCall(MatDenseRestoreSubMatrix(d->H,&H0));
     424          26 :   PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_A,&A));
     425          26 :   if (d->G) {
     426          23 :     PetscCall(DSGetMat(d->eps->ds,DS_MAT_B,&B));
     427          23 :     PetscCall(MatDenseGetSubMatrix(d->G,0,d->eps->nconv,0,d->eps->nconv,&G0));
     428          23 :     PetscCall(MatCopy(G0,B,SAME_NONZERO_PATTERN));
     429          23 :     PetscCall(MatDenseRestoreSubMatrix(d->G,&G0));
     430          23 :     PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_B,&B));
     431             :   }
     432             :   /* Set the signature on projected matrix B */
     433          26 :   if (DVD_IS(d->sEP,DVD_EP_INDEFINITE)) {
     434           0 :     PetscCall(DSGetLeadingDimension(d->eps->ds,&ld));
     435           0 :     PetscCall(DSGetArray(d->eps->ds,DS_MAT_B,&pA));
     436           0 :     PetscCall(PetscArrayzero(pA,d->eps->nconv*ld));
     437           0 :     PetscCall(VecCreateSeq(PETSC_COMM_SELF,d->eps->nconv,&v));
     438           0 :     PetscCall(BVGetSignature(d->eps->V,v));
     439           0 :     PetscCall(VecGetArrayRead(v,&pv));
     440           0 :     for (i=0;i<d->eps->nconv;i++) pA[i+ld*i] = pv[i];
     441           0 :     PetscCall(VecRestoreArrayRead(v,&pv));
     442           0 :     PetscCall(VecDestroy(&v));
     443           0 :     PetscCall(DSRestoreArray(d->eps->ds,DS_MAT_B,&pA));
     444             :   }
     445          26 :   PetscCall(DSSetState(d->eps->ds,DS_STATE_RAW));
     446          26 :   PetscCall(DSSolve(d->eps->ds,d->eps->eigr,d->eps->eigi));
     447          26 :   PetscCall(DSSynchronize(d->eps->ds,d->eps->eigr,d->eps->eigi));
     448          26 :   if (d->W) {
     449          80 :     for (i=0;i<d->eps->nconv;i++) PetscCall(d->calcpairs_eig_backtrans(d,d->eps->eigr[i],d->eps->eigi[i],&d->eps->eigr[i],&d->eps->eigi[i]));
     450             :   }
     451          26 :   PetscFunctionReturn(PETSC_SUCCESS);
     452             : }
     453             : 
     454             : /*
     455             :    Compute the residual vectors R(i) <- (AV - BV*eigr(i))*pX(i), and also
     456             :    the norm associated to the Schur pair, where i = r_s..r_e
     457             : */
     458        2692 : static PetscErrorCode dvd_calcpairs_res_0(dvdDashboard *d,PetscInt r_s,PetscInt r_e)
     459             : {
     460        2692 :   PetscInt       i,ldpX;
     461        2692 :   PetscScalar    *pX;
     462        2692 :   BV             BX = d->BX?d->BX:d->eps->V;
     463        2692 :   Vec            *R;
     464             : 
     465        2692 :   PetscFunctionBegin;
     466        2692 :   PetscCall(DSGetLeadingDimension(d->eps->ds,&ldpX));
     467        2692 :   PetscCall(DSGetArray(d->eps->ds,DS_MAT_Q,&pX));
     468             :   /* nX(i) <- ||X(i)|| */
     469        2692 :   PetscCall(dvd_improvex_compute_X(d,r_s,r_e,NULL,pX,ldpX));
     470        2692 :   PetscCall(SlepcVecPoolGetVecs(d->auxV,r_e-r_s,&R));
     471        5384 :   for (i=r_s;i<r_e;i++) {
     472             :     /* R(i-r_s) <- AV*pX(i) */
     473        2692 :     PetscCall(BVMultVec(d->AX,1.0,0.0,R[i-r_s],&pX[ldpX*i]));
     474             :     /* R(i-r_s) <- R(i-r_s) - eigr(i)*BX*pX(i) */
     475        2692 :     PetscCall(BVMultVec(BX,-d->eigr[i],1.0,R[i-r_s],&pX[ldpX*i]));
     476             :   }
     477        2692 :   PetscCall(DSRestoreArray(d->eps->ds,DS_MAT_Q,&pX));
     478        2692 :   PetscCall(d->calcpairs_proj_res(d,r_s,r_e,R));
     479        2692 :   PetscCall(SlepcVecPoolRestoreVecs(d->auxV,r_e-r_s,&R));
     480        2692 :   PetscFunctionReturn(PETSC_SUCCESS);
     481             : }
     482             : 
     483       10801 : static PetscErrorCode dvd_calcpairs_proj_res(dvdDashboard *d,PetscInt r_s,PetscInt r_e,Vec *R)
     484             : {
     485       10801 :   PetscInt       i,l,k;
     486       10801 :   PetscBool      lindep=PETSC_FALSE;
     487       10801 :   BV             cX;
     488             : 
     489       10801 :   PetscFunctionBegin;
     490       10801 :   if (d->W) cX = d->W; /* If left subspace exists, R <- orth(cY, R), nR[i] <- ||R[i]|| */
     491        9069 :   else if (!(DVD_IS(d->sEP, DVD_EP_STD) && DVD_IS(d->sEP, DVD_EP_HERMITIAN))) cX = d->eps->V; /* If not HEP, R <- orth(cX, R), nR[i] <- ||R[i]|| */
     492             :   else cX = NULL; /* Otherwise, nR[i] <- ||R[i]|| */
     493             : 
     494        2522 :   if (cX) {
     495        2522 :     PetscCall(BVGetActiveColumns(cX,&l,&k));
     496        2522 :     PetscCall(BVSetActiveColumns(cX,0,l));
     497        5044 :     for (i=0;i<r_e-r_s;i++) PetscCall(BVOrthogonalizeVec(cX,R[i],NULL,&d->nR[r_s+i],&lindep));
     498        2522 :     PetscCall(BVSetActiveColumns(cX,l,k));
     499        2522 :     if (lindep || (PetscAbs(d->nR[r_s+i]) < PETSC_MACHINE_EPSILON)) PetscCall(PetscInfo(d->eps,"The computed eigenvector residual %" PetscInt_FMT " is too low, %g!\n",r_s+i,(double)d->nR[r_s+i]));
     500             :   } else {
     501       16558 :     for (i=0;i<r_e-r_s;i++) PetscCall(VecNormBegin(R[i],NORM_2,&d->nR[r_s+i]));
     502       16558 :     for (i=0;i<r_e-r_s;i++) PetscCall(VecNormEnd(R[i],NORM_2,&d->nR[r_s+i]));
     503             :   }
     504       10801 :   PetscFunctionReturn(PETSC_SUCCESS);
     505             : }
     506             : 
     507         291 : PetscErrorCode dvd_calcpairs_qz(dvdDashboard *d,dvdBlackboard *b,PetscBool borth,PetscBool harm)
     508             : {
     509         291 :   PetscBool      std_probl,her_probl,ind_probl;
     510         291 :   DSType         dstype;
     511         291 :   Vec            v1;
     512             : 
     513         291 :   PetscFunctionBegin;
     514         291 :   std_probl = DVD_IS(d->sEP,DVD_EP_STD)? PETSC_TRUE: PETSC_FALSE;
     515         291 :   her_probl = DVD_IS(d->sEP,DVD_EP_HERMITIAN)? PETSC_TRUE: PETSC_FALSE;
     516         291 :   ind_probl = DVD_IS(d->sEP,DVD_EP_INDEFINITE)? PETSC_TRUE: PETSC_FALSE;
     517             : 
     518             :   /* Setting configuration constrains */
     519         291 :   b->max_size_proj = PetscMax(b->max_size_proj,b->max_size_V);
     520         291 :   d->W_shift = d->B? PETSC_TRUE: PETSC_FALSE;
     521             : 
     522             :   /* Setup the step */
     523         291 :   if (b->state >= DVD_STATE_CONF) {
     524          97 :     d->max_size_P = b->max_size_P;
     525          97 :     d->max_size_proj = b->max_size_proj;
     526             :     /* Create a DS if the method works with Schur decompositions */
     527          97 :     d->calcPairs = dvd_calcpairs_proj;
     528          97 :     d->calcpairs_residual = dvd_calcpairs_res_0;
     529          97 :     d->calcpairs_proj_res = dvd_calcpairs_proj_res;
     530          97 :     d->calcpairs_selectPairs = dvd_calcpairs_selectPairs;
     531             :     /* Create and configure a DS for solving the projected problems */
     532          97 :     if (d->W) dstype = DSGNHEP;    /* If we use harmonics */
     533             :     else {
     534          97 :       if (ind_probl) dstype = DSGHIEP;
     535          97 :       else if (std_probl) dstype = her_probl? DSHEP : DSNHEP;
     536          23 :       else dstype = her_probl? DSGHEP : DSGNHEP;
     537             :     }
     538          97 :     PetscCall(DSSetType(d->eps->ds,dstype));
     539          97 :     PetscCall(DSAllocate(d->eps->ds,d->eps->ncv));
     540             :     /* Create various vector basis */
     541          97 :     if (harm) {
     542          23 :       PetscCall(BVDuplicateResize(d->eps->V,d->eps->ncv,&d->W));
     543          23 :       PetscCall(BVSetMatrix(d->W,NULL,PETSC_FALSE));
     544          74 :     } else d->W = NULL;
     545          97 :     PetscCall(BVDuplicateResize(d->eps->V,d->eps->ncv,&d->AX));
     546          97 :     PetscCall(BVSetMatrix(d->AX,NULL,PETSC_FALSE));
     547          97 :     PetscCall(BVDuplicateResize(d->eps->V,d->eps->ncv,&d->auxBV));
     548          97 :     PetscCall(BVSetMatrix(d->auxBV,NULL,PETSC_FALSE));
     549          97 :     if (d->B) {
     550          14 :       PetscCall(BVDuplicateResize(d->eps->V,d->eps->ncv,&d->BX));
     551          14 :       PetscCall(BVSetMatrix(d->BX,NULL,PETSC_FALSE));
     552          83 :     } else d->BX = NULL;
     553          97 :     PetscCall(MatCreateVecsEmpty(d->A,&v1,NULL));
     554          97 :     PetscCall(SlepcVecPoolCreate(v1,0,&d->auxV));
     555          97 :     PetscCall(VecDestroy(&v1));
     556             :     /* Create projected problem matrices */
     557          97 :     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,d->eps->ncv,d->eps->ncv,NULL,&d->H));
     558          97 :     if (!std_probl) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,d->eps->ncv,d->eps->ncv,NULL,&d->G));
     559          74 :     else d->G = NULL;
     560          97 :     if (her_probl) {
     561          71 :       PetscCall(MatSetOption(d->H,MAT_HERMITIAN,PETSC_TRUE));
     562          71 :       if (d->G) PetscCall(MatSetOption(d->G,MAT_HERMITIAN,PETSC_TRUE));
     563             :     }
     564             : 
     565          97 :     if (ind_probl) PetscCall(PetscMalloc1(d->eps->ncv,&d->nBds));
     566          97 :     else d->nBds = NULL;
     567          97 :     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,d->eps->ncv,d->eps->ncv,NULL,&d->auxM));
     568             : 
     569          97 :     PetscCall(EPSDavidsonFLAdd(&d->startList,dvd_calcpairs_qz_start));
     570          97 :     PetscCall(EPSDavidsonFLAdd(&d->endList,EPSXDComputeDSConv));
     571          97 :     PetscCall(EPSDavidsonFLAdd(&d->destroyList,dvd_calcpairs_qz_d));
     572             :   }
     573         291 :   PetscFunctionReturn(PETSC_SUCCESS);
     574             : }

Generated by: LCOV version 1.14