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-04-18 00:38:59 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        8926 : static PetscErrorCode dvd_calcpairs_projeig_solve(dvdDashboard *d)
      53             : {
      54        8926 :   Vec               v;
      55        8926 :   Mat               A,B,H0,G0;
      56        8926 :   PetscScalar       *pA;
      57        8926 :   const PetscScalar *pv;
      58        8926 :   PetscInt          i,lV,kV,n,ld;
      59             : 
      60        8926 :   PetscFunctionBegin;
      61        8926 :   PetscCall(BVGetActiveColumns(d->eps->V,&lV,&kV));
      62        8926 :   n = kV-lV;
      63        8926 :   PetscCall(DSSetDimensions(d->eps->ds,n,0,0));
      64        8926 :   PetscCall(DSGetMat(d->eps->ds,DS_MAT_A,&A));
      65        8926 :   PetscCall(MatDenseGetSubMatrix(d->H,lV,lV+n,lV,lV+n,&H0));
      66        8926 :   PetscCall(MatCopy(H0,A,SAME_NONZERO_PATTERN));
      67        8926 :   PetscCall(MatDenseRestoreSubMatrix(d->H,&H0));
      68        8926 :   PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_A,&A));
      69        8926 :   if (d->G) {
      70        1494 :     PetscCall(DSGetMat(d->eps->ds,DS_MAT_B,&B));
      71        1494 :     PetscCall(MatDenseGetSubMatrix(d->G,lV,lV+n,lV,lV+n,&G0));
      72        1494 :     PetscCall(MatCopy(G0,B,SAME_NONZERO_PATTERN));
      73        1494 :     PetscCall(MatDenseRestoreSubMatrix(d->G,&G0));
      74        1494 :     PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_B,&B));
      75             :   }
      76             :   /* Set the signature on projected matrix B */
      77        8926 :   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        8926 :   PetscCall(DSSetState(d->eps->ds,DS_STATE_RAW));
      92        8926 :   PetscCall(DSSolve(d->eps->ds,d->eigr,d->eigi));
      93        8926 :   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        1748 : static PetscErrorCode EPSXDUpdateProj(Mat Q,Mat Z,PetscInt l,Mat A,PetscInt lA,PetscInt kA,Mat aux)
     100             : {
     101        1748 :   PetscScalar       one=1.0,zero=0.0;
     102        1748 :   PetscInt          i,j,dA_=kA-lA,m0,n0,ldA_,ldQ_,ldZ_,nQ_;
     103        1748 :   PetscBLASInt      dA,nQ,ldA,ldQ,ldZ;
     104        1748 :   PetscScalar       *pA,*pW;
     105        1748 :   const PetscScalar *pQ,*pZ;
     106        1748 :   PetscBool         symm=PETSC_FALSE,set,flg;
     107             : 
     108        1748 :   PetscFunctionBegin;
     109        1748 :   PetscCall(MatGetSize(A,&m0,&n0));
     110        1748 :   PetscCall(MatDenseGetLDA(A,&ldA_));
     111        1748 :   PetscAssert(m0==n0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"A should be square");
     112        1748 :   PetscAssert(lA>=0 && lA<=m0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid initial row, column in A");
     113        1748 :   PetscAssert(kA>=0 && kA>=lA && kA<=m0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid final row, column in A");
     114        1748 :   PetscCall(MatIsHermitianKnown(A,&set,&flg));
     115        1748 :   symm = set? flg: PETSC_FALSE;
     116        1748 :   PetscCall(MatGetSize(Q,&m0,&n0)); nQ_=m0;
     117        1748 :   PetscCall(MatDenseGetLDA(Q,&ldQ_));
     118        1748 :   PetscAssert(l>=0 && l<=n0 && l+dA_<=n0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid initial column in Q");
     119        1748 :   PetscCall(MatGetSize(Z,&m0,&n0));
     120        1748 :   PetscCall(MatDenseGetLDA(Z,&ldZ_));
     121        1748 :   PetscAssert(l>=0 && l<=n0 && l+dA_<=n0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid initial column in Z");
     122        1748 :   PetscCall(MatGetSize(aux,&m0,&n0));
     123        1748 :   PetscAssert(m0*n0>=nQ_*dA_,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"aux should be larger");
     124        1748 :   PetscCall(PetscBLASIntCast(dA_,&dA));
     125        1748 :   PetscCall(PetscBLASIntCast(nQ_,&nQ));
     126        1748 :   PetscCall(PetscBLASIntCast(ldA_,&ldA));
     127        1748 :   PetscCall(PetscBLASIntCast(ldQ_,&ldQ));
     128        1748 :   PetscCall(PetscBLASIntCast(ldZ_,&ldZ));
     129        1748 :   PetscCall(MatDenseGetArray(A,&pA));
     130        1748 :   PetscCall(MatDenseGetArrayRead(Q,&pQ));
     131        1748 :   if (Q!=Z) PetscCall(MatDenseGetArrayRead(Z,&pZ));
     132        1312 :   else pZ = pQ;
     133        1748 :   PetscCall(MatDenseGetArrayWrite(aux,&pW));
     134             :   /* W = A*Q */
     135        1748 :   if (symm) {
     136             :     /* symmetrize before multiplying */
     137       16464 :     for (i=lA+1;i<lA+nQ;i++) {
     138      128161 :       for (j=lA;j<i;j++) pA[i+j*ldA] = PetscConj(pA[j+i*ldA]);
     139             :     }
     140             :   }
     141        1748 :   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        1748 :   PetscCallBLAS("BLASgemm",BLASgemm_("C","N",&dA,&dA,&nQ,&one,&pZ[ldZ*l+l],&ldZ,pW,&nQ,&zero,&pA[ldA*lA+lA],&ldA));
     144        1748 :   PetscCall(MatDenseRestoreArray(A,&pA));
     145        1748 :   PetscCall(MatDenseRestoreArrayRead(Q,&pQ));
     146        1748 :   if (Q!=Z) PetscCall(MatDenseRestoreArrayRead(Z,&pZ));
     147        1748 :   PetscCall(MatDenseRestoreArrayWrite(aux,&pW));
     148        1748 :   PetscFunctionReturn(PETSC_SUCCESS);
     149             : }
     150             : 
     151        1530 : static PetscErrorCode dvd_calcpairs_updateproj(dvdDashboard *d)
     152             : {
     153        1530 :   Mat            Q,Z;
     154        1530 :   PetscInt       lV,kV;
     155        1530 :   PetscBool      symm;
     156             : 
     157        1530 :   PetscFunctionBegin;
     158        1530 :   PetscCall(DSGetMat(d->eps->ds,DS_MAT_Q,&Q));
     159        1530 :   if (d->W) PetscCall(DSGetMat(d->eps->ds,DS_MAT_Z,&Z));
     160        1312 :   else Z = Q;
     161        1530 :   PetscCall(BVGetActiveColumns(d->eps->V,&lV,&kV));
     162        1530 :   PetscCall(EPSXDUpdateProj(Q,Z,0,d->H,lV,lV+d->V_tra_e,d->auxM));
     163        1530 :   if (d->G) PetscCall(EPSXDUpdateProj(Q,Z,0,d->G,lV,lV+d->V_tra_e,d->auxM));
     164        1530 :   PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_Q,&Q));
     165        1530 :   if (d->W) PetscCall(DSRestoreMat(d->eps->ds,DS_MAT_Z,&Z));
     166             : 
     167        1530 :   PetscCall(PetscObjectTypeCompareAny((PetscObject)d->eps->ds,&symm,DSHEP,DSGHIEP,DSGHEP,""));
     168        1530 :   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        3485 : static inline PetscErrorCode dvd_calcpairs_updateBV0_gen(dvdDashboard *d,BV bv,DSMatType mat)
     200             : {
     201        3485 :   PetscInt       l,k,n;
     202        3485 :   Mat            M,M0,auxM,auxM0;
     203             : 
     204        3485 :   PetscFunctionBegin;
     205        3485 :   PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
     206        3485 :   PetscCall(DSGetDimensions(d->eps->ds,&n,NULL,NULL,NULL));
     207        3485 :   PetscAssert(k-l==n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
     208        3485 :   PetscCall(DSGetMat(d->eps->ds,mat,&M));
     209        3485 :   PetscCall(MatDenseGetSubMatrix(M,0,n,0,d->V_tra_e,&M0));
     210        3485 :   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,k,k,NULL,&auxM));
     211        3485 :   PetscCall(MatDenseGetSubMatrix(auxM,l,l+n,l,l+d->V_tra_e,&auxM0));
     212        3485 :   PetscCall(MatCopy(M0,auxM0,SAME_NONZERO_PATTERN));
     213        3485 :   PetscCall(MatDenseRestoreSubMatrix(auxM,&auxM0));
     214        3485 :   PetscCall(MatDenseRestoreSubMatrix(M,&M0));
     215        3485 :   PetscCall(DSRestoreMat(d->eps->ds,mat,&M));
     216        3485 :   PetscCall(BVMultInPlace(bv,auxM,l,l+d->V_tra_e));
     217        3485 :   PetscCall(MatDestroy(&auxM));
     218        3485 :   PetscFunctionReturn(PETSC_SUCCESS);
     219             : }
     220             : 
     221        8926 : static PetscErrorCode dvd_calcpairs_proj(dvdDashboard *d)
     222             : {
     223        8926 :   PetscInt       i,l,k;
     224        8926 :   Vec            v1,v2;
     225        8926 :   PetscScalar    *pv;
     226             : 
     227        8926 :   PetscFunctionBegin;
     228        8926 :   PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
     229             :   /* Update AV, BV, W and the projected matrices */
     230             :   /* 1. S <- S*MT */
     231        8926 :   if (d->V_tra_s != d->V_tra_e || d->V_tra_e > 0) {
     232        1530 :     PetscCall(dvd_calcpairs_updateBV0_gen(d,d->eps->V,DS_MAT_Q));
     233        1530 :     if (d->W) PetscCall(dvd_calcpairs_updateBV0_gen(d,d->W,DS_MAT_Z));
     234        1530 :     PetscCall(dvd_calcpairs_updateBV0_gen(d,d->AX,DS_MAT_Q));
     235        1530 :     if (d->BX) PetscCall(dvd_calcpairs_updateBV0_gen(d,d->BX,DS_MAT_Q));
     236        1530 :     PetscCall(dvd_calcpairs_updateproj(d));
     237             :     /* Update signature */
     238        1530 :     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        1530 :     k = l+d->V_tra_e;
     250        1530 :     l+= d->V_tra_s;
     251             :   } else {
     252             :     /* 2. V <- orth(V, V_new) */
     253        7396 :     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        7396 :     PetscAssert(k-l==d->V_new_s,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
     257       18038 :     for (i=l+d->V_new_s;i<l+d->V_new_e;i++) {
     258       10642 :       PetscCall(BVGetColumn(d->eps->V,i,&v1));
     259       10642 :       PetscCall(BVGetColumn(d->AX,i,&v2));
     260       10642 :       PetscCall(MatMult(d->A,v1,v2));
     261       10642 :       PetscCall(BVRestoreColumn(d->eps->V,i,&v1));
     262       10642 :       PetscCall(BVRestoreColumn(d->AX,i,&v2));
     263             :     }
     264             :     /* 4. BV <- [BV B * V(V_new_s:V_new_e-1)] */
     265        7396 :     if (d->BX) {
     266             :       /* Check consistency */
     267        1326 :       PetscAssert(k-l==d->V_new_s,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
     268        2865 :       for (i=l+d->V_new_s;i<l+d->V_new_e;i++) {
     269        1539 :         PetscCall(BVGetColumn(d->eps->V,i,&v1));
     270        1539 :         PetscCall(BVGetColumn(d->BX,i,&v2));
     271        1539 :         PetscCall(MatMult(d->B,v1,v2));
     272        1539 :         PetscCall(BVRestoreColumn(d->eps->V,i,&v1));
     273        1539 :         PetscCall(BVRestoreColumn(d->BX,i,&v2));
     274             :       }
     275             :     }
     276             :     /* 5. W <- [W f(AV,BV)] */
     277        7396 :     if (d->W) {
     278        1276 :       PetscCall(d->calcpairs_W(d));
     279        1276 :       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        7396 :     PetscCall(BVSetActiveColumns(d->eps->V,l+d->V_new_s,l+d->V_new_e));
     283        7396 :     PetscCall(BVSetActiveColumns(d->AX,l+d->V_new_s,l+d->V_new_e));
     284        7396 :     if (d->BX) PetscCall(BVSetActiveColumns(d->BX,l+d->V_new_s,l+d->V_new_e));
     285        7396 :     if (d->W) PetscCall(BVSetActiveColumns(d->W,l+d->V_new_s,l+d->V_new_e));
     286        7396 :     PetscCall(BVMatProject(d->AX,NULL,d->W?d->W:d->eps->V,d->H));
     287        7396 :     if (d->G) PetscCall(BVMatProject(d->BX?d->BX:d->eps->V,NULL,d->W?d->W:d->eps->V,d->G));
     288        7396 :     PetscCall(BVSetActiveColumns(d->eps->V,l,k));
     289        7396 :     PetscCall(BVSetActiveColumns(d->AX,l,k));
     290        7396 :     if (d->BX) PetscCall(BVSetActiveColumns(d->BX,l,k));
     291        7396 :     if (d->W) PetscCall(BVSetActiveColumns(d->W,l,k));
     292             : 
     293             :     /* Perform the transformation on the projected problem */
     294        7396 :     if (d->W) PetscCall(d->calcpairs_proj_trans(d));
     295        7396 :     k = l+d->V_new_e;
     296             :   }
     297        8926 :   PetscCall(BVSetActiveColumns(d->eps->V,l,k));
     298        8926 :   PetscCall(BVSetActiveColumns(d->AX,l,k));
     299        8926 :   if (d->BX) PetscCall(BVSetActiveColumns(d->BX,l,k));
     300        8926 :   if (d->W) PetscCall(BVSetActiveColumns(d->W,l,k));
     301             : 
     302             :   /* Solve the projected problem */
     303        8926 :   PetscCall(dvd_calcpairs_projeig_solve(d));
     304             : 
     305        8926 :   d->V_tra_s = d->V_tra_e = 0;
     306        8926 :   d->V_new_s = d->V_new_e;
     307        8926 :   PetscFunctionReturn(PETSC_SUCCESS);
     308             : }
     309             : 
     310       10492 : static PetscErrorCode dvd_calcpairs_apply_arbitrary(dvdDashboard *d,PetscInt r_s,PetscInt r_e,PetscScalar *rr,PetscScalar *ri)
     311             : {
     312       10492 :   PetscInt       i,k,ld;
     313       10492 :   PetscScalar    *pX;
     314       10492 :   Vec            *X,xr,xi;
     315             : #if defined(PETSC_USE_COMPLEX)
     316       10492 :   PetscInt       N=1;
     317             : #else
     318             :   PetscInt       N=2,j;
     319             : #endif
     320             : 
     321       10492 :   PetscFunctionBegin;
     322             :   /* Quick exit without neither arbitrary selection nor harmonic extraction */
     323       10492 :   if (!d->eps->arbitrary && !d->calcpairs_eig_backtrans) PetscFunctionReturn(PETSC_SUCCESS);
     324             : 
     325             :   /* Quick exit without arbitrary selection, but with harmonic extraction */
     326        3326 :   if (d->calcpairs_eig_backtrans) {
     327       37128 :     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        3326 :   if (!d->eps->arbitrary) PetscFunctionReturn(PETSC_SUCCESS);
     330             : 
     331        1286 :   PetscCall(SlepcVecPoolGetVecs(d->auxV,N,&X));
     332        1286 :   PetscCall(DSGetLeadingDimension(d->eps->ds,&ld));
     333       16280 :   for (i=r_s;i<r_e;i++) {
     334       14994 :     k = i;
     335       14994 :     PetscCall(DSVectors(d->eps->ds,DS_MAT_X,&k,NULL));
     336       14994 :     PetscCall(DSGetArray(d->eps->ds,DS_MAT_X,&pX));
     337       14994 :     PetscCall(dvd_improvex_compute_X(d,i,k+1,X,pX,ld));
     338       14994 :     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       14994 :     xr = X[0];
     348       14994 :     xi = NULL;
     349       14994 :     if (d->nX[i] != 1.0) PetscCall(VecScale(xr,1.0/d->nX[i]));
     350             : #endif
     351       14994 :     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        1286 :   PetscCall(SlepcVecPoolRestoreVecs(d->auxV,N,&X));
     361        1286 :   PetscFunctionReturn(PETSC_SUCCESS);
     362             : }
     363             : 
     364        8829 : static PetscErrorCode dvd_calcpairs_selectPairs(dvdDashboard *d,PetscInt n)
     365             : {
     366        8829 :   PetscInt       k,lV,kV,nV;
     367        8829 :   PetscScalar    *rr,*ri;
     368             : 
     369        8829 :   PetscFunctionBegin;
     370        8829 :   PetscCall(BVGetActiveColumns(d->eps->V,&lV,&kV));
     371        8829 :   nV = kV - lV;
     372        8829 :   n = PetscMin(n,nV);
     373        8829 :   if (n <= 0) PetscFunctionReturn(PETSC_SUCCESS);
     374             :   /* Put the best n pairs at the beginning. Useful for restarting */
     375        8829 :   if (d->eps->arbitrary || d->calcpairs_eig_backtrans) {
     376        1663 :     PetscCall(PetscMalloc1(nV,&rr));
     377        1663 :     PetscCall(PetscMalloc1(nV,&ri));
     378        1663 :     PetscCall(dvd_calcpairs_apply_arbitrary(d,0,nV,rr,ri));
     379             :   } else {
     380        7166 :     rr = d->eigr;
     381        7166 :     ri = d->eigi;
     382             :   }
     383        8829 :   k = n;
     384        8829 :   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        8829 :   if (n != 1)
     390             : #endif
     391             :   {
     392        8829 :     PetscCall(dvd_calcpairs_apply_arbitrary(d,0,nV,rr,ri));
     393        8829 :     k = 1;
     394        8829 :     PetscCall(DSSort(d->eps->ds,d->eigr,d->eigi,rr,ri,&k));
     395             :   }
     396        8829 :   PetscCall(DSSynchronize(d->eps->ds,d->eigr,d->eigi));
     397             : 
     398        8829 :   if (d->calcpairs_eigs_trans) PetscCall(d->calcpairs_eigs_trans(d));
     399        8829 :   if (d->eps->arbitrary || d->calcpairs_eig_backtrans) {
     400        1663 :     PetscCall(PetscFree(rr));
     401        1663 :     PetscCall(PetscFree(ri));
     402             :   }
     403        8829 :   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) 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        2601 : static PetscErrorCode dvd_calcpairs_res_0(dvdDashboard *d,PetscInt r_s,PetscInt r_e)
     459             : {
     460        2601 :   PetscInt       i,ldpX;
     461        2601 :   PetscScalar    *pX;
     462        2601 :   BV             BX = d->BX?d->BX:d->eps->V;
     463        2601 :   Vec            *R;
     464             : 
     465        2601 :   PetscFunctionBegin;
     466        2601 :   PetscCall(DSGetLeadingDimension(d->eps->ds,&ldpX));
     467        2601 :   PetscCall(DSGetArray(d->eps->ds,DS_MAT_Q,&pX));
     468             :   /* nX(i) <- ||X(i)|| */
     469        2601 :   PetscCall(dvd_improvex_compute_X(d,r_s,r_e,NULL,pX,ldpX));
     470        2601 :   PetscCall(SlepcVecPoolGetVecs(d->auxV,r_e-r_s,&R));
     471        5202 :   for (i=r_s;i<r_e;i++) {
     472             :     /* R(i-r_s) <- AV*pX(i) */
     473        2601 :     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        2601 :     PetscCall(BVMultVec(BX,-d->eigr[i],1.0,R[i-r_s],&pX[ldpX*i]));
     476             :   }
     477        2601 :   PetscCall(DSRestoreArray(d->eps->ds,DS_MAT_Q,&pX));
     478        2601 :   PetscCall(d->calcpairs_proj_res(d,r_s,r_e,R));
     479        2601 :   PetscCall(SlepcVecPoolRestoreVecs(d->auxV,r_e-r_s,&R));
     480        2601 :   PetscFunctionReturn(PETSC_SUCCESS);
     481             : }
     482             : 
     483       10619 : static PetscErrorCode dvd_calcpairs_proj_res(dvdDashboard *d,PetscInt r_s,PetscInt r_e,Vec *R)
     484             : {
     485       10619 :   PetscInt       i,l,k;
     486       10619 :   PetscBool      lindep=PETSC_FALSE;
     487       10619 :   BV             cX;
     488             : 
     489       10619 :   PetscFunctionBegin;
     490       10619 :   if (d->W) cX = d->W; /* If left subspace exists, R <- orth(cY, R), nR[i] <- ||R[i]|| */
     491        8940 :   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       10619 :   if (cX) {
     495        2431 :     PetscCall(BVGetActiveColumns(cX,&l,&k));
     496        2431 :     PetscCall(BVSetActiveColumns(cX,0,l));
     497        4862 :     for (i=0;i<r_e-r_s;i++) PetscCall(BVOrthogonalizeVec(cX,R[i],NULL,&d->nR[r_s+i],&lindep));
     498        2431 :     PetscCall(BVSetActiveColumns(cX,l,k));
     499        2431 :     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       16376 :     for (i=0;i<r_e-r_s;i++) PetscCall(VecNormBegin(R[i],NORM_2,&d->nR[r_s+i]));
     502       16376 :     for (i=0;i<r_e-r_s;i++) PetscCall(VecNormEnd(R[i],NORM_2,&d->nR[r_s+i]));
     503             :   }
     504       10619 :   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