xref: /petsc/src/mat/tests/ex94.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1 
2 static char help[] = "Tests sequential and parallel MatMatMult() and MatPtAP(), MatTransposeMatMult(), sequential MatMatTransposeMult(), MatRARt()\n\
3 Input arguments are:\n\
4   -f0 <input_file> -f1 <input_file> -f2 <input_file> -f3 <input_file> : file to load\n\n";
5 /* Example of usage:
6    ./ex94 -f0 <A_binary> -f1 <B_binary> -matmatmult_mat_view ascii::ascii_info -matmatmulttr_mat_view
7    mpiexec -n 3 ./ex94 -f0 medium -f1 medium -f2 arco1 -f3 arco1 -matmatmult_mat_view
8 */
9 
10 #include <petscmat.h>
11 
12 /*
13      B = A - B
14      norm = norm(B)
15 */
16 PetscErrorCode MatNormDifference(Mat A,Mat B,PetscReal *norm)
17 {
18   PetscErrorCode ierr;
19 
20   PetscFunctionBegin;
21   ierr = MatAXPY(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
22   ierr = MatNorm(B,NORM_FROBENIUS,norm);CHKERRQ(ierr);
23   PetscFunctionReturn(0);
24 }
25 
26 int main(int argc,char **args)
27 {
28   Mat            A,A_save,B,AT,ATT,BT,BTT,P,R,C,C1;
29   Vec            x,v1,v2,v3,v4;
30   PetscViewer    viewer;
31   PetscErrorCode ierr;
32   PetscMPIInt    size,rank;
33   PetscInt       i,m,n,j,*idxn,M,N,nzp,rstart,rend;
34   PetscReal      norm,norm_abs,norm_tmp,fill=4.0;
35   PetscRandom    rdm;
36   char           file[4][128];
37   PetscBool      flg,preload = PETSC_TRUE;
38   PetscScalar    *a,rval,alpha,none = -1.0;
39   PetscBool      Test_MatMatMult=PETSC_TRUE,Test_MatMatTr=PETSC_TRUE,Test_MatPtAP=PETSC_TRUE,Test_MatRARt=PETSC_TRUE,Test_MatMatMatMult=PETSC_TRUE;
40   PetscBool      Test_MatAXPY=PETSC_FALSE,view=PETSC_FALSE;
41   PetscInt       pm,pn,pM,pN;
42   MatInfo        info;
43   PetscBool      seqaij;
44   MatType        mattype;
45   Mat            Cdensetest,Pdense,Cdense,Adense;
46 
47   ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr;
48   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
49   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
50 
51   ierr = PetscOptionsGetReal(NULL,NULL,"-fill",&fill,NULL);CHKERRQ(ierr);
52   ierr = PetscOptionsGetBool(NULL,NULL,"-matops_view",&view,NULL);CHKERRQ(ierr);
53   if (view) {
54     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
55   }
56 
57   /*  Load the matrices A_save and B */
58   ierr = PetscOptionsGetString(NULL,NULL,"-f0",file[0],sizeof(file[0]),&flg);CHKERRQ(ierr);
59   if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Must indicate a file name for small matrix A with the -f0 option.");
60   ierr = PetscOptionsGetString(NULL,NULL,"-f1",file[1],sizeof(file[1]),&flg);CHKERRQ(ierr);
61   if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Must indicate a file name for small matrix B with the -f1 option.");
62   ierr = PetscOptionsGetString(NULL,NULL,"-f2",file[2],sizeof(file[2]),&flg);CHKERRQ(ierr);
63   if (!flg) {
64     preload = PETSC_FALSE;
65   } else {
66     ierr = PetscOptionsGetString(NULL,NULL,"-f3",file[3],128,&flg);CHKERRQ(ierr);
67     if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Must indicate a file name for test matrix B with the -f3 option.");
68   }
69 
70   PetscPreLoadBegin(preload,"Load system");
71   ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[2*PetscPreLoadIt],FILE_MODE_READ,&viewer);CHKERRQ(ierr);
72   ierr = MatCreate(PETSC_COMM_WORLD,&A_save);CHKERRQ(ierr);
73   ierr = MatSetFromOptions(A_save);CHKERRQ(ierr);
74   ierr = MatLoad(A_save,viewer);CHKERRQ(ierr);
75   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
76 
77   ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[2*PetscPreLoadIt+1],FILE_MODE_READ,&viewer);CHKERRQ(ierr);
78   ierr = MatCreate(PETSC_COMM_WORLD,&B);CHKERRQ(ierr);
79   ierr = MatSetFromOptions(B);CHKERRQ(ierr);
80   ierr = MatLoad(B,viewer);CHKERRQ(ierr);
81   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
82 
83   ierr = MatGetType(B,&mattype);CHKERRQ(ierr);
84 
85   ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr);
86   nzp  = PetscMax((PetscInt)(0.1*M),5);
87   ierr = PetscMalloc((nzp+1)*(sizeof(PetscInt)+sizeof(PetscScalar)),&idxn);CHKERRQ(ierr);
88   a    = (PetscScalar*)(idxn + nzp);
89 
90   /* Create vectors v1 and v2 that are compatible with A_save */
91   ierr = VecCreate(PETSC_COMM_WORLD,&v1);CHKERRQ(ierr);
92   ierr = MatGetLocalSize(A_save,&m,NULL);CHKERRQ(ierr);
93   ierr = VecSetSizes(v1,m,PETSC_DECIDE);CHKERRQ(ierr);
94   ierr = VecSetFromOptions(v1);CHKERRQ(ierr);
95   ierr = VecDuplicate(v1,&v2);CHKERRQ(ierr);
96 
97   ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rdm);CHKERRQ(ierr);
98   ierr = PetscRandomSetFromOptions(rdm);CHKERRQ(ierr);
99   ierr = PetscOptionsGetReal(NULL,NULL,"-fill",&fill,NULL);CHKERRQ(ierr);
100 
101   /* Test MatAXPY()    */
102   /*-------------------*/
103   ierr = PetscOptionsHasName(NULL,NULL,"-test_MatAXPY",&Test_MatAXPY);CHKERRQ(ierr);
104   if (Test_MatAXPY) {
105     Mat Btmp;
106     ierr = MatDuplicate(A_save,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
107     ierr = MatDuplicate(B,MAT_COPY_VALUES,&Btmp);CHKERRQ(ierr);
108     ierr = MatAXPY(A,-1.0,B,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); /* A = -B + A_save */
109 
110     ierr = MatScale(A,-1.0);CHKERRQ(ierr); /* A = -A = B - A_save */
111     ierr = MatAXPY(Btmp,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); /* Btmp = -A + B = A_save */
112     ierr = MatMultEqual(A_save,Btmp,10,&flg);CHKERRQ(ierr);
113     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MatAXPY() is incorrect\n");
114     ierr = MatDestroy(&A);CHKERRQ(ierr);
115     ierr = MatDestroy(&Btmp);CHKERRQ(ierr);
116 
117     Test_MatMatMult    = PETSC_FALSE;
118     Test_MatMatTr      = PETSC_FALSE;
119     Test_MatPtAP       = PETSC_FALSE;
120     Test_MatRARt       = PETSC_FALSE;
121     Test_MatMatMatMult = PETSC_FALSE;
122   }
123 
124   /* 1) Test MatMatMult() */
125   /* ---------------------*/
126   if (Test_MatMatMult) {
127     ierr = MatDuplicate(A_save,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
128     ierr = MatCreateTranspose(A,&AT);CHKERRQ(ierr);
129     ierr = MatCreateTranspose(AT,&ATT);CHKERRQ(ierr);
130     ierr = MatCreateTranspose(B,&BT);CHKERRQ(ierr);
131     ierr = MatCreateTranspose(BT,&BTT);CHKERRQ(ierr);
132     ierr = MatMatMult(ATT,B,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
133     ierr = MatMatMultEqual(A,B,C,10,&flg);CHKERRQ(ierr);
134     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error: MatMatMult()\n");
135     ierr = MatDestroy(&C);CHKERRQ(ierr);
136     ierr = MatMatMult(A,BTT,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
137     ierr = MatMatMultEqual(A,B,C,10,&flg);CHKERRQ(ierr);
138     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error: MatMatMult()\n");
139     ierr = MatDestroy(&C);CHKERRQ(ierr);
140     ierr = MatMatMult(ATT,BTT,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
141     ierr = MatMatMultEqual(A,B,C,10,&flg);CHKERRQ(ierr);
142     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error: MatMatMult()\n");
143     ierr = MatDestroy(&C);CHKERRQ(ierr);
144     ierr = MatDestroy(&BTT);CHKERRQ(ierr);
145     ierr = MatDestroy(&BT);CHKERRQ(ierr);
146     ierr = MatDestroy(&ATT);CHKERRQ(ierr);
147     ierr = MatDestroy(&AT);CHKERRQ(ierr);
148     ierr = MatMatMult(A,B,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
149     ierr = MatSetOptionsPrefix(C,"matmatmult_");CHKERRQ(ierr); /* enable option '-matmatmult_' for matrix C */
150     ierr = MatGetInfo(C,MAT_GLOBAL_SUM,&info);CHKERRQ(ierr);
151 
152     /* Test MAT_REUSE_MATRIX - reuse symbolic C */
153     alpha=1.0;
154     for (i=0; i<2; i++) {
155       alpha -=0.1;
156       ierr   = MatScale(A,alpha);CHKERRQ(ierr);
157       ierr   = MatMatMult(A,B,MAT_REUSE_MATRIX,fill,&C);CHKERRQ(ierr);
158     }
159     ierr = MatMatMultEqual(A,B,C,10,&flg);CHKERRQ(ierr);
160     if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error: MatMatMult()\n");
161     ierr = MatDestroy(&A);CHKERRQ(ierr);
162 
163     /* Test MatDuplicate() of C=A*B */
164     ierr = MatDuplicate(C,MAT_COPY_VALUES,&C1);CHKERRQ(ierr);
165     ierr = MatDestroy(&C1);CHKERRQ(ierr);
166     ierr = MatDestroy(&C);CHKERRQ(ierr);
167   } /* if (Test_MatMatMult) */
168 
169   /* 2) Test MatTransposeMatMult() and MatMatTransposeMult() */
170   /* ------------------------------------------------------- */
171   if (Test_MatMatTr) {
172     /* Create P */
173     PetscInt PN,rstart,rend;
174     PN   = M/2;
175     nzp  = 5; /* num of nonzeros in each row of P */
176     ierr = MatCreate(PETSC_COMM_WORLD,&P);CHKERRQ(ierr);
177     ierr = MatSetSizes(P,PETSC_DECIDE,PETSC_DECIDE,M,PN);CHKERRQ(ierr);
178     ierr = MatSetType(P,mattype);CHKERRQ(ierr);
179     ierr = MatSeqAIJSetPreallocation(P,nzp,NULL);CHKERRQ(ierr);
180     ierr = MatMPIAIJSetPreallocation(P,nzp,NULL,nzp,NULL);CHKERRQ(ierr);
181     ierr = MatGetOwnershipRange(P,&rstart,&rend);CHKERRQ(ierr);
182     for (i=0; i<nzp; i++) {
183       ierr = PetscRandomGetValue(rdm,&a[i]);CHKERRQ(ierr);
184     }
185     for (i=rstart; i<rend; i++) {
186       for (j=0; j<nzp; j++) {
187         ierr    = PetscRandomGetValue(rdm,&rval);CHKERRQ(ierr);
188         idxn[j] = (PetscInt)(PetscRealPart(rval)*PN);
189       }
190       ierr = MatSetValues(P,1,&i,nzp,idxn,a,ADD_VALUES);CHKERRQ(ierr);
191     }
192     ierr = MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
193     ierr = MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
194 
195     /* Create R = P^T */
196     ierr = MatTranspose(P,MAT_INITIAL_MATRIX,&R);CHKERRQ(ierr);
197 
198     { /* Test R = P^T, C1 = R*B */
199       ierr = MatMatMult(R,B,MAT_INITIAL_MATRIX,fill,&C1);CHKERRQ(ierr);
200       ierr = MatTranspose(P,MAT_REUSE_MATRIX,&R);CHKERRQ(ierr);
201       ierr = MatMatMult(R,B,MAT_REUSE_MATRIX,fill,&C1);CHKERRQ(ierr);
202       ierr = MatDestroy(&C1);CHKERRQ(ierr);
203     }
204 
205     /* C = P^T*B */
206     ierr = MatTransposeMatMult(P,B,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
207     ierr = MatGetInfo(C,MAT_GLOBAL_SUM,&info);CHKERRQ(ierr);
208 
209     /* Test MAT_REUSE_MATRIX - reuse symbolic C */
210     ierr = MatTransposeMatMult(P,B,MAT_REUSE_MATRIX,fill,&C);CHKERRQ(ierr);
211     if (view) {
212       ierr = PetscPrintf(PETSC_COMM_WORLD,"C = P^T * B:\n");CHKERRQ(ierr);
213       ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
214     }
215     ierr = MatFreeIntermediateDataStructures(C);CHKERRQ(ierr);
216     if (view) {
217       ierr = PetscPrintf(PETSC_COMM_WORLD,"\nC = P^T * B after MatFreeIntermediateDataStructures():\n");CHKERRQ(ierr);
218       ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
219     }
220 
221     /* Compare P^T*B and R*B */
222     ierr = MatMatMult(R,B,MAT_INITIAL_MATRIX,fill,&C1);CHKERRQ(ierr);
223     ierr = MatNormDifference(C,C1,&norm);CHKERRQ(ierr);
224     if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Error in MatTransposeMatMult(): %g\n",(double)norm);
225     ierr = MatDestroy(&C1);CHKERRQ(ierr);
226 
227     /* Test MatDuplicate() of C=P^T*B */
228     ierr = MatDuplicate(C,MAT_COPY_VALUES,&C1);CHKERRQ(ierr);
229     ierr = MatDestroy(&C1);CHKERRQ(ierr);
230     ierr = MatDestroy(&C);CHKERRQ(ierr);
231 
232     /* C = B*R^T */
233     ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
234     if (size == 1 && seqaij) {
235       ierr = MatMatTransposeMult(B,R,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
236       ierr = MatSetOptionsPrefix(C,"matmatmulttr_");CHKERRQ(ierr); /* enable '-matmatmulttr_' for matrix C */
237       ierr = MatGetInfo(C,MAT_GLOBAL_SUM,&info);CHKERRQ(ierr);
238 
239       /* Test MAT_REUSE_MATRIX - reuse symbolic C */
240       ierr = MatMatTransposeMult(B,R,MAT_REUSE_MATRIX,fill,&C);CHKERRQ(ierr);
241 
242       /* Check */
243       ierr = MatMatMult(B,P,MAT_INITIAL_MATRIX,fill,&C1);CHKERRQ(ierr);
244       ierr = MatNormDifference(C,C1,&norm);CHKERRQ(ierr);
245       if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Error in MatMatTransposeMult() %g\n",(double)norm);
246       ierr = MatDestroy(&C1);CHKERRQ(ierr);
247       ierr = MatDestroy(&C);CHKERRQ(ierr);
248     }
249     ierr = MatDestroy(&P);CHKERRQ(ierr);
250     ierr = MatDestroy(&R);CHKERRQ(ierr);
251   }
252 
253   /* 3) Test MatPtAP() */
254   /*-------------------*/
255   if (Test_MatPtAP) {
256     PetscInt  PN;
257     Mat       Cdup;
258 
259     ierr = MatDuplicate(A_save,MAT_COPY_VALUES,&A);CHKERRQ(ierr);
260     ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
261     ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
262 
263     PN   = M/2;
264     nzp  = (PetscInt)(0.1*PN+1); /* num of nozeros in each row of P */
265     ierr = MatCreate(PETSC_COMM_WORLD,&P);CHKERRQ(ierr);
266     ierr = MatSetSizes(P,PETSC_DECIDE,PETSC_DECIDE,N,PN);CHKERRQ(ierr);
267     ierr = MatSetType(P,mattype);CHKERRQ(ierr);
268     ierr = MatSeqAIJSetPreallocation(P,nzp,NULL);CHKERRQ(ierr);
269     ierr = MatMPIAIJSetPreallocation(P,nzp,NULL,nzp,NULL);CHKERRQ(ierr);
270     for (i=0; i<nzp; i++) {
271       ierr = PetscRandomGetValue(rdm,&a[i]);CHKERRQ(ierr);
272     }
273     ierr = MatGetOwnershipRange(P,&rstart,&rend);CHKERRQ(ierr);
274     for (i=rstart; i<rend; i++) {
275       for (j=0; j<nzp; j++) {
276         ierr    = PetscRandomGetValue(rdm,&rval);CHKERRQ(ierr);
277         idxn[j] = (PetscInt)(PetscRealPart(rval)*PN);
278       }
279       ierr = MatSetValues(P,1,&i,nzp,idxn,a,ADD_VALUES);CHKERRQ(ierr);
280     }
281     ierr = MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
282     ierr = MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
283 
284     /* ierr = MatView(P,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */
285     ierr = MatGetSize(P,&pM,&pN);CHKERRQ(ierr);
286     ierr = MatGetLocalSize(P,&pm,&pn);CHKERRQ(ierr);
287     ierr = MatPtAP(A,P,MAT_INITIAL_MATRIX,fill,&C);CHKERRQ(ierr);
288 
289     /* Test MAT_REUSE_MATRIX - reuse symbolic C */
290     alpha=1.0;
291     for (i=0; i<2; i++) {
292       alpha -=0.1;
293       ierr   = MatScale(A,alpha);CHKERRQ(ierr);
294       ierr   = MatPtAP(A,P,MAT_REUSE_MATRIX,fill,&C);CHKERRQ(ierr);
295     }
296 
297     /* Test PtAP ops with P Dense and A either AIJ or SeqDense (it assumes MatPtAP_XAIJ_XAIJ is fine) */
298     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
299     if (seqaij) {
300       ierr = MatConvert(C,MATSEQDENSE,MAT_INITIAL_MATRIX,&Cdensetest);CHKERRQ(ierr);
301       ierr = MatConvert(P,MATSEQDENSE,MAT_INITIAL_MATRIX,&Pdense);CHKERRQ(ierr);
302     } else {
303       ierr = MatConvert(C,MATMPIDENSE,MAT_INITIAL_MATRIX,&Cdensetest);CHKERRQ(ierr);
304       ierr = MatConvert(P,MATMPIDENSE,MAT_INITIAL_MATRIX,&Pdense);CHKERRQ(ierr);
305     }
306 
307     /* test with A AIJ */
308     ierr = MatPtAP(A,Pdense,MAT_INITIAL_MATRIX,fill,&Cdense);CHKERRQ(ierr);
309     ierr = MatAXPY(Cdense,-1.0,Cdensetest,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
310     ierr = MatNorm(Cdense,NORM_FROBENIUS,&norm);CHKERRQ(ierr);
311     if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatPtAP with A SeqAIJ and P SeqDense: %g\n",(double)norm);
312     ierr = MatScale(Cdense,-1.);CHKERRQ(ierr);
313     ierr = MatPtAP(A,Pdense,MAT_REUSE_MATRIX,fill,&Cdense);CHKERRQ(ierr);
314     ierr = MatAXPY(Cdense,-1.0,Cdensetest,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
315     ierr = MatNorm(Cdense,NORM_FROBENIUS,&norm);CHKERRQ(ierr);
316     if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatPtAP with A SeqAIJ and P SeqDense and MAT_REUSE_MATRIX: %g\n",(double)norm);
317     ierr = MatDestroy(&Cdense);CHKERRQ(ierr);
318 
319     /* test with A SeqDense */
320     if (seqaij) {
321       ierr = MatConvert(A,MATSEQDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
322       ierr = MatPtAP(Adense,Pdense,MAT_INITIAL_MATRIX,fill,&Cdense);CHKERRQ(ierr);
323       ierr = MatAXPY(Cdense,-1.0,Cdensetest,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
324       ierr = MatNorm(Cdense,NORM_FROBENIUS,&norm);CHKERRQ(ierr);
325       if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatPtAP with A SeqDense and P SeqDense: %g\n",(double)norm);
326       ierr = MatScale(Cdense,-1.);CHKERRQ(ierr);
327       ierr = MatPtAP(Adense,Pdense,MAT_REUSE_MATRIX,fill,&Cdense);CHKERRQ(ierr);
328       ierr = MatAXPY(Cdense,-1.0,Cdensetest,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
329       ierr = MatNorm(Cdense,NORM_FROBENIUS,&norm);CHKERRQ(ierr);
330       if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatPtAP with A SeqDense and P SeqDense and MAT_REUSE_MATRIX: %g\n",(double)norm);
331       ierr = MatDestroy(&Cdense);CHKERRQ(ierr);
332       ierr = MatDestroy(&Adense);CHKERRQ(ierr);
333     }
334     ierr = MatDestroy(&Cdensetest);CHKERRQ(ierr);
335     ierr = MatDestroy(&Pdense);CHKERRQ(ierr);
336 
337     /* Test MatDuplicate() of C=PtAP and MatView(Cdup,...) */
338     ierr = MatDuplicate(C,MAT_COPY_VALUES,&Cdup);CHKERRQ(ierr);
339     if (view) {
340       ierr = PetscPrintf(PETSC_COMM_WORLD,"\nC = P^T * A * P:\n");CHKERRQ(ierr);
341       ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
342 
343       ierr = MatFreeIntermediateDataStructures(C);CHKERRQ(ierr);
344       ierr = PetscPrintf(PETSC_COMM_WORLD,"\nC = P^T * A * P after MatFreeIntermediateDataStructures():\n");CHKERRQ(ierr);
345       ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
346 
347       ierr = PetscPrintf(PETSC_COMM_WORLD,"\nCdup:\n");CHKERRQ(ierr);
348       ierr = MatView(Cdup,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
349     }
350     ierr = MatDestroy(&Cdup);CHKERRQ(ierr);
351 
352     if (size>1 || !seqaij) Test_MatRARt = PETSC_FALSE;
353     /* 4) Test MatRARt() */
354     /* ----------------- */
355     if (Test_MatRARt) {
356       Mat       R, RARt;
357       ierr = MatTranspose(P,MAT_INITIAL_MATRIX,&R);CHKERRQ(ierr);
358       ierr = MatRARt(A,R,MAT_INITIAL_MATRIX,2.0,&RARt);CHKERRQ(ierr);
359       ierr = MatNormDifference(C,RARt,&norm);CHKERRQ(ierr);
360       if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"|PtAP - RARt| = %g",(double)norm);
361       ierr = MatDestroy(&R);CHKERRQ(ierr);
362       ierr = MatDestroy(&RARt);CHKERRQ(ierr);
363     }
364 
365     if (Test_MatMatMatMult && size == 1) {
366       Mat       R, RAP;
367       ierr = MatTranspose(P,MAT_INITIAL_MATRIX,&R);CHKERRQ(ierr);
368       ierr = MatMatMatMult(R,A,P,MAT_INITIAL_MATRIX,2.0,&RAP);CHKERRQ(ierr);
369       ierr = MatNormDifference(C,RAP,&norm);CHKERRQ(ierr);
370       if (norm > PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PtAP != RAP %g",(double)norm);
371       ierr = MatDestroy(&R);CHKERRQ(ierr);
372       ierr = MatDestroy(&RAP);CHKERRQ(ierr);
373     }
374 
375     /* Create vector x that is compatible with P */
376     ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr);
377     ierr = MatGetLocalSize(P,&m,&n);CHKERRQ(ierr);
378     ierr = VecSetSizes(x,n,PETSC_DECIDE);CHKERRQ(ierr);
379     ierr = VecSetFromOptions(x);CHKERRQ(ierr);
380 
381     ierr = VecCreate(PETSC_COMM_WORLD,&v3);CHKERRQ(ierr);
382     ierr = VecSetSizes(v3,n,PETSC_DECIDE);CHKERRQ(ierr);
383     ierr = VecSetFromOptions(v3);CHKERRQ(ierr);
384     ierr = VecDuplicate(v3,&v4);CHKERRQ(ierr);
385 
386     norm = 0.0;
387     for (i=0; i<10; i++) {
388       ierr = VecSetRandom(x,rdm);CHKERRQ(ierr);
389       ierr = MatMult(P,x,v1);CHKERRQ(ierr);
390       ierr = MatMult(A,v1,v2);CHKERRQ(ierr);  /* v2 = A*P*x */
391 
392       ierr = MatMultTranspose(P,v2,v3);CHKERRQ(ierr); /* v3 = Pt*A*P*x */
393       ierr = MatMult(C,x,v4);CHKERRQ(ierr);           /* v3 = C*x   */
394       ierr = VecNorm(v4,NORM_2,&norm_abs);CHKERRQ(ierr);
395       ierr = VecAXPY(v4,none,v3);CHKERRQ(ierr);
396       ierr = VecNorm(v4,NORM_2,&norm_tmp);CHKERRQ(ierr);
397 
398       norm_tmp /= norm_abs;
399       if (norm_tmp > norm) norm = norm_tmp;
400     }
401     if (norm >= PETSC_SMALL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error: MatPtAP(), |v1 - v2|: %g\n",(double)norm);
402 
403     ierr = MatDestroy(&A);CHKERRQ(ierr);
404     ierr = MatDestroy(&P);CHKERRQ(ierr);
405     ierr = MatDestroy(&C);CHKERRQ(ierr);
406     ierr = VecDestroy(&v3);CHKERRQ(ierr);
407     ierr = VecDestroy(&v4);CHKERRQ(ierr);
408     ierr = VecDestroy(&x);CHKERRQ(ierr);
409   }
410 
411   /* Destroy objects */
412   ierr = VecDestroy(&v1);CHKERRQ(ierr);
413   ierr = VecDestroy(&v2);CHKERRQ(ierr);
414   ierr = PetscRandomDestroy(&rdm);CHKERRQ(ierr);
415   ierr = PetscFree(idxn);CHKERRQ(ierr);
416 
417   ierr = MatDestroy(&A_save);CHKERRQ(ierr);
418   ierr = MatDestroy(&B);CHKERRQ(ierr);
419 
420   PetscPreLoadEnd();
421   PetscFinalize();
422   return ierr;
423 }
424 
425 
426 
427 /*TEST
428 
429    test:
430       suffix: 2_mattransposematmult_matmatmult
431       nsize: 3
432       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
433       args: -f0 ${DATAFILESPATH}/matrices/medium -f1 ${DATAFILESPATH}/matrices/medium -mattransposematmult_via matmatmult> ex94_2.tmp 2>&1
434 
435    test:
436       suffix: 2_mattransposematmult_scalable
437       nsize: 3
438       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
439       args: -f0 ${DATAFILESPATH}/matrices/medium -f1 ${DATAFILESPATH}/matrices/medium -mattransposematmult_via scalable> ex94_2.tmp 2>&1
440       output_file: output/ex94_1.out
441 
442    test:
443       suffix: axpy_mpiaij
444       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
445       nsize: 8
446       args: -f0 ${DATAFILESPATH}/matrices/poisson_2d5p -f1 ${DATAFILESPATH}/matrices/poisson_2d13p -test_MatAXPY
447       output_file: output/ex94_1.out
448 
449    test:
450       suffix: axpy_mpibaij
451       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
452       nsize: 8
453       args: -f0 ${DATAFILESPATH}/matrices/poisson_2d5p -f1 ${DATAFILESPATH}/matrices/poisson_2d13p -test_MatAXPY -mat_type baij
454       output_file: output/ex94_1.out
455 
456    test:
457       suffix: axpy_mpisbaij
458       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
459       nsize: 8
460       args: -f0 ${DATAFILESPATH}/matrices/poisson_2d5p -f1 ${DATAFILESPATH}/matrices/poisson_2d13p -test_MatAXPY -mat_type sbaij
461       output_file: output/ex94_1.out
462 
463    test:
464       suffix: matmatmult
465       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
466       args: -f0 ${DATAFILESPATH}/matrices/arco1 -f1 ${DATAFILESPATH}/matrices/arco1 -viewer_binary_skip_info
467       output_file: output/ex94_1.out
468 
469    test:
470       suffix: matmatmult_2
471       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
472       args: -f0 ${DATAFILESPATH}/matrices/arco1 -f1 ${DATAFILESPATH}/matrices/arco1 -mat_type mpiaij -viewer_binary_skip_info
473       output_file: output/ex94_1.out
474 
475    test:
476       suffix: matmatmult_scalable
477       nsize: 4
478       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
479       args: -f0 ${DATAFILESPATH}/matrices/arco1 -f1 ${DATAFILESPATH}/matrices/arco1 -matmatmult_via scalable
480       output_file: output/ex94_1.out
481 
482    test:
483       suffix: ptap
484       nsize: 3
485       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
486       args: -f0 ${DATAFILESPATH}/matrices/medium -f1 ${DATAFILESPATH}/matrices/medium -matptap_via scalable
487       output_file: output/ex94_1.out
488 
489    test:
490       suffix: rap
491       nsize: 3
492       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
493       args: -f0 ${DATAFILESPATH}/matrices/medium -f1 ${DATAFILESPATH}/matrices/medium
494       output_file: output/ex94_1.out
495 
496    test:
497       suffix: scalable0
498       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
499       args: -f0 ${DATAFILESPATH}/matrices/arco1 -f1 ${DATAFILESPATH}/matrices/arco1 -viewer_binary_skip_info
500       output_file: output/ex94_1.out
501 
502    test:
503       suffix: scalable1
504       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
505       args: -f0 ${DATAFILESPATH}/matrices/arco1 -f1 ${DATAFILESPATH}/matrices/arco1 -viewer_binary_skip_info -matptap_via scalable
506       output_file: output/ex94_1.out
507 
508    test:
509       suffix: view
510       nsize: 2
511       requires: datafilespath !complex double !define(PETSC_USE_64BIT_INDICES)
512       args: -f0 ${DATAFILESPATH}/matrices/tiny -f1 ${DATAFILESPATH}/matrices/tiny -viewer_binary_skip_info -matops_view
513       output_file: output/ex94_2.out
514 
515 TEST*/
516