Actual source code: ex115.c


  2: static char help[] = "Tests MatHYPRE\n";

  4: #include <petscmathypre.h>

  6: int main(int argc, char **args)
  7: {
  8:   Mat                 A, B, C, D;
  9:   Mat                 pAB, CD, CAB;
 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];

 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 (!flg) { /* Create a matrix and test MatSetValues */
 29:     PetscMPIInt size;

 31:     PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
 32:     PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL));
 33:     PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL));
 34:     PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, M, N));
 35:     PetscCall(MatSetType(A, MATAIJ));
 36:     PetscCall(MatSeqAIJSetPreallocation(A, 9, NULL));
 37:     PetscCall(MatMPIAIJSetPreallocation(A, 9, NULL, 9, NULL));
 38:     PetscCall(MatCreate(PETSC_COMM_WORLD, &B));
 39:     PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, M, N));
 40:     PetscCall(MatSetType(B, MATHYPRE));
 41:     if (M == N) {
 42:       PetscCall(MatHYPRESetPreallocation(B, 9, NULL, 9, NULL));
 43:     } else {
 44:       PetscCall(MatHYPRESetPreallocation(B, 6, NULL, 6, NULL));
 45:     }
 46:     if (M == N) {
 47:       for (i = 0; i < M; i++) {
 48:         PetscInt    cols[] = {0, 1, 2, 3, 4, 5};
 49:         PetscScalar vals[] = {0, 1. / size, 2. / size, 3. / size, 4. / size, 5. / size};
 50:         for (j = i - 2; j < i + 1; j++) {
 51:           if (j >= N) {
 52:             PetscCall(MatSetValue(A, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES));
 53:             PetscCall(MatSetValue(B, i, N - 1, (1. * j * N + i) / (3. * N * size), ADD_VALUES));
 54:           } else if (i > j) {
 55:             PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES));
 56:             PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), (1. * j * N + i) / (2. * N * size), ADD_VALUES));
 57:           } else {
 58:             PetscCall(MatSetValue(A, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES));
 59:             PetscCall(MatSetValue(B, i, PetscMin(j, N - 1), -1. - (1. * j * N + i) / (4. * N * size), ADD_VALUES));
 60:           }
 61:         }
 62:         PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES));
 63:         PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, ADD_VALUES));
 64:       }
 65:     } else {
 66:       PetscInt  rows[2];
 67:       PetscBool test_offproc = PETSC_FALSE;

 69:       PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_offproc", &test_offproc, NULL));
 70:       if (test_offproc) {
 71:         const PetscInt *ranges;
 72:         PetscMPIInt     rank;

 74:         PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
 75:         PetscCall(MatGetOwnershipRanges(A, &ranges));
 76:         rows[0] = ranges[(rank + 1) % size];
 77:         rows[1] = ranges[(rank + 1) % size + 1];
 78:       } else {
 79:         PetscCall(MatGetOwnershipRange(A, &rows[0], &rows[1]));
 80:       }
 81:       for (i = rows[0]; i < rows[1]; i++) {
 82:         PetscInt    cols[] = {0, 1, 2, 3, 4, 5};
 83:         PetscScalar vals[] = {-1, 1, -2, 2, -3, 3};

 85:         PetscCall(MatSetValues(A, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES));
 86:         PetscCall(MatSetValues(B, 1, &i, PetscMin(6, N), cols, vals, INSERT_VALUES));
 87:       }
 88:     }
 89:     /* MAT_FLUSH_ASSEMBLY currently not supported */
 90:     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
 91:     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
 92:     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
 93:     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));

 95: #if defined(PETSC_USE_COMPLEX)
 96:     /* make the matrix imaginary */
 97:     PetscCall(MatScale(A, PETSC_i));
 98:     PetscCall(MatScale(B, PETSC_i));
 99: #endif

101:     /* MatAXPY further exercises MatSetValues_HYPRE */
102:     PetscCall(MatAXPY(B, -1., A, DIFFERENT_NONZERO_PATTERN));
103:     PetscCall(MatConvert(B, MATMPIAIJ, MAT_INITIAL_MATRIX, &C));
104:     PetscCall(MatNorm(C, NORM_INFINITY, &err));
105:     PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatSetValues %g", err);
106:     PetscCall(MatDestroy(&B));
107:     PetscCall(MatDestroy(&C));
108:   } else {
109:     PetscViewer viewer;

111:     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file, FILE_MODE_READ, &viewer));
112:     PetscCall(MatSetFromOptions(A));
113:     PetscCall(MatLoad(A, viewer));
114:     PetscCall(PetscViewerDestroy(&viewer));
115:     PetscCall(MatGetSize(A, &M, &N));
116:   }

