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