1c4762a1bSJed Brown static char help[] = "Test LAPACK routine DSYEV() or DSYEVX(). \n\ 2c4762a1bSJed Brown Reads PETSc matrix A \n\ 3c4762a1bSJed Brown then computes selected eigenvalues, and optionally, eigenvectors of \n\ 4c4762a1bSJed Brown a real generalized symmetric-definite eigenproblem \n\ 5c4762a1bSJed Brown A*x = lambda*x \n\ 6c4762a1bSJed Brown Input parameters include\n\ 7c4762a1bSJed Brown -f <input_file> : file to load\n\ 8c4762a1bSJed Brown e.g. ./ex116 -f $DATAFILESPATH/matrices/small \n\n"; 9c4762a1bSJed Brown 10c4762a1bSJed Brown #include <petscmat.h> 11c4762a1bSJed Brown #include <petscblaslapack.h> 12c4762a1bSJed Brown 13c4762a1bSJed Brown extern PetscErrorCode CkEigenSolutions(PetscInt,Mat,PetscInt,PetscInt,PetscReal*,Vec*,PetscReal*); 14c4762a1bSJed Brown 15c4762a1bSJed Brown int main(int argc,char **args) 16c4762a1bSJed Brown { 17c4762a1bSJed Brown Mat A,A_dense; 18c4762a1bSJed Brown Vec *evecs; 19c4762a1bSJed Brown PetscViewer fd; /* viewer */ 20c4762a1bSJed Brown char file[1][PETSC_MAX_PATH_LEN]; /* input file name */ 21c4762a1bSJed Brown PetscBool flg,TestSYEVX=PETSC_TRUE; 22c4762a1bSJed Brown PetscErrorCode ierr; 23c4762a1bSJed Brown PetscBool isSymmetric; 24c4762a1bSJed Brown PetscScalar *arrayA,*evecs_array,*work,*evals; 25c4762a1bSJed Brown PetscMPIInt size; 26c4762a1bSJed Brown PetscInt m,n,i,cklvl=2; 27c4762a1bSJed Brown PetscBLASInt nevs,il,iu,in; 28c4762a1bSJed Brown PetscReal vl,vu,abstol=1.e-8; 29c4762a1bSJed Brown PetscBLASInt *iwork,*ifail,lwork,lierr,bn; 30c4762a1bSJed Brown PetscReal tols[2]; 31c4762a1bSJed Brown 32c4762a1bSJed Brown ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; 335f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 342c71b3e2SJacob Faibussowitsch PetscCheckFalse(size != 1,PETSC_COMM_WORLD,PETSC_ERR_SUP,"This is a uniprocessor example only!"); 35c4762a1bSJed Brown 365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL,NULL, "-test_syev", &flg)); 37c4762a1bSJed Brown if (flg) { 38c4762a1bSJed Brown TestSYEVX = PETSC_FALSE; 39c4762a1bSJed Brown } 40c4762a1bSJed Brown 41c4762a1bSJed Brown /* Determine files from which we read the two matrices */ 425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetString(NULL,NULL,"-f",file[0],sizeof(file[0]),&flg)); 43c4762a1bSJed Brown 44c4762a1bSJed Brown /* Load matrix A */ 455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[0],FILE_MODE_READ,&fd)); 465f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_WORLD,&A)); 475f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(A,MATSEQAIJ)); 485f80ce2aSJacob Faibussowitsch CHKERRQ(MatLoad(A,fd)); 495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&fd)); 505f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A,&m,&n)); 51c4762a1bSJed Brown 52c4762a1bSJed Brown /* Check whether A is symmetric */ 535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL,NULL, "-check_symmetry", &flg)); 54c4762a1bSJed Brown if (flg) { 55c4762a1bSJed Brown Mat Trans; 565f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(A,MAT_INITIAL_MATRIX, &Trans)); 575f80ce2aSJacob Faibussowitsch CHKERRQ(MatEqual(A, Trans, &isSymmetric)); 58*28b400f6SJacob Faibussowitsch PetscCheck(isSymmetric,PETSC_COMM_SELF,PETSC_ERR_USER,"A must be symmetric"); 595f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Trans)); 60c4762a1bSJed Brown } 61c4762a1bSJed Brown 62c4762a1bSJed Brown /* Solve eigenvalue problem: A_dense*x = lambda*B*x */ 63c4762a1bSJed Brown /*==================================================*/ 64c4762a1bSJed Brown /* Convert aij matrix to MatSeqDense for LAPACK */ 655f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A,MATSEQDENSE,MAT_INITIAL_MATRIX,&A_dense)); 66c4762a1bSJed Brown 675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(8*n,&lwork)); 685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(n,&bn)); 695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&evals)); 705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lwork,&work)); 715f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(A_dense,&arrayA)); 72c4762a1bSJed Brown 73c4762a1bSJed Brown if (!TestSYEVX) { /* test syev() */ 745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," LAPACKsyev: compute all %" PetscInt_FMT " eigensolutions...\n",m)); 75c4762a1bSJed Brown LAPACKsyev_("V","U",&bn,arrayA,&bn,evals,work,&lwork,&lierr); 76c4762a1bSJed Brown evecs_array = arrayA; 775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(m,&nevs)); 78c4762a1bSJed Brown il = 1; 795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(m,&iu)); 80c4762a1bSJed Brown } else { /* test syevx() */ 81c4762a1bSJed Brown il = 1; 825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(0.2*m,&iu)); 835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(n,&in)); 845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," LAPACKsyevx: compute %" PetscBLASInt_FMT " to %" PetscBLASInt_FMT "-th eigensolutions...\n",il,iu)); 855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(m*n+1,&evecs_array)); 865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(6*n+1,&iwork)); 87c4762a1bSJed Brown ifail = iwork + 5*n; 88c4762a1bSJed Brown 89c4762a1bSJed Brown /* in the case "I", vl and vu are not referenced */ 90c4762a1bSJed Brown vl = 0.0; vu = 8.0; 91c4762a1bSJed Brown LAPACKsyevx_("V","I","U",&bn,arrayA,&bn,&vl,&vu,&il,&iu,&abstol,&nevs,evals,evecs_array,&in,work,&lwork,iwork,ifail,&lierr); 925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(iwork)); 93c4762a1bSJed Brown } 945f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(A_dense,&arrayA)); 952c71b3e2SJacob Faibussowitsch PetscCheckFalse(nevs <= 0,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED, "nev=%" PetscBLASInt_FMT ", no eigensolution has found", nevs); 96c4762a1bSJed Brown 97c4762a1bSJed Brown /* View eigenvalues */ 985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL,NULL, "-eig_view", &flg)); 99c4762a1bSJed Brown if (flg) { 1005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," %" PetscBLASInt_FMT " evals: \n",nevs)); 1015f80ce2aSJacob Faibussowitsch for (i=0; i<nevs; i++) CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"%" PetscInt_FMT " %g\n",(PetscInt)(i+il),(double)evals[i])); 102c4762a1bSJed Brown } 103c4762a1bSJed Brown 104c4762a1bSJed Brown /* Check residuals and orthogonality */ 1055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nevs+1,&evecs)); 106c4762a1bSJed Brown for (i=0; i<nevs; i++) { 1075f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF,&evecs[i])); 1085f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(evecs[i],PETSC_DECIDE,n)); 1095f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetFromOptions(evecs[i])); 1105f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(evecs[i],evecs_array+i*n)); 111c4762a1bSJed Brown } 112c4762a1bSJed Brown 113c4762a1bSJed Brown tols[0] = tols[1] = PETSC_SQRT_MACHINE_EPSILON; 1145f80ce2aSJacob Faibussowitsch CHKERRQ(CkEigenSolutions(cklvl,A,il-1,iu-1,evals,evecs,tols)); 115c4762a1bSJed Brown 116c4762a1bSJed Brown /* Free work space. */ 1175f80ce2aSJacob Faibussowitsch for (i=0; i<nevs; i++) CHKERRQ(VecDestroy(&evecs[i])); 1185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(evecs)); 1195f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_dense)); 1205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(work)); 1215f80ce2aSJacob Faibussowitsch if (TestSYEVX) CHKERRQ(PetscFree(evecs_array)); 122c4762a1bSJed Brown 123c4762a1bSJed Brown /* Compute SVD: A_dense = U*SIGMA*transpose(V), 124c4762a1bSJed Brown JOBU=JOBV='S': the first min(m,n) columns of U and V are returned in the arrayU and arrayV; */ 125c4762a1bSJed Brown /*==============================================================================================*/ 126c4762a1bSJed Brown { 127c4762a1bSJed Brown /* Convert aij matrix to MatSeqDense for LAPACK */ 128c4762a1bSJed Brown PetscScalar *arrayU,*arrayVT,*arrayErr,alpha=1.0,beta=-1.0; 129c4762a1bSJed Brown Mat Err; 130c4762a1bSJed Brown PetscBLASInt minMN,maxMN,im,in; 131c4762a1bSJed Brown PetscInt j; 132c4762a1bSJed Brown PetscReal norm; 133c4762a1bSJed Brown 1345f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A,MATSEQDENSE,MAT_INITIAL_MATRIX,&A_dense)); 135c4762a1bSJed Brown 136c4762a1bSJed Brown minMN = PetscMin(m,n); 137c4762a1bSJed Brown maxMN = PetscMax(m,n); 138c4762a1bSJed Brown lwork = 5*minMN + maxMN; 1395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(m*minMN,&arrayU,m*minMN,&arrayVT,m*minMN,&arrayErr,lwork,&work)); 140c4762a1bSJed Brown 141c4762a1bSJed Brown /* Create matrix Err for checking error */ 1425f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_WORLD,&Err)); 1435f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(Err,PETSC_DECIDE,PETSC_DECIDE,m,minMN)); 1445f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(Err,MATSEQDENSE)); 1455f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqDenseSetPreallocation(Err,(PetscScalar*)arrayErr)); 146c4762a1bSJed Brown 147c4762a1bSJed Brown /* Save A to arrayErr for checking accuracy later. arrayA will be destroyed by LAPACKgesvd_() */ 1485f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(A_dense,&arrayA)); 1495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(arrayErr,arrayA,m*minMN)); 150c4762a1bSJed Brown 1515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(m,&im)); 1525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(n,&in)); 153c4762a1bSJed Brown /* Compute A = U*SIGMA*VT */ 154c4762a1bSJed Brown LAPACKgesvd_("S","S",&im,&in,arrayA,&im,evals,arrayU,&minMN,arrayVT,&minMN,work,&lwork,&lierr); 1555f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(A_dense,&arrayA)); 156c4762a1bSJed Brown if (!lierr) { 1575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," 1st 10 of %" PetscBLASInt_FMT " singular values: \n",minMN)); 1585f80ce2aSJacob Faibussowitsch for (i=0; i<10; i++) CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"%" PetscInt_FMT " %g\n",i,(double)evals[i])); 159c4762a1bSJed Brown } else { 1605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"LAPACKgesvd_ fails!")); 161c4762a1bSJed Brown } 162c4762a1bSJed Brown 163c4762a1bSJed Brown /* Check Err = (U*Sigma*V^T - A) using BLASgemm() */ 164c4762a1bSJed Brown /* U = U*Sigma */ 165c4762a1bSJed Brown for (j=0; j<minMN; j++) { /* U[:,j] = sigma[j]*U[:,j] */ 166c4762a1bSJed Brown for (i=0; i<m; i++) arrayU[j*m+i] *= evals[j]; 167c4762a1bSJed Brown } 168c4762a1bSJed Brown /* Err = U*VT - A = alpha*U*VT + beta*Err */ 169c4762a1bSJed Brown BLASgemm_("N","N",&im,&minMN,&minMN,&alpha,arrayU,&im,arrayVT,&minMN,&beta,arrayErr,&im); 1705f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(Err,NORM_FROBENIUS,&norm)); 1715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," || U*Sigma*VT - A || = %g\n",(double)norm)); 172c4762a1bSJed Brown 1735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(arrayU,arrayVT,arrayErr,work)); 1745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(evals)); 1755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_dense)); 1765f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Err)); 177c4762a1bSJed Brown } 178c4762a1bSJed Brown 1795f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 180c4762a1bSJed Brown ierr = PetscFinalize(); 181c4762a1bSJed Brown return ierr; 182c4762a1bSJed Brown } 183c4762a1bSJed Brown /*------------------------------------------------ 184c4762a1bSJed Brown Check the accuracy of the eigen solution 185c4762a1bSJed Brown ----------------------------------------------- */ 186c4762a1bSJed Brown /* 187c4762a1bSJed Brown input: 188c4762a1bSJed Brown cklvl - check level: 189c4762a1bSJed Brown 1: check residual 190c4762a1bSJed Brown 2: 1 and check B-orthogonality locally 191c4762a1bSJed Brown A - matrix 192c4762a1bSJed Brown il,iu - lower and upper index bound of eigenvalues 193c4762a1bSJed Brown eval, evec - eigenvalues and eigenvectors stored in this process 194c4762a1bSJed Brown tols[0] - reporting tol_res: || A * evec[i] - eval[i]*evec[i] || 195c4762a1bSJed Brown tols[1] - reporting tol_orth: evec[i]^T*evec[j] - delta_ij 196c4762a1bSJed Brown */ 197c4762a1bSJed Brown PetscErrorCode CkEigenSolutions(PetscInt cklvl,Mat A,PetscInt il,PetscInt iu,PetscReal *eval,Vec *evec,PetscReal *tols) 198c4762a1bSJed Brown { 1995f80ce2aSJacob Faibussowitsch PetscInt i,j,nev; 200c4762a1bSJed Brown Vec vt1,vt2; /* tmp vectors */ 201c4762a1bSJed Brown PetscReal norm,tmp,dot,norm_max,dot_max; 202c4762a1bSJed Brown 203c4762a1bSJed Brown PetscFunctionBegin; 204c4762a1bSJed Brown nev = iu - il; 205c4762a1bSJed Brown if (nev <= 0) PetscFunctionReturn(0); 206c4762a1bSJed Brown 207c4762a1bSJed Brown /*ierr = VecView(evec[0],PETSC_VIEWER_STDOUT_WORLD);*/ 2085f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(evec[0],&vt1)); 2095f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(evec[0],&vt2)); 210c4762a1bSJed Brown 211c4762a1bSJed Brown switch (cklvl) { 212c4762a1bSJed Brown case 2: 213c4762a1bSJed Brown dot_max = 0.0; 214c4762a1bSJed Brown for (i = il; i<iu; i++) { 2155f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(evec[i], vt1)); 216c4762a1bSJed Brown for (j=il; j<iu; j++) { 2175f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(evec[j],vt1,&dot)); 218c4762a1bSJed Brown if (j == i) { 219c4762a1bSJed Brown dot = PetscAbsScalar(dot - 1); 220c4762a1bSJed Brown } else { 221c4762a1bSJed Brown dot = PetscAbsScalar(dot); 222c4762a1bSJed Brown } 223c4762a1bSJed Brown if (dot > dot_max) dot_max = dot; 224c4762a1bSJed Brown if (dot > tols[1]) { 2255f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(evec[i],NORM_INFINITY,&norm)); 2265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"|delta(%" PetscInt_FMT ",%" PetscInt_FMT ")|: %g, norm: %g\n",i,j,(double)dot,(double)norm)); 227c4762a1bSJed Brown } 228c4762a1bSJed Brown } 229c4762a1bSJed Brown } 2305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," max|(x_j^T*x_i) - delta_ji|: %g\n",(double)dot_max)); 231c4762a1bSJed Brown 232c4762a1bSJed Brown case 1: 233c4762a1bSJed Brown norm_max = 0.0; 234c4762a1bSJed Brown for (i = il; i< iu; i++) { 2355f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A, evec[i], vt1)); 2365f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(evec[i], vt2)); 237c4762a1bSJed Brown tmp = -eval[i]; 2385f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(vt1,tmp,vt2)); 2395f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(vt1, NORM_INFINITY, &norm)); 240c4762a1bSJed Brown norm = PetscAbsScalar(norm); 241c4762a1bSJed Brown if (norm > norm_max) norm_max = norm; 242c4762a1bSJed Brown /* sniff, and bark if necessary */ 243c4762a1bSJed Brown if (norm > tols[0]) { 2445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," residual violation: %" PetscInt_FMT ", resi: %g\n",i, (double)norm)); 245c4762a1bSJed Brown } 246c4762a1bSJed Brown } 2475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," max_resi: %g\n", (double)norm_max)); 248c4762a1bSJed Brown break; 249c4762a1bSJed Brown default: 2505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"Error: cklvl=%" PetscInt_FMT " is not supported \n",cklvl)); 251c4762a1bSJed Brown } 2525f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vt2)); 2535f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vt1)); 254c4762a1bSJed Brown PetscFunctionReturn(0); 255c4762a1bSJed Brown } 256c4762a1bSJed Brown 257c4762a1bSJed Brown /*TEST 258c4762a1bSJed Brown 259c4762a1bSJed Brown build: 260c4762a1bSJed Brown requires: !complex 261c4762a1bSJed Brown 262c4762a1bSJed Brown test: 263dfd57a17SPierre Jolivet requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES) 264c4762a1bSJed Brown args: -f ${DATAFILESPATH}/matrices/small 265c4762a1bSJed Brown output_file: output/ex116_1.out 266c4762a1bSJed Brown 267c4762a1bSJed Brown test: 268c4762a1bSJed Brown suffix: 2 269dfd57a17SPierre Jolivet requires: datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES) 270c4762a1bSJed Brown args: -f ${DATAFILESPATH}/matrices/small -test_syev -check_symmetry 271c4762a1bSJed Brown 272c4762a1bSJed Brown TEST*/ 273