Actual source code: ex115.c
1: static char help[] = "Tests MatHYPRE\n";
3: #include <petscmathypre.h>
4: #include <petscpkg_version.h>
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;
18: PetscFunctionBeginUser;
19: PetscCall(PetscInitialize(&argc, &args, NULL, help));
20: PetscCall(PetscOptionsGetString(NULL, NULL, "-f", file, sizeof(file), &flg));
21: if (PetscDefined(USE_COMPLEX)) {
22: testptap = PETSC_FALSE;
23: testmatmatmult = PETSC_FALSE;
24: PetscCall(PetscOptionsInsertString(NULL, "-options_left 0"));
25: }
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
37: if (!flg) { /* Create a matrix and test MatSetValues */
38: PetscMPIInt size;
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;
84: PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_offproc", &test_offproc, NULL));
85: if (test_offproc) {
86: const PetscInt *ranges;
87: PetscMPIInt rank;
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};
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
113: #if PetscDefined(USE_COMPLEX)
114: /* make the matrix imaginary */
115: PetscCall(MatScale(A, PETSC_i));
116: PetscCall(MatScale(B, PETSC_i));
117: #endif
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;
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: }
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));
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));
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");
192: /* check PtAP */
193: if (testptap && M == N) {
194: Mat pP, hP;
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_DETERMINE, &pP));
199: PetscCall(MatPtAP(A, A, MAT_REUSE_MATRIX, PETSC_DETERMINE, &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");
204: /* MatPtAP_HYPRE_HYPRE -> output is a MatHYPRE */
205: PetscCall(MatPtAP(C, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &hP));
206: PetscCall(MatPtAP(C, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &hP));
207: PetscCall(MatPtAPMultEqual(C, B, hP, 10, &flg));
208: PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_HYPRE_HYPRE");
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));
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_DETERMINE, &hP));
226: PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &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));
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));
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_DETERMINE, &pAB));
244: PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &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");
249: /* MatMatMult_HYPRE_HYPRE -> output is a MatHYPRE */
250: PetscCall(MatMatMult(C, D, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &CD));
251: PetscCall(MatMatMult(C, D, MAT_REUSE_MATRIX, PETSC_DETERMINE, &CD));
252: PetscCall(MatMatMultEqual(C, D, CD, 10, &flg));
253: PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_HYPRE_HYPRE");
255: /* Test MatAXPY_Basic() */
256: #if !PetscDefined(HAVE_HYPRE_DEVICE)
257: PetscCall(MatAXPY(CD, -1., pAB, DIFFERENT_NONZERO_PATTERN));
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
267: PetscCall(MatDestroy(&C));
268: PetscCall(MatDestroy(&D));
269: PetscCall(MatDestroy(&pAB));
270: PetscCall(MatDestroy(&CD));
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_DETERMINE, &CAB));
277: PetscCall(MatDestroy(&C));
278: PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &C));
279: PetscCall(MatMatMult(C, A, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &D));
280: PetscCall(MatDestroy(&C));
281: PetscCall(MatMatMult(D, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &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: }
293: /* Check MatView */
294: PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
295: PetscCall(MatViewFromOptions(B, NULL, "-view_B"));
297: /* Check MatDuplicate/MatCopy */
298: for (j = 0; j < 3; j++) {
299: MatDuplicateOption dop;
301: dop = MAT_COPY_VALUES;
302: if (j == 1) dop = MAT_DO_NOT_COPY_VALUES;
303: if (j == 2) dop = MAT_SHARE_NONZERO_PATTERN;
305: for (i = 0; i < 3; i++) {
306: MatStructure str;
308: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Dup/Copy tests: %" PetscInt_FMT " %" PetscInt_FMT "\n", j, i));
310: str = DIFFERENT_NONZERO_PATTERN;
311: if (i == 1) str = SAME_NONZERO_PATTERN;
312: if (i == 2) str = SUBSET_NONZERO_PATTERN;
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));
367: #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
368: {
369: Vec y, y2;
371: PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
372: PetscCall(MatCreateVecs(A, NULL, &y));
373: PetscCall(MatCreateVecs(B, NULL, &y2));
374: PetscCall(MatGetRowSumAbs(A, y));
375: PetscCall(MatGetRowSumAbs(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_rowsumabs_diff"));
380: PetscCall(VecViewFromOptions(y2, NULL, "-view_rowsumabs_diff"));
381: SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatGetRowSumAbs %g", (double)err);
382: }
383: PetscCall(MatDestroy(&B));
384: PetscCall(VecDestroy(&y));
385: PetscCall(VecDestroy(&y2));
386: }
387: #endif
389: PetscCall(MatHasCongruentLayouts(A, &flg));
390: if (flg) {
391: Vec y, y2;
393: PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
394: PetscCall(MatCreateVecs(A, NULL, &y));
395: PetscCall(MatCreateVecs(B, NULL, &y2));
396: PetscCall(MatGetDiagonal(A, y));
397: PetscCall(MatGetDiagonal(B, y2));
398: PetscCall(VecAXPY(y2, -1.0, y));
399: PetscCall(VecNorm(y2, NORM_INFINITY, &err));
400: if (err > PETSC_SMALL) {
401: PetscCall(VecViewFromOptions(y, NULL, "-view_diagonal_diff"));
402: PetscCall(VecViewFromOptions(y2, NULL, "-view_diagonal_diff"));
403: SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatGetDiagonal %g", err);
404: }
405: PetscCall(MatDestroy(&B));
406: PetscCall(VecDestroy(&y));
407: PetscCall(VecDestroy(&y2));
408: }
410: PetscCall(MatDestroy(&A));
412: PetscCall(PetscFinalize());
413: return 0;
414: }
416: /*TEST
418: build:
419: requires: hypre
421: test:
422: suffix: 1
423: args: -N 11 -M 11
424: output_file: output/ex115_1.out
426: test:
427: suffix: 2
428: nsize: 3
429: args: -N 13 -M 13 -matmatmult_via hypre -options_left 0
430: output_file: output/ex115_1.out
432: test:
433: suffix: 3
434: nsize: 4
435: args: -M 13 -N 7 -matmatmult_via hypre -options_left 0
436: output_file: output/ex115_1.out
438: test:
439: suffix: 4
440: nsize: 2
441: args: -M 12 -N 19
442: output_file: output/ex115_1.out
444: test:
445: suffix: 5
446: nsize: 3
447: args: -M 13 -N 13 -options_left 0 -matptap_via hypre -matptap_hypre_outtype hypre
448: output_file: output/ex115_1.out
450: test:
451: requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
452: suffix: 6
453: nsize: 3
454: args: -M 12 -N 19 -test_offproc
455: output_file: output/ex115_1.out
457: test:
458: requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
459: suffix: 7
460: nsize: 3
461: args: -M 19 -N 12 -test_offproc -view_B ::ascii_info_detail
462: output_file: output/ex115_7.out
464: test:
465: requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
466: suffix: 8
467: nsize: 3
468: args: -M 1 -N 12 -test_offproc
469: output_file: output/ex115_1.out
471: test:
472: requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
473: suffix: 9
474: nsize: 3
475: args: -M 1 -N 2 -test_offproc
476: output_file: output/ex115_1.out
478: TEST*/