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