1 2 static char help[] = "Tests MatTranspose(), MatNorm(), MatAXPY() and MatAYPX().\n\n"; 3 4 #include <petscmat.h> 5 6 static PetscErrorCode TransposeAXPY(Mat C, PetscScalar alpha, Mat mat, PetscErrorCode (*f)(Mat, Mat *)) { 7 Mat D, E, F, G; 8 MatType mtype; 9 10 PetscFunctionBegin; 11 PetscCall(MatGetType(mat, &mtype)); 12 if (f == MatCreateTranspose) { 13 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nMatAXPY: (C^T)^T = (C^T)^T + alpha * A, C=A, SAME_NONZERO_PATTERN\n")); 14 } else { 15 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nMatAXPY: (C^H)^H = (C^H)^H + alpha * A, C=A, SAME_NONZERO_PATTERN\n")); 16 } 17 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, &C)); 18 PetscCall(f(C, &D)); 19 PetscCall(f(D, &E)); 20 PetscCall(MatAXPY(E, alpha, mat, SAME_NONZERO_PATTERN)); 21 PetscCall(MatConvert(E, mtype, MAT_INPLACE_MATRIX, &E)); 22 PetscCall(MatView(E, PETSC_VIEWER_STDOUT_WORLD)); 23 PetscCall(MatDestroy(&E)); 24 PetscCall(MatDestroy(&D)); 25 PetscCall(MatDestroy(&C)); 26 if (f == MatCreateTranspose) { 27 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: C = C + alpha * (A^T)^T, C=A, SAME_NONZERO_PATTERN\n")); 28 } else { 29 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: C = C + alpha * (A^H)^H, C=A, SAME_NONZERO_PATTERN\n")); 30 } 31 if (f == MatCreateTranspose) { 32 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &D)); 33 } else { 34 PetscCall(MatHermitianTranspose(mat, MAT_INITIAL_MATRIX, &D)); 35 } 36 PetscCall(f(D, &E)); 37 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, &C)); 38 PetscCall(MatAXPY(C, alpha, E, SAME_NONZERO_PATTERN)); 39 PetscCall(MatView(C, PETSC_VIEWER_STDOUT_WORLD)); 40 PetscCall(MatDestroy(&E)); 41 PetscCall(MatDestroy(&D)); 42 PetscCall(MatDestroy(&C)); 43 if (f == MatCreateTranspose) { 44 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: (C^T)^T = (C^T)^T + alpha * (A^T)^T, C=A, SAME_NONZERO_PATTERN\n")); 45 } else { 46 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: (C^H)^H = (C^H)^H + alpha * (A^H)^H, C=A, SAME_NONZERO_PATTERN\n")); 47 } 48 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, &C)); 49 PetscCall(f(C, &D)); 50 PetscCall(f(D, &E)); 51 PetscCall(f(mat, &F)); 52 PetscCall(f(F, &G)); 53 PetscCall(MatAXPY(E, alpha, G, SAME_NONZERO_PATTERN)); 54 PetscCall(MatConvert(E, mtype, MAT_INPLACE_MATRIX, &E)); 55 PetscCall(MatView(E, PETSC_VIEWER_STDOUT_WORLD)); 56 PetscCall(MatDestroy(&G)); 57 PetscCall(MatDestroy(&F)); 58 PetscCall(MatDestroy(&E)); 59 PetscCall(MatDestroy(&D)); 60 PetscCall(MatDestroy(&C)); 61 62 /* Call f on a matrix that does not implement the transposition */ 63 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: Now without the transposition operation\n")); 64 PetscCall(MatConvert(mat, MATSHELL, MAT_INITIAL_MATRIX, &C)); 65 PetscCall(f(C, &D)); 66 PetscCall(f(D, &E)); 67 /* XXX cannot use MAT_INPLACE_MATRIX, it leaks mat */ 68 PetscCall(MatConvert(E, mtype, MAT_INITIAL_MATRIX, &F)); 69 PetscCall(MatAXPY(F, alpha, mat, SAME_NONZERO_PATTERN)); 70 PetscCall(MatView(F, PETSC_VIEWER_STDOUT_WORLD)); 71 PetscCall(MatDestroy(&F)); 72 PetscCall(MatDestroy(&E)); 73 PetscCall(MatDestroy(&D)); 74 PetscCall(MatDestroy(&C)); 75 PetscFunctionReturn(0); 76 } 77 78 int main(int argc, char **argv) { 79 Mat mat, tmat = 0; 80 PetscInt m = 7, n, i, j, rstart, rend, rect = 0; 81 PetscMPIInt size, rank; 82 PetscBool flg; 83 PetscScalar v, alpha; 84 PetscReal normf, normi, norm1; 85 86 PetscFunctionBeginUser; 87 PetscCall(PetscInitialize(&argc, &argv, (char *)0, help)); 88 PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_COMMON)); 89 PetscCall(PetscOptionsGetInt(NULL, NULL, "-m", &m, NULL)); 90 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 91 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 92 n = m; 93 PetscCall(PetscOptionsHasName(NULL, NULL, "-rectA", &flg)); 94 if (flg) { 95 n += 2; 96 rect = 1; 97 } 98 PetscCall(PetscOptionsHasName(NULL, NULL, "-rectB", &flg)); 99 if (flg) { 100 n -= 2; 101 rect = 1; 102 } 103 104 /* ------- Assemble matrix --------- */ 105 PetscCall(MatCreate(PETSC_COMM_WORLD, &mat)); 106 PetscCall(MatSetSizes(mat, PETSC_DECIDE, PETSC_DECIDE, m, n)); 107 PetscCall(MatSetFromOptions(mat)); 108 PetscCall(MatSetUp(mat)); 109 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 110 for (i = rstart; i < rend; i++) { 111 for (j = 0; j < n; j++) { 112 v = 10.0 * i + j + 1.0; 113 PetscCall(MatSetValues(mat, 1, &i, 1, &j, &v, INSERT_VALUES)); 114 } 115 } 116 PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 117 PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 118 119 /* ----------------- Test MatNorm() ----------------- */ 120 PetscCall(MatNorm(mat, NORM_FROBENIUS, &normf)); 121 PetscCall(MatNorm(mat, NORM_1, &norm1)); 122 PetscCall(MatNorm(mat, NORM_INFINITY, &normi)); 123 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "original A: Frobenious norm = %g, one norm = %g, infinity norm = %g\n", (double)normf, (double)norm1, (double)normi)); 124 PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD)); 125 126 /* --------------- Test MatTranspose() -------------- */ 127 PetscCall(PetscOptionsHasName(NULL, NULL, "-in_place", &flg)); 128 if (!rect && flg) { 129 PetscCall(MatTranspose(mat, MAT_REUSE_MATRIX, &mat)); /* in-place transpose */ 130 tmat = mat; 131 mat = NULL; 132 } else { /* out-of-place transpose */ 133 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &tmat)); 134 } 135 136 /* ----------------- Test MatNorm() ----------------- */ 137 /* Print info about transpose matrix */ 138 PetscCall(MatNorm(tmat, NORM_FROBENIUS, &normf)); 139 PetscCall(MatNorm(tmat, NORM_1, &norm1)); 140 PetscCall(MatNorm(tmat, NORM_INFINITY, &normi)); 141 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "B = A^T: Frobenious norm = %g, one norm = %g, infinity norm = %g\n", (double)normf, (double)norm1, (double)normi)); 142 PetscCall(MatView(tmat, PETSC_VIEWER_STDOUT_WORLD)); 143 144 /* ----------------- Test MatAXPY(), MatAYPX() ----------------- */ 145 if (mat && !rect) { 146 alpha = 1.0; 147 PetscCall(PetscOptionsGetScalar(NULL, NULL, "-alpha", &alpha, NULL)); 148 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: B = B + alpha * A\n")); 149 PetscCall(MatAXPY(tmat, alpha, mat, DIFFERENT_NONZERO_PATTERN)); 150 PetscCall(MatView(tmat, PETSC_VIEWER_STDOUT_WORLD)); 151 152 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAYPX: B = alpha*B + A\n")); 153 PetscCall(MatAYPX(tmat, alpha, mat, DIFFERENT_NONZERO_PATTERN)); 154 PetscCall(MatView(tmat, PETSC_VIEWER_STDOUT_WORLD)); 155 } 156 157 { 158 Mat C; 159 alpha = 1.0; 160 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: C = C + alpha * A, C=A, SAME_NONZERO_PATTERN\n")); 161 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, &C)); 162 PetscCall(MatAXPY(C, alpha, mat, SAME_NONZERO_PATTERN)); 163 PetscCall(MatView(C, PETSC_VIEWER_STDOUT_WORLD)); 164 PetscCall(MatDestroy(&C)); 165 PetscCall(TransposeAXPY(C, alpha, mat, MatCreateTranspose)); 166 PetscCall(TransposeAXPY(C, alpha, mat, MatCreateHermitianTranspose)); 167 } 168 169 { 170 Mat matB; 171 /* get matB that has nonzeros of mat in all even numbers of row and col */ 172 PetscCall(MatCreate(PETSC_COMM_WORLD, &matB)); 173 PetscCall(MatSetSizes(matB, PETSC_DECIDE, PETSC_DECIDE, m, n)); 174 PetscCall(MatSetFromOptions(matB)); 175 PetscCall(MatSetUp(matB)); 176 PetscCall(MatGetOwnershipRange(matB, &rstart, &rend)); 177 if (rstart % 2 != 0) rstart++; 178 for (i = rstart; i < rend; i += 2) { 179 for (j = 0; j < n; j += 2) { 180 v = 10.0 * i + j + 1.0; 181 PetscCall(MatSetValues(matB, 1, &i, 1, &j, &v, INSERT_VALUES)); 182 } 183 } 184 PetscCall(MatAssemblyBegin(matB, MAT_FINAL_ASSEMBLY)); 185 PetscCall(MatAssemblyEnd(matB, MAT_FINAL_ASSEMBLY)); 186 PetscCall(PetscPrintf(PETSC_COMM_WORLD, " A: original matrix:\n")); 187 PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD)); 188 PetscCall(PetscPrintf(PETSC_COMM_WORLD, " B(a subset of A):\n")); 189 PetscCall(MatView(matB, PETSC_VIEWER_STDOUT_WORLD)); 190 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatAXPY: B = B + alpha * A, SUBSET_NONZERO_PATTERN\n")); 191 PetscCall(MatAXPY(mat, alpha, matB, SUBSET_NONZERO_PATTERN)); 192 PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD)); 193 PetscCall(MatDestroy(&matB)); 194 } 195 196 /* Test MatZeroRows */ 197 j = rstart - 1; 198 if (j < 0) j = m - 1; 199 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatZeroRows:\n")); 200 PetscCall(MatZeroRows(mat, 1, &j, 0.0, NULL, NULL)); 201 PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD)); 202 203 /* Test MatShift */ 204 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "MatShift: B = B - 2*I\n")); 205 PetscCall(MatShift(mat, -2.0)); 206 PetscCall(MatView(mat, PETSC_VIEWER_STDOUT_WORLD)); 207 208 PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD)); 209 /* Free data structures */ 210 PetscCall(MatDestroy(&mat)); 211 PetscCall(MatDestroy(&tmat)); 212 PetscCall(PetscFinalize()); 213 return 0; 214 } 215 216 /*TEST 217 218 test: 219 suffix: 11_A 220 args: -mat_type seqaij -rectA 221 filter: grep -v "Mat Object" 222 223 test: 224 suffix: 12_A 225 args: -mat_type seqdense -rectA 226 filter: grep -v type | grep -v "Mat Object" 227 228 test: 229 requires: cuda 230 suffix: 12_A_cuda 231 args: -mat_type seqdensecuda -rectA 232 output_file: output/ex2_12_A.out 233 filter: grep -v type | grep -v "Mat Object" 234 235 test: 236 requires: kokkos_kernels 237 suffix: 12_A_kokkos 238 args: -mat_type aijkokkos -rectA 239 output_file: output/ex2_12_A.out 240 filter: grep -v type | grep -v "Mat Object" 241 242 test: 243 suffix: 11_B 244 args: -mat_type seqaij -rectB 245 filter: grep -v "Mat Object" 246 247 test: 248 suffix: 12_B 249 args: -mat_type seqdense -rectB 250 filter: grep -v type | grep -v "Mat Object" 251 252 testset: 253 args: -rectB 254 output_file: output/ex2_12_B.out 255 filter: grep -v type | grep -v "Mat Object" 256 257 test: 258 requires: cuda 259 suffix: 12_B_cuda 260 args: -mat_type {{seqdensecuda seqaijcusparse}} 261 262 test: 263 requires: kokkos_kernels 264 suffix: 12_B_kokkos 265 args: -mat_type aijkokkos 266 267 test: 268 suffix: 12_B_aij 269 args: -mat_type aij 270 test: 271 suffix: 21 272 args: -mat_type mpiaij 273 filter: grep -v type | grep -v " MPI process" 274 275 test: 276 suffix: 22 277 args: -mat_type mpidense 278 filter: grep -v type | grep -v "Mat Object" 279 280 test: 281 requires: cuda 282 suffix: 22_cuda 283 output_file: output/ex2_22.out 284 args: -mat_type mpidensecuda 285 filter: grep -v type | grep -v "Mat Object" 286 287 test: 288 requires: kokkos_kernels 289 suffix: 22_kokkos 290 output_file: output/ex2_22.out 291 args: -mat_type aijkokkos 292 filter: grep -v type | grep -v "Mat Object" 293 294 test: 295 suffix: 23 296 nsize: 3 297 args: -mat_type mpiaij 298 filter: grep -v type | grep -v " MPI process" 299 300 test: 301 suffix: 24 302 nsize: 3 303 args: -mat_type mpidense 304 filter: grep -v type | grep -v "Mat Object" 305 306 test: 307 requires: cuda 308 suffix: 24_cuda 309 nsize: 3 310 output_file: output/ex2_24.out 311 args: -mat_type mpidensecuda 312 filter: grep -v type | grep -v "Mat Object" 313 314 test: 315 suffix: 2_aijcusparse_1 316 args: -mat_type mpiaijcusparse 317 output_file: output/ex2_21.out 318 requires: cuda 319 filter: grep -v type | grep -v " MPI process" 320 321 test: 322 suffix: 2_aijkokkos_1 323 args: -mat_type aijkokkos 324 output_file: output/ex2_21.out 325 requires: kokkos_kernels 326 filter: grep -v type | grep -v " MPI process" 327 328 test: 329 suffix: 2_aijcusparse_2 330 nsize: 3 331 args: -mat_type mpiaijcusparse 332 output_file: output/ex2_23.out 333 requires: cuda 334 filter: grep -v type | grep -v " MPI process" 335 336 test: 337 suffix: 2_aijkokkos_2 338 nsize: 3 339 args: -mat_type aijkokkos 340 output_file: output/ex2_23.out 341 # Turn off hip due to intermittent CI failures on hip.txcorp.com. Should re-enable this test when the machine is upgraded. 342 requires: !hip kokkos_kernels 343 filter: grep -v type | grep -v "MPI processes" 344 345 test: 346 suffix: 3 347 nsize: 2 348 args: -mat_type mpiaij -rectA 349 350 test: 351 suffix: 3_aijcusparse 352 nsize: 2 353 args: -mat_type mpiaijcusparse -rectA 354 requires: cuda 355 356 test: 357 suffix: 4 358 nsize: 2 359 args: -mat_type mpidense -rectA 360 filter: grep -v type | grep -v " MPI process" 361 362 test: 363 requires: cuda 364 suffix: 4_cuda 365 nsize: 2 366 output_file: output/ex2_4.out 367 args: -mat_type mpidensecuda -rectA 368 filter: grep -v type | grep -v " MPI process" 369 370 test: 371 suffix: aijcusparse_1 372 args: -mat_type seqaijcusparse -rectA 373 filter: grep -v "Mat Object" 374 output_file: output/ex2_11_A_aijcusparse.out 375 requires: cuda 376 377 TEST*/ 378