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