118:   /* check conversion routines */
119:   PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
120:   PetscCall(MatConvert(A, MATHYPRE, MAT_REUSE_MATRIX, &B));
121:   PetscCall(MatMultEqual(B, A, 4, &flg));
122:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat HYPRE");
123:   PetscCall(MatConvert(B, MATIS, MAT_INITIAL_MATRIX, &D));
124:   PetscCall(MatConvert(B, MATIS, MAT_REUSE_MATRIX, &D));
125:   PetscCall(MatMultEqual(D, A, 4, &flg));
126:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS");
127:   PetscCall(MatConvert(B, MATAIJ, MAT_INITIAL_MATRIX, &C));
128:   PetscCall(MatConvert(B, MATAIJ, MAT_REUSE_MATRIX, &C));
129:   PetscCall(MatMultEqual(C, A, 4, &flg));
130:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ");
131:   PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN));
132:   PetscCall(MatNorm(C, NORM_INFINITY, &err));
133:   PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat AIJ %g", err);
134:   PetscCall(MatDestroy(&C));
135:   PetscCall(MatConvert(D, MATAIJ, MAT_INITIAL_MATRIX, &C));
136:   PetscCall(MatAXPY(C, -1., A, SAME_NONZERO_PATTERN));
137:   PetscCall(MatNorm(C, NORM_INFINITY, &err));
138:   PetscCheck(err <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error Mat IS %g", err);
139:   PetscCall(MatDestroy(&C));
140:   PetscCall(MatDestroy(&D));

142:   /* check MatCreateFromParCSR */
143:   PetscCall(MatHYPREGetParCSR(B, &parcsr));
144:   PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_COPY_VALUES, &D));
145:   PetscCall(MatDestroy(&D));
146:   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, PETSC_USE_POINTER, &C));

148:   /* check MatMult operations */
149:   PetscCall(MatMultEqual(A, B, 4, &flg));
150:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult B");
151:   PetscCall(MatMultEqual(A, C, 4, &flg));
152:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMult C");
153:   PetscCall(MatMultAddEqual(A, B, 4, &flg));
154:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd B");
155:   PetscCall(MatMultAddEqual(A, C, 4, &flg));
156:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultAdd C");
157:   PetscCall(MatMultTransposeEqual(A, B, 4, &flg));
158:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose B");
159:   PetscCall(MatMultTransposeEqual(A, C, 4, &flg));
160:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTranspose C");
161:   PetscCall(MatMultTransposeAddEqual(A, B, 4, &flg));
162:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd B");
163:   PetscCall(MatMultTransposeAddEqual(A, C, 4, &flg));
164:   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMultTransposeAdd C");

166:   /* check PtAP */
167:   if (testptap && M == N) {
168:     Mat pP, hP;

170:     /* PETSc MatPtAP -> output is a MatAIJ
171:        It uses HYPRE functions when -matptap_via hypre is specified at command line */
172:     PetscCall(MatPtAP(A, A, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pP));
173:     PetscCall(MatPtAP(A, A, MAT_REUSE_MATRIX, PETSC_DEFAULT, &pP));
174:     PetscCall(MatNorm(pP, NORM_INFINITY, &norm));
175:     PetscCall(MatPtAPMultEqual(A, A, pP, 10, &flg));
176:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_MatAIJ");

178:     /* MatPtAP_HYPRE_HYPRE -> output is a MatHYPRE */
179:     PetscCall(MatPtAP(C, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &hP));
180:     PetscCall(MatPtAP(C, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &hP));
181:     PetscCall(MatPtAPMultEqual(C, B, hP, 10, &flg));
182:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_HYPRE_HYPRE");

184:     /* Test MatAXPY_Basic() */
185:     PetscCall(MatAXPY(hP, -1., pP, DIFFERENT_NONZERO_PATTERN));
186:     PetscCall(MatHasOperation(hP, MATOP_NORM, &flg));
187:     if (!flg) { /* TODO add MatNorm_HYPRE */
188:       PetscCall(MatConvert(hP, MATAIJ, MAT_INPLACE_MATRIX, &hP));
189:     }
190:     PetscCall(MatNorm(hP, NORM_INFINITY, &err));
191:     PetscCheck(err / norm <= PETSC_SMALL, PetscObjectComm((PetscObject)hP), PETSC_ERR_PLIB, "Error MatPtAP %g %g", err, norm);
192:     PetscCall(MatDestroy(&pP));
193:     PetscCall(MatDestroy(&hP));

195:     /* MatPtAP_AIJ_HYPRE -> output can be decided at runtime with -matptap_hypre_outtype */
196:     PetscCall(MatPtAP(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &hP));
197:     PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &hP));
198:     PetscCall(MatPtAPMultEqual(A, B, hP, 10, &flg));
199:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatPtAP_AIJ_HYPRE");
200:     PetscCall(MatDestroy(&hP));
201:   }
202:   PetscCall(MatDestroy(&C));
203:   PetscCall(MatDestroy(&B));

