LCOV - code coverage report
Current view: top level - sys/classes/bv/tests - test11.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 130 140 92.9 %
Date: 2024-05-02 00:43:15 Functions: 2 2 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             : static char help[] = "Test BV block orthogonalization.\n\n";
      12             : 
      13             : #include <slepcbv.h>
      14             : 
      15             : /*
      16             :    Compute the Frobenius norm ||A(l:k,l:k)-diag||_F
      17             :  */
      18         504 : PetscErrorCode MyMatNorm(Mat A,PetscInt lda,PetscInt l,PetscInt k,PetscScalar diag,PetscReal *norm)
      19             : {
      20         504 :   PetscInt          i,j;
      21         504 :   const PetscScalar *pA;
      22         504 :   PetscReal         s,val;
      23             : 
      24         504 :   PetscFunctionBeginUser;
      25         504 :   PetscCall(MatDenseGetArrayRead(A,&pA));
      26             :   s = 0.0;
      27        3252 :   for (i=l;i<k;i++) {
      28       20736 :     for (j=l;j<k;j++) {
      29       17988 :       val = (i==j)? PetscAbsScalar(pA[i+j*lda]-diag): PetscAbsScalar(pA[i+j*lda]);
      30       17988 :       s += val*val;
      31             :     }
      32             :   }
      33         504 :   *norm = PetscSqrtReal(s);
      34         504 :   PetscCall(MatDenseRestoreArrayRead(A,&pA));
      35         504 :   PetscFunctionReturn(PETSC_SUCCESS);
      36             : }
      37             : 
      38         192 : int main(int argc,char **argv)
      39             : {
      40         192 :   BV             X,Y,Z,cached;
      41         192 :   Mat            B=NULL,M,R=NULL;
      42         192 :   Vec            v,t;
      43         192 :   PetscInt       i,j,n=20,l=2,k=8,Istart,Iend;
      44         192 :   PetscViewer    view;
      45         192 :   PetscBool      withb,resid,rand,verbose;
      46         192 :   PetscReal      norm;
      47         192 :   PetscScalar    alpha;
      48             : 
      49         192 :   PetscFunctionBeginUser;
      50         192 :   PetscCall(SlepcInitialize(&argc,&argv,(char*)0,help));
      51         192 :   PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL));
      52         192 :   PetscCall(PetscOptionsGetInt(NULL,NULL,"-l",&l,NULL));
      53         192 :   PetscCall(PetscOptionsGetInt(NULL,NULL,"-k",&k,NULL));
      54         192 :   PetscCall(PetscOptionsHasName(NULL,NULL,"-withb",&withb));
      55         192 :   PetscCall(PetscOptionsHasName(NULL,NULL,"-resid",&resid));
      56         192 :   PetscCall(PetscOptionsHasName(NULL,NULL,"-rand",&rand));
      57         192 :   PetscCall(PetscOptionsHasName(NULL,NULL,"-verbose",&verbose));
      58         336 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Test BV block orthogonalization (length %" PetscInt_FMT ", l=%" PetscInt_FMT ", k=%" PetscInt_FMT ")%s.\n",n,l,k,withb?" with non-standard inner product":""));
      59             : 
      60             :   /* Create template vector */
      61         192 :   PetscCall(VecCreate(PETSC_COMM_WORLD,&t));
      62         192 :   PetscCall(VecSetSizes(t,PETSC_DECIDE,n));
      63         192 :   PetscCall(VecSetFromOptions(t));
      64             : 
      65             :   /* Create BV object X */
      66         192 :   PetscCall(BVCreate(PETSC_COMM_WORLD,&X));
      67         192 :   PetscCall(PetscObjectSetName((PetscObject)X,"X"));
      68         192 :   PetscCall(BVSetSizesFromVec(X,t,k));
      69         192 :   PetscCall(BVSetFromOptions(X));
      70             : 
      71             :   /* Set up viewer */
      72         192 :   PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&view));
      73         192 :   if (verbose) PetscCall(PetscViewerPushFormat(view,PETSC_VIEWER_ASCII_MATLAB));
      74             : 
      75             :   /* Fill X entries */
      76         192 :   if (rand) PetscCall(BVSetRandom(X));
      77             :   else {
      78        1692 :     for (j=0;j<k;j++) {
      79        1500 :       PetscCall(BVGetColumn(X,j,&v));
      80        1500 :       PetscCall(VecSet(v,0.0));
      81       38160 :       for (i=0;i<=n/2;i++) {
      82       36660 :         if (i+j<n) {
      83       36660 :           alpha = (3.0*i+j-2)/(2*(i+j+1));
      84       36660 :           PetscCall(VecSetValue(v,i+j,alpha,INSERT_VALUES));
      85             :         }
      86             :       }
      87        1500 :       PetscCall(VecAssemblyBegin(v));
      88        1500 :       PetscCall(VecAssemblyEnd(v));
      89        1500 :       PetscCall(BVRestoreColumn(X,j,&v));
      90             :     }
      91             :   }
      92         192 :   if (verbose) PetscCall(BVView(X,view));
      93             : 
      94         192 :   if (withb) {
      95             :     /* Create inner product matrix */
      96          48 :     PetscCall(MatCreate(PETSC_COMM_WORLD,&B));
      97          48 :     PetscCall(MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,n,n));
      98          48 :     PetscCall(MatSetFromOptions(B));
      99          48 :     PetscCall(PetscObjectSetName((PetscObject)B,"B"));
     100             : 
     101          48 :     PetscCall(MatGetOwnershipRange(B,&Istart,&Iend));
     102         528 :     for (i=Istart;i<Iend;i++) {
     103         480 :       if (i>0) PetscCall(MatSetValue(B,i,i-1,-1.0,INSERT_VALUES));
     104         480 :       if (i<n-1) PetscCall(MatSetValue(B,i,i+1,-1.0,INSERT_VALUES));
     105         480 :       PetscCall(MatSetValue(B,i,i,2.0,INSERT_VALUES));
     106             :     }
     107          48 :     PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
     108          48 :     PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
     109          48 :     if (verbose) PetscCall(MatView(B,view));
     110          48 :     PetscCall(BVSetMatrix(X,B,PETSC_FALSE));
     111             :   }
     112             : 
     113             :   /* Create copy on Y */
     114         192 :   PetscCall(BVDuplicate(X,&Y));
     115         192 :   PetscCall(PetscObjectSetName((PetscObject)Y,"Y"));
     116         192 :   PetscCall(BVCopy(X,Y));
     117         192 :   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,k,k,NULL,&M));
     118             : 
     119         192 :   if (resid) {
     120             :     /* Create matrix R to store triangular factor */
     121         100 :     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,k,k,NULL,&R));
     122         100 :     PetscCall(PetscObjectSetName((PetscObject)R,"R"));
     123             :   }
     124             : 
     125         192 :   if (l>0) {
     126             :     /* First orthogonalize leading columns */
     127         156 :     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Orthogonalizing leading columns\n"));
     128         156 :     PetscCall(BVSetActiveColumns(Y,0,l));
     129         156 :     PetscCall(BVSetActiveColumns(X,0,l));
     130         156 :     PetscCall(BVOrthogonalize(Y,R));
     131         156 :     if (verbose) {
     132           0 :       PetscCall(BVView(Y,view));
     133           0 :       if (resid) PetscCall(MatView(R,view));
     134             :     }
     135             : 
     136         156 :     if (withb) {
     137             :       /* Extract cached BV and check it is equal to B*X */
     138          48 :       PetscCall(BVGetCachedBV(Y,&cached));
     139          48 :       PetscCall(BVDuplicate(X,&Z));
     140          48 :       PetscCall(BVSetMatrix(Z,NULL,PETSC_FALSE));
     141          48 :       PetscCall(BVSetActiveColumns(Z,0,l));
     142          48 :       PetscCall(BVCopy(X,Z));
     143          48 :       PetscCall(BVMatMult(X,B,Z));
     144          48 :       PetscCall(BVMult(Z,-1.0,1.0,cached,NULL));
     145          48 :       PetscCall(BVNorm(Z,NORM_FROBENIUS,&norm));
     146          48 :       if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Difference ||cached-BX|| < 100*eps\n"));
     147           0 :       else PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Difference ||cached-BX||: %g\n",(double)norm));
     148          48 :       PetscCall(BVDestroy(&Z));
     149             :     }
     150             : 
     151             :     /* Check orthogonality */
     152         156 :     PetscCall(BVDot(Y,Y,M));
     153         156 :     PetscCall(MyMatNorm(M,k,0,l,1.0,&norm));
     154         156 :     if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Level of orthogonality of Q1 < 100*eps\n"));
     155           0 :     else PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Level of orthogonality of Q1: %g\n",(double)norm));
     156             : 
     157         156 :     if (resid) {
     158             :       /* Check residual */
     159          64 :       PetscCall(BVDuplicate(X,&Z));
     160          64 :       PetscCall(BVSetMatrix(Z,NULL,PETSC_FALSE));
     161          64 :       PetscCall(BVSetActiveColumns(Z,0,l));
     162          64 :       PetscCall(BVCopy(X,Z));
     163          64 :       PetscCall(BVMult(Z,-1.0,1.0,Y,R));
     164          64 :       PetscCall(BVNorm(Z,NORM_FROBENIUS,&norm));
     165          64 :       if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Residual ||X1-Q1*R11|| < 100*eps\n"));
     166           0 :       else PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Residual ||X1-Q1*R11||: %g\n",(double)norm));
     167          64 :       PetscCall(BVDestroy(&Z));
     168             :     }
     169             : 
     170             :   }
     171             : 
     172             :   /* Now orthogonalize the rest of columns */
     173         192 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Orthogonalizing active columns\n"));
     174         192 :   PetscCall(BVSetActiveColumns(Y,l,k));
     175         192 :   PetscCall(BVSetActiveColumns(X,l,k));
     176         192 :   PetscCall(BVOrthogonalize(Y,R));
     177         192 :   if (verbose) {
     178           0 :     PetscCall(BVView(Y,view));
     179           0 :     if (resid) PetscCall(MatView(R,view));
     180             :   }
     181             : 
     182         192 :   if (l>0) {
     183             :     /* Check orthogonality */
     184         156 :     PetscCall(BVDot(Y,Y,M));
     185         156 :     PetscCall(MyMatNorm(M,k,l,k,1.0,&norm));
     186         156 :     if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Level of orthogonality of Q2 < 100*eps\n"));
     187           0 :     else PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Level of orthogonality of Q2: %g\n",(double)norm));
     188             :   }
     189             : 
     190             :   /* Check the complete decomposition */
     191         192 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Overall decomposition\n"));
     192         192 :   PetscCall(BVSetActiveColumns(Y,0,k));
     193         192 :   PetscCall(BVSetActiveColumns(X,0,k));
     194             : 
     195             :   /* Check orthogonality */
     196         192 :   PetscCall(BVDot(Y,Y,M));
     197         192 :   PetscCall(MyMatNorm(M,k,0,k,1.0,&norm));
     198         192 :   if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Level of orthogonality of Q < 100*eps\n"));
     199           0 :   else PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Level of orthogonality of Q: %g\n",(double)norm));
     200             : 
     201         192 :   if (resid) {
     202             :     /* Check residual */
     203         100 :     PetscCall(BVMult(X,-1.0,1.0,Y,R));
     204         100 :     PetscCall(BVSetMatrix(X,NULL,PETSC_FALSE));
     205         100 :     PetscCall(BVNorm(X,NORM_FROBENIUS,&norm));
     206         100 :     if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Residual ||X-Q*R|| < 100*eps\n"));
     207           0 :     else PetscCall(PetscPrintf(PETSC_COMM_WORLD,"  Residual ||X-Q*R||: %g\n",(double)norm));
     208         100 :     PetscCall(MatDestroy(&R));
     209             :   }
     210             : 
     211         192 :   if (B) PetscCall(MatDestroy(&B));
     212         192 :   PetscCall(MatDestroy(&M));
     213         192 :   PetscCall(BVDestroy(&X));
     214         192 :   PetscCall(BVDestroy(&Y));
     215         192 :   PetscCall(VecDestroy(&t));
     216         192 :   PetscCall(SlepcFinalize());
     217             :   return 0;
     218             : }
     219             : 
     220             : /*TEST
     221             : 
     222             :    testset:
     223             :       args: -bv_orthog_block {{gs chol tsqr tsqrchol svqb}}
     224             :       nsize: 2
     225             :       output_file: output/test11_1.out
     226             :       test:
     227             :          suffix: 1
     228             :          args: -bv_type {{vecs contiguous svec mat}shared output}
     229             :       test:
     230             :          suffix: 1_cuda
     231             :          args: -bv_type {{svec mat}} -vec_type cuda
     232             :          requires: cuda
     233             : 
     234             :    testset:
     235             :       args: -withb -bv_orthog_block {{gs chol svqb}}
     236             :       nsize: 2
     237             :       output_file: output/test11_4.out
     238             :       test:
     239             :          suffix: 4
     240             :          args: -bv_type {{vecs contiguous svec mat}shared output}
     241             :       test:
     242             :          suffix: 4_cuda
     243             :          args: -bv_type {{svec mat}} -vec_type cuda -mat_type aijcusparse
     244             :          requires: cuda
     245             : 
     246             :    testset:
     247             :       args: -resid -bv_orthog_block {{gs chol tsqr tsqrchol svqb}}
     248             :       nsize: 2
     249             :       output_file: output/test11_6.out
     250             :       test:
     251             :          suffix: 6
     252             :          args: -bv_type {{vecs contiguous svec mat}shared output}
     253             :       test:
     254             :          suffix: 6_cuda
     255             :          args: -bv_type {{svec mat}} -vec_type cuda
     256             :          requires: cuda
     257             : 
     258             :    testset:
     259             :       args: -resid -withb -bv_orthog_block {{gs chol svqb}}
     260             :       nsize: 2
     261             :       output_file: output/test11_9.out
     262             :       test:
     263             :          suffix: 9
     264             :          args: -bv_type {{vecs contiguous svec mat}shared output}
     265             :       test:
     266             :          suffix: 9_cuda
     267             :          args: -bv_type {{svec mat}} -vec_type cuda -mat_type aijcusparse
     268             :          requires: cuda
     269             : 
     270             :    testset:
     271             :       args: -bv_orthog_block tsqr
     272             :       nsize: 7
     273             :       output_file: output/test11_1.out
     274             :       test:
     275             :          suffix: 11
     276             :          args: -bv_type {{vecs contiguous svec mat}shared output}
     277             :          requires: !defined(PETSCTEST_VALGRIND)
     278             :       test:
     279             :          suffix: 11_cuda
     280             :          TODO: too many processes accessing the GPU
     281             :          args: -bv_type {{svec mat}} -vec_type cuda
     282             :          requires: cuda !defined(PETSCTEST_VALGRIND)
     283             : 
     284             :    testset:
     285             :       args: -resid -n 180 -l 0 -k 7 -bv_orthog_block tsqr
     286             :       nsize: 9
     287             :       output_file: output/test11_12.out
     288             :       test:
     289             :          suffix: 12
     290             :          args: -bv_type {{vecs contiguous svec mat}shared output}
     291             :          requires: !single !defined(PETSCTEST_VALGRIND)
     292             :       test:
     293             :          suffix: 12_cuda
     294             :          TODO: too many processes accessing the GPU
     295             :          args: -bv_type {{svec mat}} -vec_type cuda
     296             :          requires: cuda !single !defined(PETSCTEST_VALGRIND)
     297             : 
     298             : TEST*/

Generated by: LCOV version 1.14