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