205:   /* check MatMatMult */
206:   if (testmatmatmult) {
207:     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B));
208:     PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &C));
209:     PetscCall(MatConvert(B, MATHYPRE, MAT_INITIAL_MATRIX, &D));

211:     /* PETSc MatMatMult -> output is a MatAIJ
212:        It uses HYPRE functions when -matmatmult_via hypre is specified at command line */
213:     PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pAB));
214:     PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &pAB));
215:     PetscCall(MatNorm(pAB, NORM_INFINITY, &norm));
216:     PetscCall(MatMatMultEqual(A, B, pAB, 10, &flg));
217:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_AIJ_AIJ");

219:     /* MatMatMult_HYPRE_HYPRE -> output is a MatHYPRE */
220:     PetscCall(MatMatMult(C, D, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CD));
221:     PetscCall(MatMatMult(C, D, MAT_REUSE_MATRIX, PETSC_DEFAULT, &CD));
222:     PetscCall(MatMatMultEqual(C, D, CD, 10, &flg));
223:     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Error in MatMatMult_HYPRE_HYPRE");

225:     /* Test MatAXPY_Basic() */
226:     PetscCall(MatAXPY(CD, -1., pAB, DIFFERENT_NONZERO_PATTERN));

228:     PetscCall(MatHasOperation(CD, MATOP_NORM, &flg));
229:     if (!flg) { /* TODO add MatNorm_HYPRE */
230:       PetscCall(MatConvert(CD, MATAIJ, MAT_INPLACE_MATRIX, &CD));
231:     }
232:     PetscCall(MatNorm(CD, NORM_INFINITY, &err));
233:     PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)CD), PETSC_ERR_PLIB, "Error MatMatMult %g %g", err, norm);

235:     PetscCall(MatDestroy(&C));
236:     PetscCall(MatDestroy(&D));
237:     PetscCall(MatDestroy(&pAB));
238:     PetscCall(MatDestroy(&CD));

240:     /* When configured with HYPRE, MatMatMatMult is available for the triplet transpose(aij)-aij-aij */
241:     PetscCall(MatCreateTranspose(A, &C));
242:     PetscCall(MatMatMatMult(C, A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CAB));
243:     PetscCall(MatDestroy(&C));
244:     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &C));
245:     PetscCall(MatMatMult(C, A, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &D));
246:     PetscCall(MatDestroy(&C));
247:     PetscCall(MatMatMult(D, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &C));
248:     PetscCall(MatNorm(C, NORM_INFINITY, &norm));
249:     PetscCall(MatAXPY(C, -1., CAB, DIFFERENT_NONZERO_PATTERN));
250:     PetscCall(MatNorm(C, NORM_INFINITY, &err));
251:     PetscCheck((err / norm) <= PETSC_SMALL, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatMatMatMult %g %g", err, norm);
252:     PetscCall(MatDestroy(&C));
253:     PetscCall(MatDestroy(&D));
254:     PetscCall(MatDestroy(&CAB));
255:     PetscCall(MatDestroy(&B));
256:   }

258:   /* Check MatView */
259:   PetscCall(MatViewFromOptions(A, NULL, "-view_A"));
260:   PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
261:   PetscCall(MatViewFromOptions(B, NULL, "-view_B"));

