xref: /petsc/src/mat/tests/ex93.c (revision 9566063d113dddea24716c546802770db7481bc0)
1c4762a1bSJed Brown static char help[] = "Test MatMatMult() and MatPtAP() for AIJ matrices.\n\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown #include <petscmat.h>
4c4762a1bSJed Brown 
5c4762a1bSJed Brown extern PetscErrorCode testPTAPRectangular(void);
6c4762a1bSJed Brown 
7c4762a1bSJed Brown int main(int argc,char **argv)
8c4762a1bSJed Brown {
9c4762a1bSJed Brown   Mat            A,B,C,D;
10c4762a1bSJed Brown   PetscScalar    a[] ={1.,1.,0.,0.,1.,1.,0.,0.,1.};
11c4762a1bSJed Brown   PetscInt       ij[]={0,1,2};
12c20d7725SJed Brown   PetscReal      fill=4.0;
13c4762a1bSJed Brown   PetscMPIInt    size,rank;
14c20d7725SJed Brown   PetscBool      isequal;
15c20d7725SJed Brown #if defined(PETSC_HAVE_HYPRE)
16c4762a1bSJed Brown   PetscBool      test_hypre=PETSC_FALSE;
17c20d7725SJed Brown #endif
18c4762a1bSJed Brown 
19*9566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,(char*)0,help));
20c4762a1bSJed Brown #if defined(PETSC_HAVE_HYPRE)
21*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-test_hypre",&test_hypre,NULL));
22c4762a1bSJed Brown #endif
23*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
24*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
25c4762a1bSJed Brown 
26*9566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD,&A));
27*9566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,3,3));
28*9566063dSJacob Faibussowitsch   PetscCall(MatSetType(A,MATAIJ));
29*9566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(A));
30*9566063dSJacob Faibussowitsch   PetscCall(MatSetUp(A));
31*9566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE));
32c4762a1bSJed Brown 
33dd400576SPatrick Sanan   if (rank == 0) {
34*9566063dSJacob Faibussowitsch     PetscCall(MatSetValues(A,3,ij,3,ij,a,ADD_VALUES));
35c4762a1bSJed Brown   }
36*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
37*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
38c4762a1bSJed Brown 
39c4762a1bSJed Brown   /* Test MatMatMult() */
40*9566063dSJacob Faibussowitsch   PetscCall(MatTranspose(A,MAT_INITIAL_MATRIX,&B));      /* B = A^T */
41*9566063dSJacob Faibussowitsch   PetscCall(MatMatMult(B,A,MAT_INITIAL_MATRIX,fill,&C)); /* C = B*A */
42*9566063dSJacob Faibussowitsch   PetscCall(MatMatMult(B,A,MAT_REUSE_MATRIX,fill,&C));   /* recompute C=B*A */
43*9566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(C,"C_"));
44*9566063dSJacob Faibussowitsch   PetscCall(MatMatMultEqual(B,A,C,10,&isequal));
4528b400f6SJacob Faibussowitsch   PetscCheck(isequal,PETSC_COMM_WORLD,PETSC_ERR_ARG_INCOMP,"MatMatMult: C != B*A");
46c4762a1bSJed Brown 
47*9566063dSJacob Faibussowitsch   PetscCall(MatMatMult(C,A,MAT_INITIAL_MATRIX,fill,&D)); /* D = C*A = (A^T*A)*A */
48*9566063dSJacob Faibussowitsch   PetscCall(MatMatMult(C,A,MAT_REUSE_MATRIX,fill,&D));
49*9566063dSJacob Faibussowitsch   PetscCall(MatMatMultEqual(C,A,D,10,&isequal));
5028b400f6SJacob Faibussowitsch   PetscCheck(isequal,PETSC_COMM_WORLD,PETSC_ERR_ARG_INCOMP,"MatMatMult: D != C*A");
51c4762a1bSJed Brown 
52*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
53*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
54*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&D));
55c4762a1bSJed Brown 
56c20d7725SJed Brown   /* Test MatPtAP */
57*9566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B));      /* B = A */
58*9566063dSJacob Faibussowitsch   PetscCall(MatPtAP(A,B,MAT_INITIAL_MATRIX,fill,&C)); /* C = B^T*A*B */
59*9566063dSJacob Faibussowitsch   PetscCall(MatPtAPMultEqual(A,B,C,10,&isequal));
6028b400f6SJacob Faibussowitsch   PetscCheck(isequal,PETSC_COMM_WORLD,PETSC_ERR_ARG_INCOMP,"MatPtAP: C != B^T*A*B");
61c4762a1bSJed Brown 
62c20d7725SJed Brown   /* Repeat MatPtAP to test symbolic/numeric separation for reuse of the symbolic product */
63*9566063dSJacob Faibussowitsch   PetscCall(MatPtAP(A,B,MAT_REUSE_MATRIX,fill,&C));
64*9566063dSJacob Faibussowitsch   PetscCall(MatPtAPMultEqual(A,B,C,10,&isequal));
6528b400f6SJacob Faibussowitsch   PetscCheck(isequal,PETSC_COMM_WORLD,PETSC_ERR_ARG_INCOMP,"MatPtAP(reuse): C != B^T*A*B");
66c4762a1bSJed Brown 
67*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
68c1995e1cSHong Zhang 
69c1995e1cSHong Zhang   /* Test MatPtAP with A as a dense matrix */
70c1995e1cSHong Zhang   {
71c1995e1cSHong Zhang     Mat Adense;
72*9566063dSJacob Faibussowitsch     PetscCall(MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense));
73*9566063dSJacob Faibussowitsch     PetscCall(MatPtAP(Adense,B,MAT_INITIAL_MATRIX,fill,&C));
74c1995e1cSHong Zhang 
75*9566063dSJacob Faibussowitsch     PetscCall(MatPtAPMultEqual(Adense,B,C,10,&isequal));
76c1995e1cSHong Zhang     PetscCheck(isequal,PETSC_COMM_WORLD,PETSC_ERR_ARG_INCOMP,"MatPtAP(reuse): C != B^T*Adense*B");
77*9566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Adense));
78c1995e1cSHong Zhang   }
79c4762a1bSJed Brown 
80c4762a1bSJed Brown   if (size == 1) {
81c4762a1bSJed Brown     /* A test contributed by Tobias Neckel <neckel@in.tum.de> */
82*9566063dSJacob Faibussowitsch     PetscCall(testPTAPRectangular());
83c4762a1bSJed Brown 
84c4762a1bSJed Brown     /* test MatMatTransposeMult(): A*B^T */
85*9566063dSJacob Faibussowitsch     PetscCall(MatMatTransposeMult(A,A,MAT_INITIAL_MATRIX,fill,&D)); /* D = A*A^T */
86*9566063dSJacob Faibussowitsch     PetscCall(MatScale(A,2.0));
87*9566063dSJacob Faibussowitsch     PetscCall(MatMatTransposeMult(A,A,MAT_REUSE_MATRIX,fill,&D));
88*9566063dSJacob Faibussowitsch     PetscCall(MatMatTransposeMultEqual(A,A,D,10,&isequal));
8928b400f6SJacob Faibussowitsch     PetscCheck(isequal,PETSC_COMM_WORLD,PETSC_ERR_ARG_INCOMP,"MatMatTranspose: D != A*A^T");
90c4762a1bSJed Brown   }
91c4762a1bSJed Brown 
92*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
93*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
94*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
95*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&D));
96*9566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
97b122ec5aSJacob Faibussowitsch   return 0;
98c4762a1bSJed Brown }
99c4762a1bSJed Brown 
100c4762a1bSJed Brown /* a test contributed by Tobias Neckel <neckel@in.tum.de>, 02 Jul 2008 */
101c4762a1bSJed Brown PetscErrorCode testPTAPRectangular(void)
102c4762a1bSJed Brown {
103c20d7725SJed Brown   const int      rows = 3,cols = 5;
104c4762a1bSJed Brown   int            i;
105c20d7725SJed Brown   Mat            A,P,C;
106c4762a1bSJed Brown 
107c4762a1bSJed Brown   PetscFunctionBegin;
108c4762a1bSJed Brown   /* set up A  */
109*9566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJ(PETSC_COMM_WORLD, rows, rows,1, NULL, &A));
110c4762a1bSJed Brown   for (i=0; i<rows; i++) {
111*9566063dSJacob Faibussowitsch     PetscCall(MatSetValue(A, i, i, 1.0, INSERT_VALUES));
112c4762a1bSJed Brown   }
113*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
114*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
115c4762a1bSJed Brown 
116c4762a1bSJed Brown   /* set up P */
117*9566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJ(PETSC_COMM_WORLD, rows, cols,5, NULL, &P));
118*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 0, 0,  1.0, INSERT_VALUES));
119*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 0, 1,  2.0, INSERT_VALUES));
120*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 0, 2,  0.0, INSERT_VALUES));
121c4762a1bSJed Brown 
122*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 0, 3, -1.0, INSERT_VALUES));
123c4762a1bSJed Brown 
124*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 1, 0,  0.0, INSERT_VALUES));
125*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 1, 1, -1.0, INSERT_VALUES));
126*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 1, 2,  1.0, INSERT_VALUES));
127c4762a1bSJed Brown 
128*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 2, 0,  3.0, INSERT_VALUES));
129*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 2, 1,  0.0, INSERT_VALUES));
130*9566063dSJacob Faibussowitsch   PetscCall(MatSetValue(P, 2, 2, -3.0, INSERT_VALUES));
131c4762a1bSJed Brown 
132*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY));
133*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY));
134c4762a1bSJed Brown 
135c4762a1bSJed Brown   /* compute C */
136*9566063dSJacob Faibussowitsch   PetscCall(MatPtAP(A, P, MAT_INITIAL_MATRIX, 1.0, &C));
137c4762a1bSJed Brown 
138*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
139*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
140c4762a1bSJed Brown 
141c4762a1bSJed Brown   /* compare results */
142c4762a1bSJed Brown   /*
143c4762a1bSJed Brown   printf("C:\n");
144*9566063dSJacob Faibussowitsch   PetscCall(MatView(C,PETSC_VIEWER_STDOUT_WORLD));
145c4762a1bSJed Brown 
146c4762a1bSJed Brown   blitz::Array<double,2> actualC(cols, cols);
147c4762a1bSJed Brown   actualC = 0.0;
148c4762a1bSJed Brown   for (int i=0; i<cols; i++) {
149c4762a1bSJed Brown     for (int j=0; j<cols; j++) {
150*9566063dSJacob Faibussowitsch       PetscCall(MatGetValues(C, 1, &i, 1, &j, &actualC(i,j)));
151c4762a1bSJed Brown     }
152c4762a1bSJed Brown   }
153c4762a1bSJed Brown   blitz::Array<double,2> expectedC(cols, cols);
154c4762a1bSJed Brown   expectedC = 0.0;
155c4762a1bSJed Brown 
156c4762a1bSJed Brown   expectedC(0,0) = 10.0;
157c4762a1bSJed Brown   expectedC(0,1) =  2.0;
158c4762a1bSJed Brown   expectedC(0,2) = -9.0;
159c4762a1bSJed Brown   expectedC(0,3) = -1.0;
160c4762a1bSJed Brown   expectedC(1,0) =  2.0;
161c4762a1bSJed Brown   expectedC(1,1) =  5.0;
162c4762a1bSJed Brown   expectedC(1,2) = -1.0;
163c4762a1bSJed Brown   expectedC(1,3) = -2.0;
164c4762a1bSJed Brown   expectedC(2,0) = -9.0;
165c4762a1bSJed Brown   expectedC(2,1) = -1.0;
166c4762a1bSJed Brown   expectedC(2,2) = 10.0;
167c4762a1bSJed Brown   expectedC(2,3) =  0.0;
168c4762a1bSJed Brown   expectedC(3,0) = -1.0;
169c4762a1bSJed Brown   expectedC(3,1) = -2.0;
170c4762a1bSJed Brown   expectedC(3,2) =  0.0;
171c4762a1bSJed Brown   expectedC(3,3) =  1.0;
172c4762a1bSJed Brown 
173c4762a1bSJed Brown   int check = areBlitzArrays2NumericallyEqual(actualC,expectedC);
174c4762a1bSJed Brown   validateEqualsWithParams3(check, -1 , "testPTAPRectangular()", check, actualC(check), expectedC(check));
175c4762a1bSJed Brown   */
176c4762a1bSJed Brown 
177*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
178*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&P));
179*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
180c4762a1bSJed Brown   PetscFunctionReturn(0);
181c4762a1bSJed Brown }
182c4762a1bSJed Brown 
183c4762a1bSJed Brown /*TEST
184c4762a1bSJed Brown 
185c4762a1bSJed Brown    test:
186c4762a1bSJed Brown 
187c4762a1bSJed Brown    test:
188c4762a1bSJed Brown       suffix: 2
189c4762a1bSJed Brown       nsize: 2
190c20d7725SJed Brown       args: -matmatmult_via nonscalable
191c20d7725SJed Brown       output_file: output/ex93_1.out
192c4762a1bSJed Brown 
193c4762a1bSJed Brown    test:
194c4762a1bSJed Brown       suffix: 3
195c4762a1bSJed Brown       nsize: 2
196c20d7725SJed Brown       output_file: output/ex93_1.out
197c4762a1bSJed Brown 
198c4762a1bSJed Brown    test:
199c4762a1bSJed Brown       suffix: 4
200c4762a1bSJed Brown       nsize: 2
201c20d7725SJed Brown       args: -matptap_via scalable
202c20d7725SJed Brown       output_file: output/ex93_1.out
203c4762a1bSJed Brown 
204c4762a1bSJed Brown    test:
205c4762a1bSJed Brown       suffix: btheap
206c20d7725SJed Brown       args: -matmatmult_via btheap -matmattransmult_via color
207c4762a1bSJed Brown       output_file: output/ex93_1.out
208c4762a1bSJed Brown 
209c4762a1bSJed Brown    test:
210c4762a1bSJed Brown       suffix: heap
211c20d7725SJed Brown       args: -matmatmult_via heap
212c4762a1bSJed Brown       output_file: output/ex93_1.out
213c4762a1bSJed Brown 
214c4762a1bSJed Brown    #HYPRE PtAP is broken for complex numbers
215c4762a1bSJed Brown    test:
216c4762a1bSJed Brown       suffix: hypre
217c4762a1bSJed Brown       nsize: 3
218c4762a1bSJed Brown       requires: hypre !complex
219c20d7725SJed Brown       args: -matmatmult_via hypre -matptap_via hypre -test_hypre
220c20d7725SJed Brown       output_file: output/ex93_hypre.out
221c4762a1bSJed Brown 
222c4762a1bSJed Brown    test:
223c4762a1bSJed Brown       suffix: llcondensed
224c20d7725SJed Brown       args: -matmatmult_via llcondensed
225c4762a1bSJed Brown       output_file: output/ex93_1.out
226c4762a1bSJed Brown 
227c4762a1bSJed Brown    test:
228c4762a1bSJed Brown       suffix: scalable
229c20d7725SJed Brown       args: -matmatmult_via scalable
230c4762a1bSJed Brown       output_file: output/ex93_1.out
231c4762a1bSJed Brown 
232c4762a1bSJed Brown    test:
233c4762a1bSJed Brown       suffix: scalable_fast
234c20d7725SJed Brown       args: -matmatmult_via scalable_fast
235c4762a1bSJed Brown       output_file: output/ex93_1.out
236c4762a1bSJed Brown 
237c4762a1bSJed Brown TEST*/
238