xref: /petsc/src/mat/tests/ex221.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1 static char help[] = "Tests various routines for MATSHELL\n\n";
2 
3 #include <petscmat.h>
4 
5 typedef struct _n_User *User;
6 struct _n_User {
7   Mat B;
8 };
9 
10 static PetscErrorCode MatGetDiagonal_User(Mat A,Vec X)
11 {
12   User           user;
13   PetscErrorCode ierr;
14 
15   PetscFunctionBegin;
16   ierr = MatShellGetContext(A,&user);CHKERRQ(ierr);
17   ierr = MatGetDiagonal(user->B,X);CHKERRQ(ierr);
18   PetscFunctionReturn(0);
19 }
20 
21 static PetscErrorCode MatMult_User(Mat A,Vec X,Vec Y)
22 {
23   User           user;
24   PetscErrorCode ierr;
25 
26   PetscFunctionBegin;
27   ierr = MatShellGetContext(A,&user);CHKERRQ(ierr);
28   ierr = MatMult(user->B,X,Y);CHKERRQ(ierr);
29   PetscFunctionReturn(0);
30 }
31 
32 static PetscErrorCode MatMultTranspose_User(Mat A,Vec X,Vec Y)
33 {
34   User           user;
35   PetscErrorCode ierr;
36 
37   PetscFunctionBegin;
38   ierr = MatShellGetContext(A,&user);CHKERRQ(ierr);
39   ierr = MatMultTranspose(user->B,X,Y);CHKERRQ(ierr);
40   PetscFunctionReturn(0);
41 }
42 
43 static PetscErrorCode MatCopy_User(Mat A,Mat X,MatStructure str)
44 {
45   User           user,userX;
46   PetscErrorCode ierr;
47 
48   PetscFunctionBegin;
49   ierr = MatShellGetContext(A,&user);CHKERRQ(ierr);
50   ierr = MatShellGetContext(X,&userX);CHKERRQ(ierr);
51   if (user != userX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"This should not happen");
52   ierr = PetscObjectReference((PetscObject)user->B);CHKERRQ(ierr);
53   PetscFunctionReturn(0);
54 }
55 
56 static PetscErrorCode MatDestroy_User(Mat A)
57 {
58   User           user;
59   PetscErrorCode ierr;
60 
61   PetscFunctionBegin;
62   ierr = MatShellGetContext(A,&user);CHKERRQ(ierr);
63   ierr = PetscObjectDereference((PetscObject)user->B);CHKERRQ(ierr);
64   PetscFunctionReturn(0);
65 }
66 
67 int main(int argc,char **args)
68 {
69   User           user;
70   Mat            A,S;
71   PetscScalar    *data,diag = 1.3;
72   PetscReal      tol = PETSC_SMALL;
73   PetscInt       i,j,m = PETSC_DECIDE,n = PETSC_DECIDE,M = 17,N = 15,s1,s2;
74   PetscInt       test, ntest = 2;
75   PetscMPIInt    rank,size;
76   PetscBool      nc = PETSC_FALSE, cong, flg;
77   PetscBool      ronl = PETSC_TRUE;
78   PetscBool      randomize = PETSC_FALSE, submat = PETSC_FALSE;
79   PetscBool      keep = PETSC_FALSE;
80   PetscBool      testzerorows = PETSC_TRUE, testdiagscale = PETSC_TRUE, testgetdiag = PETSC_TRUE, testsubmat = PETSC_TRUE;
81   PetscBool      testshift = PETSC_TRUE, testscale = PETSC_TRUE, testdup = PETSC_TRUE, testreset = PETSC_TRUE;
82   PetscBool      testaxpy = PETSC_TRUE, testaxpyd = PETSC_TRUE, testaxpyerr = PETSC_FALSE;
83   PetscErrorCode ierr;
84 
85   ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr;
86   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
87   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
88   ierr = PetscOptionsGetInt(NULL,NULL,"-M",&M,NULL);CHKERRQ(ierr);
89   ierr = PetscOptionsGetInt(NULL,NULL,"-N",&N,NULL);CHKERRQ(ierr);
90   ierr = PetscOptionsGetInt(NULL,NULL,"-ml",&m,NULL);CHKERRQ(ierr);
91   ierr = PetscOptionsGetInt(NULL,NULL,"-nl",&n,NULL);CHKERRQ(ierr);
92   ierr = PetscOptionsGetBool(NULL,NULL,"-square_nc",&nc,NULL);CHKERRQ(ierr);
93   ierr = PetscOptionsGetBool(NULL,NULL,"-rows_only",&ronl,NULL);CHKERRQ(ierr);
94   ierr = PetscOptionsGetBool(NULL,NULL,"-randomize",&randomize,NULL);CHKERRQ(ierr);
95   ierr = PetscOptionsGetBool(NULL,NULL,"-submat",&submat,NULL);CHKERRQ(ierr);
96   ierr = PetscOptionsGetBool(NULL,NULL,"-test_zerorows",&testzerorows,NULL);CHKERRQ(ierr);
97   ierr = PetscOptionsGetBool(NULL,NULL,"-test_diagscale",&testdiagscale,NULL);CHKERRQ(ierr);
98   ierr = PetscOptionsGetBool(NULL,NULL,"-test_getdiag",&testgetdiag,NULL);CHKERRQ(ierr);
99   ierr = PetscOptionsGetBool(NULL,NULL,"-test_shift",&testshift,NULL);CHKERRQ(ierr);
100   ierr = PetscOptionsGetBool(NULL,NULL,"-test_scale",&testscale,NULL);CHKERRQ(ierr);
101   ierr = PetscOptionsGetBool(NULL,NULL,"-test_dup",&testdup,NULL);CHKERRQ(ierr);
102   ierr = PetscOptionsGetBool(NULL,NULL,"-test_reset",&testreset,NULL);CHKERRQ(ierr);
103   ierr = PetscOptionsGetBool(NULL,NULL,"-test_submat",&testsubmat,NULL);CHKERRQ(ierr);
104   ierr = PetscOptionsGetBool(NULL,NULL,"-test_axpy",&testaxpy,NULL);CHKERRQ(ierr);
105   ierr = PetscOptionsGetBool(NULL,NULL,"-test_axpy_different",&testaxpyd,NULL);CHKERRQ(ierr);
106   ierr = PetscOptionsGetBool(NULL,NULL,"-test_axpy_error",&testaxpyerr,NULL);CHKERRQ(ierr);
107   ierr = PetscOptionsGetInt(NULL,NULL,"-loop",&ntest,NULL);CHKERRQ(ierr);
108   ierr = PetscOptionsGetReal(NULL,NULL,"-tol",&tol,NULL);CHKERRQ(ierr);
109   ierr = PetscOptionsGetScalar(NULL,NULL,"-diag",&diag,NULL);CHKERRQ(ierr);
110   ierr = PetscOptionsGetBool(NULL,NULL,"-keep",&keep,NULL);CHKERRQ(ierr);
111   /* This tests square matrices with different row/col layout */
112   if (nc && size > 1) {
113     M = PetscMax(PetscMax(N,M),1);
114     N = M;
115     m = n = 0;
116     if (rank == 0) { m = M-1; n = 1; }
117     else if (rank == 1) { m = 1; n = N-1; }
118   }
119   ierr = MatCreateDense(PETSC_COMM_WORLD,m,n,M,N,NULL,&A);CHKERRQ(ierr);
120   ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
121   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
122   ierr = MatGetOwnershipRange(A,&s1,NULL);CHKERRQ(ierr);
123   s2   = 1;
124   while (s2 < M) s2 *= 10;
125   ierr = MatDenseGetArray(A,&data);CHKERRQ(ierr);
126   for (j = 0; j < N; j++) {
127     for (i = 0; i < m; i++) {
128       data[j*m + i] = s2*j + i + s1 + 1;
129     }
130   }
131   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
132   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
133 
134   if (submat) {
135     Mat      A2;
136     IS       r,c;
137     PetscInt rst,ren,cst,cen;
138 
139     ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
140     ierr = MatGetOwnershipRangeColumn(A,&cst,&cen);CHKERRQ(ierr);
141     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),(ren-rst)/2,rst,1,&r);CHKERRQ(ierr);
142     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),(cen-cst)/2,cst,1,&c);CHKERRQ(ierr);
143     ierr = MatCreateSubMatrix(A,r,c,MAT_INITIAL_MATRIX,&A2);CHKERRQ(ierr);
144     ierr = ISDestroy(&r);CHKERRQ(ierr);
145     ierr = ISDestroy(&c);CHKERRQ(ierr);
146     ierr = MatDestroy(&A);CHKERRQ(ierr);
147     A = A2;
148   }
149 
150   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
151   ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
152   ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr);
153 
154   ierr = MatConvert(A,MATAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
155   ierr = MatSetOption(A,MAT_KEEP_NONZERO_PATTERN,keep);CHKERRQ(ierr);
156   ierr = PetscObjectSetName((PetscObject)A,"initial");CHKERRQ(ierr);
157   ierr = MatViewFromOptions(A,NULL,"-view_mat");CHKERRQ(ierr);
158 
159   ierr = PetscNew(&user);CHKERRQ(ierr);
160   ierr = MatCreateShell(PETSC_COMM_WORLD,m,n,M,N,user,&S);CHKERRQ(ierr);
161   ierr = MatShellSetOperation(S,MATOP_MULT,(void (*)(void))MatMult_User);CHKERRQ(ierr);
162   ierr = MatShellSetOperation(S,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_User);CHKERRQ(ierr);
163   if (cong) {
164     ierr = MatShellSetOperation(S,MATOP_GET_DIAGONAL,(void (*)(void))MatGetDiagonal_User);CHKERRQ(ierr);
165   }
166   ierr = MatShellSetOperation(S,MATOP_COPY,(void (*)(void))MatCopy_User);CHKERRQ(ierr);
167   ierr = MatShellSetOperation(S,MATOP_DESTROY,(void (*)(void))MatDestroy_User);CHKERRQ(ierr);
168   ierr = MatDuplicate(A,MAT_COPY_VALUES,&user->B);CHKERRQ(ierr);
169 
170   /* Square and rows only scaling */
171   ronl = cong ? ronl : PETSC_TRUE;
172 
173   for (test = 0; test < ntest; test++) {
174     PetscReal err;
175 
176     ierr = MatMultAddEqual(A,S,10,&flg);CHKERRQ(ierr);
177     if (!flg) {
178       ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mult add\n",test);CHKERRQ(ierr);
179     }
180     ierr = MatMultTransposeAddEqual(A,S,10,&flg);CHKERRQ(ierr);
181     if (!flg) {
182       ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mult add (T)\n",test);CHKERRQ(ierr);
183     }
184     if (testzerorows) {
185       Mat       ST,B,C,BT,BTT;
186       IS        zr;
187       Vec       x = NULL, b1 = NULL, b2 = NULL;
188       PetscInt  *idxs = NULL, nr = 0;
189 
190       if (rank == (test%size)) {
191         nr = 1;
192         ierr = PetscMalloc1(nr,&idxs);CHKERRQ(ierr);
193         if (test%2) {
194           idxs[0] = (2*M - 1 - test/2)%M;
195         } else {
196           idxs[0] = (test/2)%M;
197         }
198         idxs[0] = PetscMax(idxs[0],0);
199       }
200       ierr = ISCreateGeneral(PETSC_COMM_WORLD,nr,idxs,PETSC_OWN_POINTER,&zr);CHKERRQ(ierr);
201       ierr = PetscObjectSetName((PetscObject)zr,"ZR");CHKERRQ(ierr);
202       ierr = ISViewFromOptions(zr,NULL,"-view_is");CHKERRQ(ierr);
203       ierr = MatCreateVecs(A,&x,&b1);CHKERRQ(ierr);
204       if (randomize) {
205         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
206         ierr = VecSetRandom(b1,NULL);CHKERRQ(ierr);
207       } else {
208         ierr = VecSet(x,11.4);CHKERRQ(ierr);
209         ierr = VecSet(b1,-14.2);CHKERRQ(ierr);
210       }
211       ierr = VecDuplicate(b1,&b2);CHKERRQ(ierr);
212       ierr = VecCopy(b1,b2);CHKERRQ(ierr);
213       ierr = PetscObjectSetName((PetscObject)b1,"A_B1");CHKERRQ(ierr);
214       ierr = PetscObjectSetName((PetscObject)b2,"A_B2");CHKERRQ(ierr);
215       if (size > 1 && !cong) { /* MATMPIAIJ ZeroRows and ZeroRowsColumns are buggy in this case */
216         ierr = VecDestroy(&b1);CHKERRQ(ierr);
217       }
218       if (ronl) {
219         ierr = MatZeroRowsIS(A,zr,diag,x,b1);CHKERRQ(ierr);
220         ierr = MatZeroRowsIS(S,zr,diag,x,b2);CHKERRQ(ierr);
221       } else {
222         ierr = MatZeroRowsColumnsIS(A,zr,diag,x,b1);CHKERRQ(ierr);
223         ierr = MatZeroRowsColumnsIS(S,zr,diag,x,b2);CHKERRQ(ierr);
224         ierr = ISDestroy(&zr);CHKERRQ(ierr);
225         /* Mix zerorows and zerorowscols */
226         nr   = 0;
227         idxs = NULL;
228         if (!rank) {
229           nr   = 1;
230           ierr = PetscMalloc1(nr,&idxs);CHKERRQ(ierr);
231           if (test%2) {
232             idxs[0] = (3*M - 2 - test/2)%M;
233           } else {
234             idxs[0] = (test/2+1)%M;
235           }
236           idxs[0] = PetscMax(idxs[0],0);
237         }
238         ierr = ISCreateGeneral(PETSC_COMM_WORLD,nr,idxs,PETSC_OWN_POINTER,&zr);CHKERRQ(ierr);
239         ierr = PetscObjectSetName((PetscObject)zr,"ZR2");CHKERRQ(ierr);
240         ierr = ISViewFromOptions(zr,NULL,"-view_is");CHKERRQ(ierr);
241         ierr = MatZeroRowsIS(A,zr,diag*2.0+PETSC_SMALL,NULL,NULL);CHKERRQ(ierr);
242         ierr = MatZeroRowsIS(S,zr,diag*2.0+PETSC_SMALL,NULL,NULL);CHKERRQ(ierr);
243       }
244       ierr = ISDestroy(&zr);CHKERRQ(ierr);
245 
246       if (b1) {
247         Vec b;
248 
249         ierr = VecViewFromOptions(b1,NULL,"-view_b");CHKERRQ(ierr);
250         ierr = VecViewFromOptions(b2,NULL,"-view_b");CHKERRQ(ierr);
251         ierr = VecDuplicate(b1,&b);CHKERRQ(ierr);
252         ierr = VecCopy(b1,b);CHKERRQ(ierr);
253         ierr = VecAXPY(b,-1.0,b2);CHKERRQ(ierr);
254         ierr = VecNorm(b,NORM_INFINITY,&err);CHKERRQ(ierr);
255         if (err >= tol) {
256           ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error b %g\n",test,(double)err);CHKERRQ(ierr);
257         }
258         ierr = VecDestroy(&b);CHKERRQ(ierr);
259       }
260       ierr = VecDestroy(&b1);CHKERRQ(ierr);
261       ierr = VecDestroy(&b2);CHKERRQ(ierr);
262       ierr = VecDestroy(&x);CHKERRQ(ierr);
263       ierr = MatConvert(S,MATDENSE,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
264 
265       ierr = MatCreateTranspose(S,&ST);CHKERRQ(ierr);
266       ierr = MatComputeOperator(ST,MATDENSE,&BT);CHKERRQ(ierr);
267       ierr = MatTranspose(BT,MAT_INITIAL_MATRIX,&BTT);CHKERRQ(ierr);
268       ierr = PetscObjectSetName((PetscObject)B,"S");CHKERRQ(ierr);
269       ierr = PetscObjectSetName((PetscObject)BTT,"STT");CHKERRQ(ierr);
270       ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
271       ierr = PetscObjectSetName((PetscObject)C,"A");CHKERRQ(ierr);
272 
273       ierr = MatViewFromOptions(C,NULL,"-view_mat");CHKERRQ(ierr);
274       ierr = MatViewFromOptions(B,NULL,"-view_mat");CHKERRQ(ierr);
275       ierr = MatViewFromOptions(BTT,NULL,"-view_mat");CHKERRQ(ierr);
276 
277       ierr = MatAXPY(C,-1.0,B,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
278       ierr = MatNorm(C,NORM_FROBENIUS,&err);CHKERRQ(ierr);
279       if (err >= tol) {
280         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mat mult after %s %g\n",test,ronl ? "MatZeroRows" : "MatZeroRowsColumns",(double)err);CHKERRQ(ierr);
281       }
282 
283       ierr = MatConvert(A,MATDENSE,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr);
284       ierr = MatAXPY(C,-1.0,BTT,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
285       ierr = MatNorm(C,NORM_FROBENIUS,&err);CHKERRQ(ierr);
286       if (err >= tol) {
287         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mat mult transpose after %s %g\n",test,ronl ? "MatZeroRows" : "MatZeroRowsColumns",(double)err);CHKERRQ(ierr);
288       }
289 
290       ierr = MatDestroy(&ST);CHKERRQ(ierr);
291       ierr = MatDestroy(&BTT);CHKERRQ(ierr);
292       ierr = MatDestroy(&BT);CHKERRQ(ierr);
293       ierr = MatDestroy(&B);CHKERRQ(ierr);
294       ierr = MatDestroy(&C);CHKERRQ(ierr);
295     }
296     if (testdiagscale) { /* MatDiagonalScale() */
297       Vec vr,vl;
298 
299       ierr = MatCreateVecs(A,&vr,&vl);CHKERRQ(ierr);
300       if (randomize) {
301         ierr = VecSetRandom(vr,NULL);CHKERRQ(ierr);
302         ierr = VecSetRandom(vl,NULL);CHKERRQ(ierr);
303       } else {
304         ierr = VecSet(vr,test%2 ? 0.15 : 1.0/0.15);CHKERRQ(ierr);
305         ierr = VecSet(vl,test%2 ? -1.2 : 1.0/-1.2);CHKERRQ(ierr);
306       }
307       ierr = MatDiagonalScale(A,vl,vr);CHKERRQ(ierr);
308       ierr = MatDiagonalScale(S,vl,vr);CHKERRQ(ierr);
309       ierr = VecDestroy(&vr);CHKERRQ(ierr);
310       ierr = VecDestroy(&vl);CHKERRQ(ierr);
311     }
312 
313     if (testscale) { /* MatScale() */
314       ierr = MatScale(A,test%2 ? 1.4 : 1.0/1.4);CHKERRQ(ierr);
315       ierr = MatScale(S,test%2 ? 1.4 : 1.0/1.4);CHKERRQ(ierr);
316     }
317 
318     if (testshift && cong) { /* MatShift() : MATSHELL shift is broken when row/cols layout are not congruent and left/right scaling have been applied */
319       ierr = MatShift(A,test%2 ? -77.5 : 77.5);CHKERRQ(ierr);
320       ierr = MatShift(S,test%2 ? -77.5 : 77.5);CHKERRQ(ierr);
321     }
322 
323     if (testgetdiag && cong) { /* MatGetDiagonal() */
324       Vec dA,dS;
325 
326       ierr = MatCreateVecs(A,&dA,NULL);CHKERRQ(ierr);
327       ierr = MatCreateVecs(S,&dS,NULL);CHKERRQ(ierr);
328       ierr = MatGetDiagonal(A,dA);CHKERRQ(ierr);
329       ierr = MatGetDiagonal(S,dS);CHKERRQ(ierr);
330       ierr = VecAXPY(dA,-1.0,dS);CHKERRQ(ierr);
331       ierr = VecNorm(dA,NORM_INFINITY,&err);CHKERRQ(ierr);
332       if (err >= tol) {
333         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error diag %g\n",test,(double)err);CHKERRQ(ierr);
334       }
335       ierr = VecDestroy(&dA);CHKERRQ(ierr);
336       ierr = VecDestroy(&dS);CHKERRQ(ierr);
337     }
338 
339     if (testdup && !test) {
340       Mat A2, S2;
341 
342       ierr = MatDuplicate(A,MAT_COPY_VALUES,&A2);CHKERRQ(ierr);
343       ierr = MatDuplicate(S,MAT_COPY_VALUES,&S2);CHKERRQ(ierr);
344       ierr = MatDestroy(&A);CHKERRQ(ierr);
345       ierr = MatDestroy(&S);CHKERRQ(ierr);
346       A = A2;
347       S = S2;
348     }
349 
350     if (testsubmat) {
351       Mat      sA,sS,dA,dS,At,St;
352       IS       r,c;
353       PetscInt rst,ren,cst,cen;
354 
355       ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
356       ierr = MatGetOwnershipRangeColumn(A,&cst,&cen);CHKERRQ(ierr);
357       ierr = ISCreateStride(PetscObjectComm((PetscObject)A),(ren-rst)/2,rst,1,&r);CHKERRQ(ierr);
358       ierr = ISCreateStride(PetscObjectComm((PetscObject)A),(cen-cst)/2,cst,1,&c);CHKERRQ(ierr);
359       ierr = MatCreateSubMatrix(A,r,c,MAT_INITIAL_MATRIX,&sA);CHKERRQ(ierr);
360       ierr = MatCreateSubMatrix(S,r,c,MAT_INITIAL_MATRIX,&sS);CHKERRQ(ierr);
361       ierr = MatMultAddEqual(sA,sS,10,&flg);CHKERRQ(ierr);
362       if (!flg) {
363         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error submatrix mult add\n",test);CHKERRQ(ierr);
364       }
365       ierr = MatMultTransposeAddEqual(sA,sS,10,&flg);CHKERRQ(ierr);
366       if (!flg) {
367         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error submatrix mult add (T)\n",test);CHKERRQ(ierr);
368       }
369       ierr = MatConvert(sA,MATDENSE,MAT_INITIAL_MATRIX,&dA);CHKERRQ(ierr);
370       ierr = MatConvert(sS,MATDENSE,MAT_INITIAL_MATRIX,&dS);CHKERRQ(ierr);
371       ierr = MatAXPY(dA,-1.0,dS,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
372       ierr = MatNorm(dA,NORM_FROBENIUS,&err);CHKERRQ(ierr);
373       if (err >= tol) {
374         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mat submatrix %g\n",test,(double)err);CHKERRQ(ierr);
375       }
376       ierr = MatDestroy(&sA);CHKERRQ(ierr);
377       ierr = MatDestroy(&sS);CHKERRQ(ierr);
378       ierr = MatDestroy(&dA);CHKERRQ(ierr);
379       ierr = MatDestroy(&dS);CHKERRQ(ierr);
380       ierr = MatCreateTranspose(A,&At);CHKERRQ(ierr);
381       ierr = MatCreateTranspose(S,&St);CHKERRQ(ierr);
382       ierr = MatCreateSubMatrix(At,c,r,MAT_INITIAL_MATRIX,&sA);CHKERRQ(ierr);
383       ierr = MatCreateSubMatrix(St,c,r,MAT_INITIAL_MATRIX,&sS);CHKERRQ(ierr);
384       ierr = MatMultAddEqual(sA,sS,10,&flg);CHKERRQ(ierr);
385       if (!flg) {
386         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error submatrix (T) mult add\n",test);CHKERRQ(ierr);
387       }
388       ierr = MatMultTransposeAddEqual(sA,sS,10,&flg);CHKERRQ(ierr);
389       if (!flg) {
390         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error submatrix (T) mult add (T)\n",test);CHKERRQ(ierr);
391       }
392       ierr = MatConvert(sA,MATDENSE,MAT_INITIAL_MATRIX,&dA);CHKERRQ(ierr);
393       ierr = MatConvert(sS,MATDENSE,MAT_INITIAL_MATRIX,&dS);CHKERRQ(ierr);
394       ierr = MatAXPY(dA,-1.0,dS,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
395       ierr = MatNorm(dA,NORM_FROBENIUS,&err);CHKERRQ(ierr);
396       if (err >= tol) {
397         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mat submatrix (T) %g\n",test,(double)err);CHKERRQ(ierr);
398       }
399       ierr = MatDestroy(&sA);CHKERRQ(ierr);
400       ierr = MatDestroy(&sS);CHKERRQ(ierr);
401       ierr = MatDestroy(&dA);CHKERRQ(ierr);
402       ierr = MatDestroy(&dS);CHKERRQ(ierr);
403       ierr = MatDestroy(&At);CHKERRQ(ierr);
404       ierr = MatDestroy(&St);CHKERRQ(ierr);
405       ierr = ISDestroy(&r);CHKERRQ(ierr);
406       ierr = ISDestroy(&c);CHKERRQ(ierr);
407     }
408 
409     if (testaxpy) {
410       Mat          tA,tS,dA,dS;
411       MatStructure str[3] = { SAME_NONZERO_PATTERN, SUBSET_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN };
412 
413       ierr = MatDuplicate(A,MAT_COPY_VALUES,&tA);CHKERRQ(ierr);
414       if (testaxpyd && !(test%2)) {
415         ierr = PetscObjectReference((PetscObject)tA);CHKERRQ(ierr);
416         tS   = tA;
417       } else {
418         ierr = PetscObjectReference((PetscObject)S);CHKERRQ(ierr);
419         tS   = S;
420       }
421       ierr = MatAXPY(A,0.5,tA,str[test%3]);CHKERRQ(ierr);
422       ierr = MatAXPY(S,0.5,tS,str[test%3]);CHKERRQ(ierr);
423       /* this will trigger an error the next MatMult or MatMultTranspose call for S */
424       if (testaxpyerr) { ierr = MatScale(tA,0);CHKERRQ(ierr); }
425       ierr = MatDestroy(&tA);CHKERRQ(ierr);
426       ierr = MatDestroy(&tS);CHKERRQ(ierr);
427       ierr = MatMultAddEqual(A,S,10,&flg);CHKERRQ(ierr);
428       if (!flg) {
429         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error axpy mult add\n",test);CHKERRQ(ierr);
430       }
431       ierr = MatMultTransposeAddEqual(A,S,10,&flg);CHKERRQ(ierr);
432       if (!flg) {
433         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error axpy mult add (T)\n",test);CHKERRQ(ierr);
434       }
435       ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&dA);CHKERRQ(ierr);
436       ierr = MatConvert(S,MATDENSE,MAT_INITIAL_MATRIX,&dS);CHKERRQ(ierr);
437       ierr = MatAXPY(dA,-1.0,dS,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
438       ierr = MatNorm(dA,NORM_FROBENIUS,&err);CHKERRQ(ierr);
439       if (err >= tol) {
440         ierr = PetscPrintf(PETSC_COMM_WORLD,"[test %D] Error mat submatrix %g\n",test,(double)err);CHKERRQ(ierr);
441       }
442       ierr = MatDestroy(&dA);CHKERRQ(ierr);
443       ierr = MatDestroy(&dS);CHKERRQ(ierr);
444     }
445 
446     if (testreset && (ntest == 1 || test == ntest-2)) {
447       /* reset MATSHELL */
448       ierr = MatAssemblyBegin(S,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
449       ierr = MatAssemblyEnd(S,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
450       /* reset A */
451       ierr = MatCopy(user->B,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
452     }
453   }
454 
455   ierr = MatDestroy(&A);CHKERRQ(ierr);
456   ierr = MatDestroy(&S);CHKERRQ(ierr);
457   ierr = PetscFree(user);CHKERRQ(ierr);
458   ierr = PetscFinalize();
459   return ierr;
460 }
461 
462 
463 /*TEST
464 
465    testset:
466      suffix: rect
467      requires: !single
468      output_file: output/ex221_1.out
469      nsize: {{1 3}}
470      args: -loop 3 -keep {{0 1}} -M {{12 19}} -N {{19 12}} -submat {{0 1}} -test_axpy_different {{0 1}}
471 
472    testset:
473      suffix: square
474      requires: !single
475      output_file: output/ex221_1.out
476      nsize: {{1 3}}
477      args: -M 21 -N 21 -loop 4 -rows_only {{0 1}} -keep {{0 1}} -submat {{0 1}} -test_axpy_different {{0 1}}
478 TEST*/
479