263:   /* Check MatDuplicate/MatCopy */
264:   for (j = 0; j < 3; j++) {
265:     MatDuplicateOption dop;

267:     dop = MAT_COPY_VALUES;
268:     if (j == 1) dop = MAT_DO_NOT_COPY_VALUES;
269:     if (j == 2) dop = MAT_SHARE_NONZERO_PATTERN;

271:     for (i = 0; i < 3; i++) {
272:       MatStructure str;

274:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Dup/Copy tests: %" PetscInt_FMT " %" PetscInt_FMT "\n", j, i));

276:       str = DIFFERENT_NONZERO_PATTERN;
277:       if (i == 1) str = SAME_NONZERO_PATTERN;
278:       if (i == 2) str = SUBSET_NONZERO_PATTERN;

280:       PetscCall(MatDuplicate(A, dop, &C));
281:       PetscCall(MatDuplicate(B, dop, &D));
282:       if (dop != MAT_COPY_VALUES) {
283:         PetscCall(MatCopy(A, C, str));
284:         PetscCall(MatCopy(B, D, str));
285:       }
286:       /* AXPY with AIJ and HYPRE */
287:       PetscCall(MatAXPY(C, -1.0, D, str));
288:       PetscCall(MatNorm(C, NORM_INFINITY, &err));
289:       if (err > PETSC_SMALL) {
290:         PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
291:         PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff"));
292:         PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff"));
293:         SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 1 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
294:       }
295:       /* AXPY with HYPRE and HYPRE */
296:       PetscCall(MatAXPY(D, -1.0, B, str));
297:       if (err > PETSC_SMALL) {
298:         PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
299:         PetscCall(MatViewFromOptions(B, NULL, "-view_duplicate_diff"));
300:         PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
301:         SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 2 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
302:       }
303:       /* Copy from HYPRE to AIJ */
304:       PetscCall(MatCopy(B, C, str));
305:       /* Copy from AIJ to HYPRE */
306:       PetscCall(MatCopy(A, D, str));
307:       /* AXPY with HYPRE and AIJ */
308:       PetscCall(MatAXPY(D, -1.0, C, str));
309:       PetscCall(MatHasOperation(D, MATOP_NORM, &flg));
310:       if (!flg) { /* TODO add MatNorm_HYPRE */
311:         PetscCall(MatConvert(D, MATAIJ, MAT_INPLACE_MATRIX, &D));
312:       }
313:       PetscCall(MatNorm(D, NORM_INFINITY, &err));
314:       if (err > PETSC_SMALL) {
315:         PetscCall(MatViewFromOptions(A, NULL, "-view_duplicate_diff"));
316:         PetscCall(MatViewFromOptions(C, NULL, "-view_duplicate_diff"));
317:         PetscCall(MatViewFromOptions(D, NULL, "-view_duplicate_diff"));
318:         SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error test 3 MatDuplicate/MatCopy %g (%" PetscInt_FMT ",%" PetscInt_FMT ")", err, j, i);
319:       }
320:       PetscCall(MatDestroy(&C));
321:       PetscCall(MatDestroy(&D));
322:     }
323:   }
324:   PetscCall(MatDestroy(&B));

326:   PetscCall(MatHasCongruentLayouts(A, &flg));
327:   if (flg) {
328:     Vec y, y2;

330:     PetscCall(MatConvert(A, MATHYPRE, MAT_INITIAL_MATRIX, &B));
331:     PetscCall(MatCreateVecs(A, NULL, &y));
332:     PetscCall(MatCreateVecs(B, NULL, &y2));
333:     PetscCall(MatGetDiagonal(A, y));
334:     PetscCall(MatGetDiagonal(B, y2));
335:     PetscCall(VecAXPY(y2, -1.0, y));
336:     PetscCall(VecNorm(y2, NORM_INFINITY, &err));
337:     if (err > PETSC_SMALL) {
338:       PetscCall(VecViewFromOptions(y, NULL, "-view_diagonal_diff"));
339:       PetscCall(VecViewFromOptions(y2, NULL, "-view_diagonal_diff"));
340:       SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Error MatGetDiagonal %g", err);
341:     }
342:     PetscCall(MatDestroy(&B));
343:     PetscCall(VecDestroy(&y));
344:     PetscCall(VecDestroy(&y2));
345:   }

347:   PetscCall(MatDestroy(&A));

349:   PetscCall(PetscFinalize());
350:   return 0;
351: }

353: /*TEST

355:    build:
356:       requires: hypre

358:    test:
359:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
360:       suffix: 1
361:       args: -N 11 -M 11
362:       output_file: output/ex115_1.out

364:    test:
365:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
366:       suffix: 2
367:       nsize: 3
368:       args: -N 13 -M 13 -matmatmult_via hypre
369:       output_file: output/ex115_1.out

371:    test:
372:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
373:       suffix: 3
374:       nsize: 4
375:       args: -M 13 -N 7 -matmatmult_via hypre
376:       output_file: output/ex115_1.out

378:    test:
379:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
380:       suffix: 4
381:       nsize: 2
382:       args: -M 12 -N 19
383:       output_file: output/ex115_1.out

385:    test:
386:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
387:       suffix: 5
388:       nsize: 3
389:       args: -M 13 -N 13 -matptap_via hypre -matptap_hypre_outtype hypre
390:       output_file: output/ex115_1.out

392:    test:
393:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
394:       suffix: 6
395:       nsize: 3
396:       args: -M 12 -N 19 -test_offproc
397:       output_file: output/ex115_1.out

399:    test:
400:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
401:       suffix: 7
402:       nsize: 3
403:       args: -M 19 -N 12 -test_offproc -view_B ::ascii_info_detail
404:       output_file: output/ex115_7.out

406:    test:
407:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
408:       suffix: 8
409:       nsize: 3
410:       args: -M 1 -N 12 -test_offproc
411:       output_file: output/ex115_1.out

413:    test:
414:       requires: !defined(PETSC_HAVE_HYPRE_DEVICE)
415:       suffix: 9
416:       nsize: 3
417:       args: -M 1 -N 2 -test_offproc
418:       output_file: output/ex115_1.out

420: TEST*/