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