xref: /petsc/src/mat/tests/ex115.c (revision daa037dfd3c3bec8dc8659548d2b20b07c1dc6de)
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,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];
16 
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