1 2 static char help[] = "Tests MatHYPRE\n"; 3 4 #include <petscmathypre.h> 5 6 int main(int argc, char **args) 7 { 8 Mat A, B, C, D; 9 Mat pAB, CD; 10 hypre_ParCSRMatrix *parcsr; 11 PetscReal err; 12 PetscInt i, j, N = 6, M = 6; 13 PetscBool flg, testptap = PETSC_TRUE, testmatmatmult = PETSC_TRUE; 14 PetscReal norm; 15 char file[256]; 16 MatType mtype = MATAIJ; 17 18 PetscFunctionBeginUser; 19 PetscCall(PetscInitialize(&argc, &args, (char *)0, help)); 20 PetscCall(PetscOptionsGetString(NULL, NULL, "-f", file, sizeof(file), &flg)); 21 #if defined(PETSC_USE_COMPLEX) 22 testptap = PETSC_FALSE; 23 testmatmatmult = PETSC_FALSE; 24 PetscCall(PetscOptionsInsertString(NULL, "-options_left 0")); 25 #endif 26 PetscCall(PetscOptionsGetBool(NULL, NULL, "-ptap", &testptap, NULL)); 27 PetscCall(PetscOptionsGetBool(NULL, NULL, "-matmatmult", &testmatmatmult, NULL)); 28 PetscCall(MatCreate(PETSC_COMM_WORLD, &A)); 29 #if PetscDefined(HAVE_HYPRE_DEVICE) 30 #if PetscDefined(HAVE_HIP) 31 mtype = MATAIJHIPSPARSE; 32 #elif PetscDefined(HAVE_CUDA) 33 mtype = MATAIJCUSPARSE; 34 #endif 35 #endif 36 37 if (!flg) { /* Create a matrix and test MatSetValues */ 38 PetscMPIInt size; 39 40 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 41 PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL)); 42 PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL)); 43 PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, M, N)); 44 PetscCall(MatSetType(A, mtype)); 45 PetscCall(MatSeqAIJSetPreallocation(A, 9, NULL)); 46 PetscCall(MatMPIAIJSetPreallocation(A, 9, NULL, 9, NULL)); 47 PetscCall(MatCreate(PETSC_COMM_WORLD, &B)); 48 PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, M, N)); 49 #if PetscDefined(HAVE_HYPRE_DEVICE) 50 PetscCall(MatSetType(B, mtype)); 51 #else 52 PetscCall(MatSetType(B, MATHYPRE)); 53 #endif 54 PetscCall(MatSeqAIJSetPreallocation(B, 9, NULL)); 55 PetscCall(MatMPIAIJSetPreallocation(B, 9, NULL, 9, NULL)); 56 if (M == N) { 57 PetscCall(MatHYPRESetPreallocation(B, 9, NULL, 9, NULL)); 58 } else { 59 PetscCall(MatHYPRESetPreallocation(B, 6, NULL, 6, NULL)); 60 } 61 if (M == N) { 62 for (i = 0; i < M; i++) { 63 PetscInt cols[] = {0, 1, 2, 3, 4, 5}; 64 PetscScalar vals[] = {0, 1. / size, 2. / size, 3. / size, 4. / size, 5. / size}; 65 for (j = i - 2; j < i + 1; j++) { 66 if (j >= N) { 67 PetscCall(MatSetValue(A, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES)); 68 PetscCall(MatSetValue(B, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES)); 69 } else if (i > j) { 70 PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES)); 71 PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES)); 72 } else { 73 PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES)); 74 PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES)); 75 } 76 } 77 PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES)); 78 PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES)); 79 } 80 } else { 81 PetscInt rows[2]; 82 PetscBool test_offproc = PETSC_FALSE; 83 84 PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_offproc", &test_offproc, NULL)); 85 if (test_offproc) { 86 const PetscInt *ranges; 87 PetscMPIInt rank; 88 89 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 90 PetscCall(MatGetOwnershipRanges(A, &ranges)); 91 rows[0] = ranges[(rank + 1) % size]; 92 rows[1] = ranges[(rank + 1) % size + 1]; 93 } else { 94 PetscCall(MatGetOwnershipRange(A, &rows[0], &rows[1])); 95 } 96 for (i = rows[0]; i < rows[1]; i++) { 97 PetscInt cols[] = {0, 1, 2, 3, 4, 5}; 98 PetscScalar vals[] = {-1, 1, -2, 2, -3, 3}; 99 100 PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES)); 101 PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES)); 102 } 103 } 104 /* MAT_FLUSH_ASSEMBLY currently not supported */ 105 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 106 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 107 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 108 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 109 #if PetscDefined(HAVE_HYPRE_DEVICE) 110 PetscCall(MatConvert(B, MATHYPRE, MAT_INPLACE_MATRIX, &B)); 111 #endif 112 113 #if defined(PETSC_USE_COMPLEX) 114 /* make the matrix imaginary */ 115 PetscCall(MatScale(A, PETSC_i)); 116 PetscCall(MatScale(B, PETSC_i)); 117 #endif 118 119 #if !PetscDefined(HAVE_HYPRE_DEVICE) 120 /* MatAXPY further exercises MatSetValues_HYPRE */ 121 PetscCall(MatAXPY(B, -1., A, DIFFERENT_NONZERO_PATTERN)); 122 PetscCall(MatConvert(B, MATMPIAIJ, MAT_INITIAL_MATRIX, &C)); 123 PetscCall(MatNorm(C, NORM_INFINITY, &err)); 124 PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatSetValues %g", err); 125 PetscCall(MatDestroy(&C)); 126 #endif 127 PetscCall(MatDestroy(&B)); 128 } else { 129 PetscViewer viewer; 130 131 PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file, FILE_MODE_READ, &viewer)); 132 PetscCall(MatSetFromOptions(A)); 133 PetscCall(MatLoad(A, viewer)); 134 PetscCall(MatSetType(A, mtype)); 135 PetscCall(PetscViewerDestroy(&viewer)); 136 PetscCall(MatGetSize(A, &M, &N)); 137 } 138 139 /* check conversion routines */ 140 PetscCall(MatViewFromOptions(A, NULL, "-view_A")); 141 PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B)); 142 PetscCall(MatViewFromOptions(B, NULL, "-view_convert")); 143 PetscCall(MatMultEqual(B, A, 4, &flg)); 144 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE init"); 145 PetscCall(MatConvert(A, MATHYPRE, MAT_REUSE_MATRIX, &B)); 146 PetscCall(MatViewFromOptions(B, NULL, "-view_convert")); 147 PetscCall(MatMultEqual(B, A, 4, &flg)); 148 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE reuse"); 149 PetscCall(MatConvert(B, MATIS, MAT_INITIAL_MATRIX, &D)); 150 PetscCall(MatConvert(B, MATIS, MAT_REUSE_MATRIX, &D)); 151 PetscCall(MatMultEqual(D, A, 4, &flg)); 152 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS"); 153 PetscCall(MatConvert(B, MATAIJ, MAT_INITIAL_MATRIX, &C)); 154 PetscCall(MatConvert(B, MATAIJ, MAT_REUSE_MATRIX, &C)); 155 PetscCall(MatMultEqual(C, A, 4, &flg)); 156 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ"); 157 PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN)); 158 PetscCall(MatNorm(C, NORM_INFINITY, &err)); 159 PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ %g", err); 160 PetscCall(MatDestroy(&C)); 161 PetscCall(MatConvert(D, MATAIJ, MAT_INITIAL_MATRIX, &C)); 162 PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN)); 163 PetscCall(MatNorm(C, NORM_INFINITY, &err)); 164 PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS %g", err); 165 PetscCall(MatDestroy(&C)); 166 PetscCall(MatDestroy(&D)); 167 168 /* check MatCreateFromParCSR */ 169 PetscCall(MatHYPREGetParCSR(B, &parcsr)); 170 PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_COPY_VALUES, &D)); 171 PetscCall(MatDestroy(&D)); 172 PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, PETSC_USE_POINTER, &C)); 173 174 /* check MatMult operations */ 175 PetscCall(MatMultEqual(A, B, 4, &flg)); 176 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult B"); 177 PetscCall(MatMultEqual(A, C, 4, &flg)); 178 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult C"); 179 PetscCall(MatMultAddEqual(A, B, 4, &flg)); 180 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd B"); 181 PetscCall(MatMultAddEqual(A, C, 4, &flg)); 182 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd C"); 183 PetscCall(MatMultTransposeEqual(A, B, 4, &flg)); 184 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose B"); 185 PetscCall(MatMultTransposeEqual(A, C, 4, &flg)); 186 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose C"); 187 PetscCall(MatMultTransposeAddEqual(A, B, 4, &flg)); 188 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd B"); 189 PetscCall(MatMultTransposeAddEqual(A, C, 4, &flg)); 190 PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd C"); 191 192 /* check PtAP */ 193 if (testptap && M == N) { 194 Mat pP, hP; 195 196 /* PETSc MatPtAP -> output is a MatAIJ 197 It uses HYPRE functions when -matptap_via hypre is specified at command line */ 198 PetscCall(MatPtAP(A, A, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pP)); 199 PetscCall(MatPtAP(A, A, MAT_REUSE_MATRIX, PETSC_DEFAULT, &pP)); 200 PetscCall(MatNorm(pP, NORM_INFINITY, &norm)); 201 PetscCall(MatPtAPMultEqual(A, A, pP, 10, &flg)); 202 PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_MatAIJ"); 203 204 /* MatPtAP_HYPRE_HYPRE -> output is a MatHYPRE */ 205 PetscCall(MatPtAP(C, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &hP)); 206 PetscCall(MatPtAP(C, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &hP)); 207 PetscCall(MatPtAPMultEqual(C, B, hP, 10, &flg)); 208 PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_HYPRE_HYPRE"); 209 210 /* Test MatAXPY_Basic() */ 211 #if !PetscDefined(HAVE_HYPRE_DEVICE) 212 PetscCall(MatAXPY(hP, -1., pP, DIFFERENT_NONZERO_PATTERN)); 213 PetscCall(MatHasOperation(hP, MATOP_NORM, &flg)); 214 if (!flg) { /* TODO add MatNorm_HYPRE */ 215 PetscCall(MatConvert(hP, MATAIJ, MAT_INPLACE_MATRIX, &hP)); 216 } 217 PetscCall(MatNorm(hP, NORM_INFINITY, &err)); 218 PetscCheck(err / norm <= PETSC_SMALL, PetscObjectComm((PetscObject)hP), PETSC_ERR_PLIB, "Error MatPtAP %g %g", err, norm); 219 #endif 220 PetscCall(MatDestroy(&pP)); 221 PetscCall(MatDestroy(&hP)); 222 223 /* MatPtAP_AIJ_HYPRE -> output can be decided at runtime with -matptap_hypre_outtype */ 224 #if !PetscDefined(HAVE_HYPRE_DEVICE) 225 PetscCall(MatPtAP(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &hP)); 226 PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &hP)); 227 PetscCall(MatPtAPMultEqual(A, B, hP, 10, &flg)); 228 PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_AIJ_HYPRE"); 229 PetscCall(MatDestroy(&hP)); 230 #endif 231 } 232 PetscCall(MatDestroy(&C)); 233 PetscCall(MatDestroy(&B)); 234 235 /* check MatMatMult */ 236 if (testmatmatmult) { 237 PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B)); 238 PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &C)); 239 PetscCall(MatConvert(B, MATHYPRE, MAT_INITIAL_MATRIX, &D)); 240 241 /* PETSc MatMatMult -> output is a MatAIJ 242 It uses HYPRE functions when -matmatmult_via hypre is specified at command line */ 243 PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pAB)); 244 PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &pAB)); 245 PetscCall(MatNorm(pAB, NORM_INFINITY, &norm)); 246 PetscCall(MatMatMultEqual(A, B, pAB, 10, &flg)); 247 PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_AIJ_AIJ"); 248 249 /* MatMatMult_HYPRE_HYPRE -> output is a MatHYPRE */ 250 PetscCall(MatMatMult(C, D, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CD)); 251 PetscCall(MatMatMult(C, D, MAT_REUSE_MATRIX, PETSC_DEFAULT, &CD)); 252 PetscCall(MatMatMultEqual(C, D, CD, 10, &flg)); 253 PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_HYPRE_HYPRE"); 254 255 /* Test MatAXPY_Basic() */ 256 #if !PetscDefined(HAVE_HYPRE_DEVICE) 257 PetscCall(MatAXPY(CD, -1., pAB, DIFFERENT_NONZERO_PATTERN)); 258 259 PetscCall(MatHasOperation(CD, MATOP_NORM, &flg)); 260 if (!flg) { /* TODO add MatNorm_HYPRE */ 261 PetscCall(MatConvert(CD, MATAIJ, MAT_INPLACE_MATRIX, &CD)); 262 } 263 PetscCall(MatNorm(CD, NORM_INFINITY, &err)); 264 PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)CD), PETSC_ERR_PLIB, "Error MatMatMult %g %g", err, norm); 265 #endif 266 267 PetscCall(MatDestroy(&C)); 268 PetscCall(MatDestroy(&D)); 269 PetscCall(MatDestroy(&pAB)); 270 PetscCall(MatDestroy(&CD)); 271 272 /* When configured with HYPRE, MatMatMatMult is available for the triplet transpose(aij)-aij-aij */ 273 #if !PetscDefined(HAVE_HYPRE_DEVICE) 274 Mat CAB; 275 PetscCall(MatCreateTranspose(A, &C)); 276 PetscCall(MatMatMatMult(C, A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CAB)); 277 PetscCall(MatDestroy(&C)); 278 PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &C)); 279 PetscCall(MatMatMult(C, A, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &D)); 280 PetscCall(MatDestroy(&C)); 281 PetscCall(MatMatMult(D, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C)); 282 PetscCall(MatNorm(C, NORM_INFINITY, &norm)); 283 PetscCall(MatAXPY(C, -1., CAB, DIFFERENT_NONZERO_PATTERN)); 284 PetscCall(MatNorm(C, NORM_INFINITY, &err)); 285 PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMatMatMult %g %g", err, norm); 286 PetscCall(MatDestroy(&C)); 287 PetscCall(MatDestroy(&D)); 288 PetscCall(MatDestroy(&CAB)); 289 #endif 290 PetscCall(MatDestroy(&B)); 291 } 292 293 /* Check MatView */ 294 PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B)); 295 PetscCall(MatViewFromOptions(B, NULL, "-view_B")); 296 297 /* Check MatDuplicate/MatCopy */ 298 for (j = 0; j < 3; j++) { 299 MatDuplicateOption dop; 300 301 dop = MAT_COPY_VALUES; 302 if (j == 1) dop = MAT_DO_NOT_COPY_VALUES; 303 if (j == 2) dop = MAT_SHARE_NONZERO_PATTERN; 304 305 for (i = 0; i < 3; i++) { 306 MatStructure str; 307 308 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Dup/Copy tests: %" PetscInt_FMT " %" PetscInt_FMT "\n", j, i)); 309 310 str = DIFFERENT_NONZERO_PATTERN; 311 if (i == 1) str = SAME_NONZERO_PATTERN; 312 if (i == 2) str = SUBSET_NONZERO_PATTERN; 313 314 PetscCall(MatDuplicate(A, dop, &C)); 315 PetscCall(MatDuplicate(B, dop, &D)); 316 if (dop != MAT_COPY_VALUES) { 317 PetscCall(MatCopy(A, C, str)); 318 PetscCall(MatCopy(B, D, str)); 319 } 320 /* AXPY with AIJ and HYPRE */ 321 #if !PetscDefined(HAVE_HYPRE_DEVICE) 322 PetscCall(MatAXPY(C, -1.0, D, str)); 323 PetscCall(MatNorm(C, NORM_INFINITY, &err)); 324 #else 325 err = 0.0; 326 #endif 327 if (err > PETSC_SMALL) { 328 PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff")); 329 PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff")); 330 PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff")); 331 PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff")); 332 SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 1 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i); 333 } 334 /* AXPY with HYPRE and HYPRE */ 335 PetscCall(MatAXPY(D, -1.0, B, str)); 336 if (err > PETSC_SMALL) { 337 PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff")); 338 PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff")); 339 PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff")); 340 SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 2 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i); 341 } 342 #if !PetscDefined(HAVE_HYPRE_DEVICE) 343 /* Copy from HYPRE to AIJ */ 344 PetscCall(MatCopy(B, C, str)); 345 /* Copy from AIJ to HYPRE */ 346 PetscCall(MatCopy(A, D, str)); 347 /* AXPY with HYPRE and AIJ */ 348 PetscCall(MatAXPY(D, -1.0, C, str)); 349 PetscCall(MatHasOperation(D, MATOP_NORM, &flg)); 350 if (!flg) { /* TODO add MatNorm_HYPRE */ 351 PetscCall(MatConvert(D, MATAIJ, MAT_INPLACE_MATRIX, &D)); 352 } 353 PetscCall(MatNorm(D, NORM_INFINITY, &err)); 354 if (err > PETSC_SMALL) { 355 PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff")); 356 PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff")); 357 PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff")); 358 SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 3 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i); 359 } 360 #endif 361 PetscCall(MatDestroy(&C)); 362 PetscCall(MatDestroy(&D)); 363 } 364 } 365 PetscCall(MatDestroy(&B)); 366 367 PetscCall(MatHasCongruentLayouts(A, &flg)); 368 if (flg) { 369 Vec y, y2; 370 371 PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B)); 372 PetscCall(MatCreateVecs(A, NULL, &y)); 373 PetscCall(MatCreateVecs(B, NULL, &y2)); 374 PetscCall(MatGetDiagonal(A, y)); 375 PetscCall(MatGetDiagonal(B, y2)); 376 PetscCall(VecAXPY(y2, -1.0, y)); 377 PetscCall(VecNorm(y2, NORM_INFINITY, &err)); 378 if (err > PETSC_SMALL) { 379 PetscCall(VecViewFromOptions(y, NULL, "-view_diagonal_diff")); 380 PetscCall(VecViewFromOptions(y2, NULL, "-view_diagonal_diff")); 381 SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatGetDiagonal %g", err); 382 } 383 PetscCall(MatDestroy(&B)); 384 PetscCall(VecDestroy(&y)); 385 PetscCall(VecDestroy(&y2)); 386 } 387 388 PetscCall(MatDestroy(&A)); 389 390 PetscCall(PetscFinalize()); 391 return 0; 392 } 393 394 /*TEST 395 396 build: 397 requires: hypre 398 399 test: 400 suffix: 1 401 args: -N 11 -M 11 402 output_file: output/ex115_1.out 403 404 test: 405 suffix: 2 406 nsize: 3 407 args: -N 13 -M 13 -matmatmult_via hypre -options_left 0 408 output_file: output/ex115_1.out 409 410 test: 411 suffix: 3 412 nsize: 4 413 args: -M 13 -N 7 -matmatmult_via hypre -options_left 0 414 output_file: output/ex115_1.out 415 416 test: 417 suffix: 4 418 nsize: 2 419 args: -M 12 -N 19 420 output_file: output/ex115_1.out 421 422 test: 423 suffix: 5 424 nsize: 3 425 args: -M 13 -N 13 -options_left 0 -matptap_via hypre -matptap_hypre_outtype hypre 426 output_file: output/ex115_1.out 427 428 test: 429 requires: !defined(PETSC_HAVE_HYPRE_DEVICE) 430 suffix: 6 431 nsize: 3 432 args: -M 12 -N 19 -test_offproc 433 output_file: output/ex115_1.out 434 435 test: 436 requires: !defined(PETSC_HAVE_HYPRE_DEVICE) 437 suffix: 7 438 nsize: 3 439 args: -M 19 -N 12 -test_offproc -view_B ::ascii_info_detail 440 output_file: output/ex115_7.out 441 442 test: 443 requires: !defined(PETSC_HAVE_HYPRE_DEVICE) 444 suffix: 8 445 nsize: 3 446 args: -M 1 -N 12 -test_offproc 447 output_file: output/ex115_1.out 448 449 test: 450 requires: !defined(PETSC_HAVE_HYPRE_DEVICE) 451 suffix: 9 452 nsize: 3 453 args: -M 1 -N 2 -test_offproc 454 output_file: output/ex115_1.out 455 456 TEST*/ 457