LCOV - code coverage report
Current view: top level - sys/classes/ds/impls/ghep - dsghep.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 124 136 91.2 %
Date: 2024-04-18 01:01:30 Functions: 8 8 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             : #include <slepc/private/dsimpl.h>
      12             : #include <slepcblaslapack.h>
      13             : 
      14          34 : static PetscErrorCode DSAllocate_GHEP(DS ds,PetscInt ld)
      15             : {
      16          34 :   PetscFunctionBegin;
      17          34 :   PetscCall(DSAllocateMat_Private(ds,DS_MAT_A));
      18          34 :   PetscCall(DSAllocateMat_Private(ds,DS_MAT_B));
      19          34 :   PetscCall(DSAllocateMat_Private(ds,DS_MAT_Q));
      20          34 :   PetscCall(PetscFree(ds->perm));
      21          34 :   PetscCall(PetscMalloc1(ld,&ds->perm));
      22          34 :   PetscFunctionReturn(PETSC_SUCCESS);
      23             : }
      24             : 
      25           1 : static PetscErrorCode DSView_GHEP(DS ds,PetscViewer viewer)
      26             : {
      27           1 :   PetscViewerFormat format;
      28             : 
      29           1 :   PetscFunctionBegin;
      30           1 :   PetscCall(PetscViewerGetFormat(viewer,&format));
      31           1 :   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
      32           0 :   PetscCall(DSViewMat(ds,viewer,DS_MAT_A));
      33           0 :   PetscCall(DSViewMat(ds,viewer,DS_MAT_B));
      34           0 :   if (ds->state>DS_STATE_INTERMEDIATE) PetscCall(DSViewMat(ds,viewer,DS_MAT_Q));
      35           0 :   if (ds->omat[DS_MAT_X]) PetscCall(DSViewMat(ds,viewer,DS_MAT_X));
      36           0 :   PetscFunctionReturn(PETSC_SUCCESS);
      37             : }
      38             : 
      39        1714 : static PetscErrorCode DSVectors_GHEP(DS ds,DSMatType mat,PetscInt *j,PetscReal *rnorm)
      40             : {
      41        1714 :   PetscScalar       *Z;
      42        1714 :   const PetscScalar *Q;
      43        1714 :   PetscInt          ld = ds->ld;
      44             : 
      45        1714 :   PetscFunctionBegin;
      46        1714 :   PetscCheck(!rnorm,PetscObjectComm((PetscObject)ds),PETSC_ERR_SUP,"Not implemented yet");
      47        1714 :   switch (mat) {
      48        1714 :     case DS_MAT_X:
      49             :     case DS_MAT_Y:
      50        1714 :       if (j) {
      51           1 :         PetscCall(MatDenseGetArray(ds->omat[mat],&Z));
      52           1 :         if (ds->state>=DS_STATE_CONDENSED) {
      53           1 :           PetscCall(MatDenseGetArrayRead(ds->omat[DS_MAT_Q],&Q));
      54           1 :           PetscCall(PetscArraycpy(Z+(*j)*ld,Q+(*j)*ld,ld));
      55           1 :           PetscCall(MatDenseRestoreArrayRead(ds->omat[DS_MAT_Q],&Q));
      56             :         } else {
      57           0 :           PetscCall(PetscArrayzero(Z+(*j)*ld,ld));
      58           0 :           Z[(*j)+(*j)*ld] = 1.0;
      59             :         }
      60           1 :         PetscCall(MatDenseRestoreArray(ds->omat[mat],&Z));
      61             :       } else {
      62        1713 :         if (ds->state>=DS_STATE_CONDENSED) PetscCall(MatCopy(ds->omat[DS_MAT_Q],ds->omat[mat],SAME_NONZERO_PATTERN));
      63           0 :         else PetscCall(DSSetIdentity(ds,mat));
      64             :       }
      65        1714 :       break;
      66           0 :     case DS_MAT_U:
      67             :     case DS_MAT_V:
      68           0 :       SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_SUP,"Not implemented yet");
      69           0 :     default:
      70           0 :       SETERRQ(PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
      71             :   }
      72        1714 :   PetscFunctionReturn(PETSC_SUCCESS);
      73             : }
      74             : 
      75        1704 : static PetscErrorCode DSSort_GHEP(DS ds,PetscScalar *wr,PetscScalar *wi,PetscScalar *rr,PetscScalar *ri,PetscInt *k)
      76             : {
      77        1704 :   PetscInt       n,l,i,*perm,ld=ds->ld;
      78        1704 :   PetscScalar    *A;
      79             : 
      80        1704 :   PetscFunctionBegin;
      81        1704 :   if (!ds->sc) PetscFunctionReturn(PETSC_SUCCESS);
      82        1704 :   n = ds->n;
      83        1704 :   l = ds->l;
      84        1704 :   PetscCall(MatDenseGetArray(ds->omat[DS_MAT_A],&A));
      85        1704 :   perm = ds->perm;
      86       17412 :   for (i=l;i<n;i++) wr[i] = A[i+i*ld];
      87        1704 :   if (rr) PetscCall(DSSortEigenvalues_Private(ds,rr,ri,perm,PETSC_FALSE));
      88        1695 :   else PetscCall(DSSortEigenvalues_Private(ds,wr,NULL,perm,PETSC_FALSE));
      89       17412 :   for (i=l;i<n;i++) A[i+i*ld] = wr[perm[i]];
      90       17412 :   for (i=l;i<n;i++) wr[i] = A[i+i*ld];
      91        1704 :   PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_A],&A));
      92        1704 :   PetscCall(DSPermuteColumns_Private(ds,l,n,n,DS_MAT_Q,perm));
      93        1704 :   PetscFunctionReturn(PETSC_SUCCESS);
      94             : }
      95             : 
      96        1704 : static PetscErrorCode DSSolve_GHEP(DS ds,PetscScalar *wr,PetscScalar *wi)
      97             : {
      98        1704 :   PetscScalar    *work,*A,*B,*Q;
      99        1704 :   PetscBLASInt   itype = 1,*iwork,info,n1,liwork,ld,lrwork=0,lwork;
     100        1704 :   PetscInt       off,i;
     101             : #if defined(PETSC_USE_COMPLEX)
     102             :   PetscReal      *rwork,*rr;
     103             : #endif
     104             : 
     105        1704 :   PetscFunctionBegin;
     106        1704 :   PetscCall(PetscBLASIntCast(ds->n-ds->l,&n1));
     107        1704 :   PetscCall(PetscBLASIntCast(ds->ld,&ld));
     108        1704 :   PetscCall(PetscBLASIntCast(5*ds->n+3,&liwork));
     109             : #if defined(PETSC_USE_COMPLEX)
     110             :   PetscCall(PetscBLASIntCast(ds->n*ds->n+2*ds->n,&lwork));
     111             :   PetscCall(PetscBLASIntCast(2*ds->n*ds->n+5*ds->n+1+n1,&lrwork));
     112             : #else
     113        1704 :   PetscCall(PetscBLASIntCast(2*ds->n*ds->n+6*ds->n+1,&lwork));
     114             : #endif
     115        1704 :   PetscCall(DSAllocateWork_Private(ds,lwork,lrwork,liwork));
     116        1704 :   work = ds->work;
     117        1704 :   iwork = ds->iwork;
     118        1704 :   off = ds->l+ds->l*ld;
     119        1704 :   PetscCall(MatDenseGetArray(ds->omat[DS_MAT_A],&A));
     120        1704 :   PetscCall(MatDenseGetArray(ds->omat[DS_MAT_B],&B));
     121        1704 :   PetscCall(MatDenseGetArray(ds->omat[DS_MAT_Q],&Q));
     122             : #if defined(PETSC_USE_COMPLEX)
     123             :   rr = ds->rwork;
     124             :   rwork = ds->rwork + n1;
     125             :   lrwork = ds->lrwork - n1;
     126             :   PetscCallBLAS("LAPACKsygvd",LAPACKsygvd_(&itype,"V","U",&n1,A+off,&ld,B+off,&ld,rr,work,&lwork,rwork,&lrwork,iwork,&liwork,&info));
     127             :   for (i=0;i<n1;i++) wr[ds->l+i] = rr[i];
     128             : #else
     129        1704 :   PetscCallBLAS("LAPACKsygvd",LAPACKsygvd_(&itype,"V","U",&n1,A+off,&ld,B+off,&ld,wr+ds->l,work,&lwork,iwork,&liwork,&info));
     130             : #endif
     131        1704 :   SlepcCheckLapackInfo("sygvd",info);
     132        1704 :   PetscCall(PetscArrayzero(Q+ds->l*ld,n1*ld));
     133       17412 :   for (i=ds->l;i<ds->n;i++) PetscCall(PetscArraycpy(Q+ds->l+i*ld,A+ds->l+i*ld,n1));
     134        1704 :   PetscCall(PetscArrayzero(B+ds->l*ld,n1*ld));
     135        1704 :   PetscCall(PetscArrayzero(A+ds->l*ld,n1*ld));
     136       17412 :   for (i=ds->l;i<ds->n;i++) {
     137       15708 :     if (wi) wi[i] = 0.0;
     138       15708 :     B[i+i*ld] = 1.0;
     139       15708 :     A[i+i*ld] = wr[i];
     140             :   }
     141        1704 :   PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_A],&A));
     142        1704 :   PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_B],&B));
     143        1704 :   PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_Q],&Q));
     144        1704 :   PetscFunctionReturn(PETSC_SUCCESS);
     145             : }
     146             : 
     147             : #if !defined(PETSC_HAVE_MPIUNI)
     148          72 : static PetscErrorCode DSSynchronize_GHEP(DS ds,PetscScalar eigr[],PetscScalar eigi[])
     149             : {
     150          72 :   PetscScalar    *A,*B,*Q;
     151          72 :   PetscInt       ld=ds->ld,l=ds->l,k;
     152          72 :   PetscMPIInt    n,rank,off=0,size,ldn;
     153             : 
     154          72 :   PetscFunctionBegin;
     155          72 :   k = 2*(ds->n-l)*ld;
     156          72 :   if (ds->state>DS_STATE_RAW) k += (ds->n-l)*ld;
     157          72 :   if (eigr) k += (ds->n-l);
     158          72 :   PetscCall(DSAllocateWork_Private(ds,k,0,0));
     159          72 :   PetscCall(PetscMPIIntCast(k*sizeof(PetscScalar),&size));
     160          72 :   PetscCall(PetscMPIIntCast(ds->n-l,&n));
     161          72 :   PetscCall(PetscMPIIntCast(ld*(ds->n-l),&ldn));
     162          72 :   PetscCall(MatDenseGetArray(ds->omat[DS_MAT_A],&A));
     163          72 :   PetscCall(MatDenseGetArray(ds->omat[DS_MAT_B],&B));
     164          72 :   if (ds->state>DS_STATE_RAW) PetscCall(MatDenseGetArray(ds->omat[DS_MAT_Q],&Q));
     165          72 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ds),&rank));
     166          72 :   if (!rank) {
     167          36 :     PetscCallMPI(MPI_Pack(A+l*ld,ldn,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
     168          36 :     PetscCallMPI(MPI_Pack(B+l*ld,ldn,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
     169          36 :     if (ds->state>DS_STATE_RAW) PetscCallMPI(MPI_Pack(Q+l*ld,ldn,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
     170          36 :     if (eigr) PetscCallMPI(MPI_Pack(eigr+l,n,MPIU_SCALAR,ds->work,size,&off,PetscObjectComm((PetscObject)ds)));
     171             :   }
     172         144 :   PetscCallMPI(MPI_Bcast(ds->work,size,MPI_BYTE,0,PetscObjectComm((PetscObject)ds)));
     173          72 :   if (rank) {
     174          36 :     PetscCallMPI(MPI_Unpack(ds->work,size,&off,A+l*ld,ldn,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
     175          36 :     PetscCallMPI(MPI_Unpack(ds->work,size,&off,B+l*ld,ldn,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
     176          36 :     if (ds->state>DS_STATE_RAW) PetscCallMPI(MPI_Unpack(ds->work,size,&off,Q+l*ld,ldn,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
     177          36 :     if (eigr) PetscCallMPI(MPI_Unpack(ds->work,size,&off,eigr+l,n,MPIU_SCALAR,PetscObjectComm((PetscObject)ds)));
     178             :   }
     179          72 :   PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_A],&A));
     180          72 :   PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_B],&B));
     181          72 :   if (ds->state>DS_STATE_RAW) PetscCall(MatDenseRestoreArray(ds->omat[DS_MAT_Q],&Q));
     182          72 :   PetscFunctionReturn(PETSC_SUCCESS);
     183             : }
     184             : #endif
     185             : 
     186        5082 : static PetscErrorCode DSHermitian_GHEP(DS ds,DSMatType m,PetscBool *flg)
     187             : {
     188        5082 :   PetscFunctionBegin;
     189        5082 :   if (m==DS_MAT_A || m==DS_MAT_B) *flg = PETSC_TRUE;
     190        1711 :   else *flg = PETSC_FALSE;
     191        5082 :   PetscFunctionReturn(PETSC_SUCCESS);
     192             : }
     193             : 
     194             : /*MC
     195             :    DSGHEP - Dense Generalized Hermitian Eigenvalue Problem.
     196             : 
     197             :    Level: beginner
     198             : 
     199             :    Notes:
     200             :    The problem is expressed as A*X = B*X*Lambda, where both A and B are
     201             :    real symmetric (or complex Hermitian) and B is positive-definite. Lambda
     202             :    is a diagonal matrix whose diagonal elements are the arguments of DSSolve().
     203             :    After solve, A is overwritten with Lambda, and B is overwritten with I.
     204             : 
     205             :    No intermediate state is implemented, nor compact storage.
     206             : 
     207             :    Used DS matrices:
     208             : +  DS_MAT_A - first problem matrix
     209             : .  DS_MAT_B - second problem matrix
     210             : -  DS_MAT_Q - matrix of B-orthogonal eigenvectors, which is equal to X
     211             : 
     212             :    Implemented methods:
     213             : .  0 - Divide and Conquer (_sygvd)
     214             : 
     215             : .seealso: DSCreate(), DSSetType(), DSType
     216             : M*/
     217          34 : SLEPC_EXTERN PetscErrorCode DSCreate_GHEP(DS ds)
     218             : {
     219          34 :   PetscFunctionBegin;
     220          34 :   ds->ops->allocate      = DSAllocate_GHEP;
     221          34 :   ds->ops->view          = DSView_GHEP;
     222          34 :   ds->ops->vectors       = DSVectors_GHEP;
     223          34 :   ds->ops->solve[0]      = DSSolve_GHEP;
     224          34 :   ds->ops->sort          = DSSort_GHEP;
     225             : #if !defined(PETSC_HAVE_MPIUNI)
     226          34 :   ds->ops->synchronize   = DSSynchronize_GHEP;
     227             : #endif
     228          34 :   ds->ops->hermitian     = DSHermitian_GHEP;
     229          34 :   PetscFunctionReturn(PETSC_SUCCESS);
     230             : }

Generated by: LCOV version 1.14