1 static char help[] = "Test MatMatMult(), MatTranspose(), MatTransposeMatMult() for Dense and Elemental matrices.\n\n"; 2 /* 3 Example: 4 mpiexec -n <np> ./ex104 -mat_type elemental 5 */ 6 7 #include <petscmat.h> 8 9 int main(int argc,char **argv) 10 { 11 Mat A,B,C,D; 12 PetscInt i,M=10,N=5,j,nrows,ncols,am,an,rstart,rend; 13 PetscRandom r; 14 PetscBool equal,Aiselemental; 15 PetscReal fill = 1.0; 16 IS isrows,iscols; 17 const PetscInt *rows,*cols; 18 PetscScalar *v,rval; 19 #if defined(PETSC_HAVE_ELEMENTAL) 20 PetscBool Test_MatMatMult=PETSC_TRUE; 21 #else 22 PetscBool Test_MatMatMult=PETSC_FALSE; 23 #endif 24 PetscMPIInt size; 25 26 PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); 27 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 28 29 PetscCall(PetscOptionsGetInt(NULL,NULL,"-M",&M,NULL)); 30 PetscCall(PetscOptionsGetInt(NULL,NULL,"-N",&N,NULL)); 31 PetscCall(MatCreate(PETSC_COMM_WORLD,&A)); 32 PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,M,N)); 33 PetscCall(MatSetType(A,MATDENSE)); 34 PetscCall(MatSetFromOptions(A)); 35 PetscCall(MatSetUp(A)); 36 PetscCall(PetscRandomCreate(PETSC_COMM_WORLD,&r)); 37 PetscCall(PetscRandomSetFromOptions(r)); 38 39 /* Set local matrix entries */ 40 PetscCall(MatGetOwnershipIS(A,&isrows,&iscols)); 41 PetscCall(ISGetLocalSize(isrows,&nrows)); 42 PetscCall(ISGetIndices(isrows,&rows)); 43 PetscCall(ISGetLocalSize(iscols,&ncols)); 44 PetscCall(ISGetIndices(iscols,&cols)); 45 PetscCall(PetscMalloc1(nrows*ncols,&v)); 46 for (i=0; i<nrows; i++) { 47 for (j=0; j<ncols; j++) { 48 PetscCall(PetscRandomGetValue(r,&rval)); 49 v[i*ncols+j] = rval; 50 } 51 } 52 PetscCall(MatSetValues(A,nrows,rows,ncols,cols,v,INSERT_VALUES)); 53 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 54 PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 55 PetscCall(ISRestoreIndices(isrows,&rows)); 56 PetscCall(ISRestoreIndices(iscols,&cols)); 57 PetscCall(ISDestroy(&isrows)); 58 PetscCall(ISDestroy(&iscols)); 59 PetscCall(PetscRandomDestroy(&r)); 60 61 PetscCall(PetscObjectTypeCompare((PetscObject)A,MATELEMENTAL,&Aiselemental)); 62 63 /* Test MatCreateTranspose() and MatTranspose() */ 64 PetscCall(MatCreateTranspose(A,&C)); 65 PetscCall(MatTranspose(A,MAT_INITIAL_MATRIX,&B)); /* B = A^T */ 66 PetscCall(MatMultEqual(C,B,10,&equal)); 67 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"A^T*x != (x^T*A)^T"); 68 PetscCall(MatDestroy(&B)); 69 70 PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B)); 71 if (!Aiselemental) { 72 PetscCall(MatTranspose(B,MAT_INPLACE_MATRIX,&B)); 73 PetscCall(MatMultEqual(C,B,10,&equal)); 74 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"C*x != B*x"); 75 } 76 PetscCall(MatDestroy(&B)); 77 78 /* Test B = C*A for matrix type transpose and seqdense */ 79 if (size == 1 && !Aiselemental) { 80 PetscCall(MatMatMult(C,A,MAT_INITIAL_MATRIX,fill,&B)); 81 PetscCall(MatMatMultEqual(C,A,B,10,&equal)); 82 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"B != C*A for matrix type transpose and seqdense"); 83 PetscCall(MatDestroy(&B)); 84 } 85 PetscCall(MatDestroy(&C)); 86 87 /* Test MatMatMult() */ 88 if (Test_MatMatMult) { 89 #if !defined(PETSC_HAVE_ELEMENTAL) 90 PetscCheck(size == 1,PETSC_COMM_SELF,PETSC_ERR_SUP,"This test requires ELEMENTAL"); 91 #endif 92 PetscCall(MatTranspose(A,MAT_INITIAL_MATRIX,&B)); /* B = A^T */ 93 PetscCall(MatMatMult(B,A,MAT_INITIAL_MATRIX,fill,&C)); /* C = B*A = A^T*A */ 94 PetscCall(MatMatMult(B,A,MAT_REUSE_MATRIX,fill,&C)); 95 PetscCall(MatMatMultEqual(B,A,C,10,&equal)); 96 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"B*A*x != C*x"); 97 98 /* Test MatDuplicate for matrix product */ 99 PetscCall(MatDuplicate(C,MAT_COPY_VALUES,&D)); 100 101 PetscCall(MatDestroy(&D)); 102 PetscCall(MatDestroy(&C)); 103 PetscCall(MatDestroy(&B)); 104 } 105 106 /* Test MatTransposeMatMult() */ 107 if (!Aiselemental) { 108 PetscCall(MatTransposeMatMult(A,A,MAT_INITIAL_MATRIX,fill,&D)); /* D = A^T*A */ 109 PetscCall(MatTransposeMatMult(A,A,MAT_REUSE_MATRIX,fill,&D)); 110 PetscCall(MatTransposeMatMultEqual(A,A,D,10,&equal)); 111 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"D*x != A^T*A*x"); 112 113 /* Test MatDuplicate for matrix product */ 114 PetscCall(MatDuplicate(D,MAT_COPY_VALUES,&C)); 115 PetscCall(MatDestroy(&C)); 116 PetscCall(MatDestroy(&D)); 117 118 /* Test D*x = A^T*C*A*x, where C is in AIJ format */ 119 PetscCall(MatGetLocalSize(A,&am,&an)); 120 PetscCall(MatCreate(PETSC_COMM_WORLD,&C)); 121 if (size == 1) { 122 PetscCall(MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,am,am)); 123 } else { 124 PetscCall(MatSetSizes(C,am,am,PETSC_DECIDE,PETSC_DECIDE)); 125 } 126 PetscCall(MatSetFromOptions(C)); 127 PetscCall(MatSetUp(C)); 128 PetscCall(MatGetOwnershipRange(C,&rstart,&rend)); 129 v[0] = 1.0; 130 for (i=rstart; i<rend; i++) { 131 PetscCall(MatSetValues(C,1,&i,1,&i,v,INSERT_VALUES)); 132 } 133 PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 134 PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 135 136 /* B = C*A, D = A^T*B */ 137 PetscCall(MatMatMult(C,A,MAT_INITIAL_MATRIX,1.0,&B)); 138 PetscCall(MatTransposeMatMult(A,B,MAT_INITIAL_MATRIX,fill,&D)); 139 PetscCall(MatTransposeMatMultEqual(A,B,D,10,&equal)); 140 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"D*x != A^T*B*x"); 141 142 PetscCall(MatDestroy(&D)); 143 PetscCall(MatDestroy(&C)); 144 PetscCall(MatDestroy(&B)); 145 } 146 147 /* Test MatMatTransposeMult() */ 148 if (!Aiselemental) { 149 PetscReal diff, scale; 150 PetscInt am, an, aM, aN; 151 152 PetscCall(MatGetLocalSize(A, &am, &an)); 153 PetscCall(MatGetSize(A, &aM, &aN)); 154 PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A),PETSC_DECIDE, an, aM + 10, aN, NULL, &B)); 155 PetscCall(MatSetRandom(B, NULL)); 156 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 157 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 158 PetscCall(MatMatTransposeMult(A,B,MAT_INITIAL_MATRIX,fill,&D)); /* D = A*A^T */ 159 160 /* Test MatDuplicate for matrix product */ 161 PetscCall(MatDuplicate(D,MAT_COPY_VALUES,&C)); 162 163 PetscCall(MatMatTransposeMult(A,B,MAT_REUSE_MATRIX,fill,&D)); 164 PetscCall(MatAXPY(C, -1., D, SAME_NONZERO_PATTERN)); 165 166 PetscCall(MatNorm(C, NORM_FROBENIUS, &diff)); 167 PetscCall(MatNorm(D, NORM_FROBENIUS, &scale)); 168 PetscCheck(diff <= PETSC_SMALL * scale,PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "MatMatTransposeMult() differs between MAT_INITIAL_MATRIX and MAT_REUSE_MATRIX"); 169 PetscCall(MatDestroy(&C)); 170 171 PetscCall(MatMatTransposeMultEqual(A,B,D,10,&equal)); 172 PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"D*x != A^T*A*x"); 173 PetscCall(MatDestroy(&D)); 174 PetscCall(MatDestroy(&B)); 175 176 } 177 178 PetscCall(MatDestroy(&A)); 179 PetscCall(PetscFree(v)); 180 PetscCall(PetscFinalize()); 181 return 0; 182 } 183 184 /*TEST 185 186 test: 187 output_file: output/ex104.out 188 189 test: 190 suffix: 2 191 nsize: 2 192 output_file: output/ex104.out 193 194 test: 195 suffix: 3 196 nsize: 4 197 output_file: output/ex104.out 198 args: -M 23 -N 31 199 200 test: 201 suffix: 4 202 nsize: 4 203 output_file: output/ex104.out 204 args: -M 23 -N 31 -matmattransmult_mpidense_mpidense_via cyclic 205 206 test: 207 suffix: 5 208 nsize: 4 209 output_file: output/ex104.out 210 args: -M 23 -N 31 -matmattransmult_mpidense_mpidense_via allgatherv 211 212 test: 213 suffix: 6 214 args: -mat_type elemental 215 requires: elemental 216 output_file: output/ex104.out 217 218 test: 219 suffix: 7 220 nsize: 2 221 args: -mat_type elemental 222 requires: elemental 223 output_file: output/ex104.out 224 225 TEST*/ 226