xref: /petsc/src/mat/utils/multequal.c (revision 7d3de750dec08ee2edc7d15bcef3046c0443ab7d)
186a22c91SHong Zhang 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>  /*I   "petscmat.h"  I*/
386a22c91SHong Zhang 
4e573050aSPierre Jolivet static PetscErrorCode MatMultEqual_Private(Mat A,Mat B,PetscInt n,PetscBool *flg,PetscInt t,PetscBool add)
5447fed29SStefano Zampini {
6447fed29SStefano Zampini   PetscErrorCode ierr;
7b84f494bSStefano Zampini   Vec            Ax = NULL,Bx = NULL,s1 = NULL,s2 = NULL,Ay = NULL, By = NULL;
8447fed29SStefano Zampini   PetscRandom    rctx;
9447fed29SStefano Zampini   PetscReal      r1,r2,tol=PETSC_SQRT_MACHINE_EPSILON;
10447fed29SStefano Zampini   PetscInt       am,an,bm,bn,k;
11447fed29SStefano Zampini   PetscScalar    none = -1.0;
12e573050aSPierre Jolivet   const char*    sops[] = {"MatMult","MatMultAdd","MatMultTranspose","MatMultTransposeAdd","MatMultHermitianTranspose","MatMultHermitianTranposeAdd"};
13447fed29SStefano Zampini   const char*    sop;
14447fed29SStefano Zampini 
15447fed29SStefano Zampini   PetscFunctionBegin;
16447fed29SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
17447fed29SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
18447fed29SStefano Zampini   PetscCheckSameComm(A,1,B,2);
19447fed29SStefano Zampini   PetscValidLogicalCollectiveInt(A,n,3);
20447fed29SStefano Zampini   PetscValidPointer(flg,4);
21e573050aSPierre Jolivet   PetscValidLogicalCollectiveInt(A,t,5);
22447fed29SStefano Zampini   PetscValidLogicalCollectiveBool(A,add,6);
23447fed29SStefano Zampini   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
24447fed29SStefano Zampini   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
2598921bdaSJacob Faibussowitsch   if (PetscUnlikely(am != bm || an != bn)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT,am,bm,an,bn);
26e573050aSPierre Jolivet   sop  = sops[(add ? 1 : 0) + 2 * t]; /* t = 0 => no transpose, t = 1 => transpose, t = 2 => Hermitian transpose */
27447fed29SStefano Zampini   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)A),&rctx);CHKERRQ(ierr);
28447fed29SStefano Zampini   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
29447fed29SStefano Zampini   if (t) {
30447fed29SStefano Zampini     ierr = MatCreateVecs(A,&s1,&Ax);CHKERRQ(ierr);
31447fed29SStefano Zampini     ierr = MatCreateVecs(B,&s2,&Bx);CHKERRQ(ierr);
32447fed29SStefano Zampini   } else {
33447fed29SStefano Zampini     ierr = MatCreateVecs(A,&Ax,&s1);CHKERRQ(ierr);
34447fed29SStefano Zampini     ierr = MatCreateVecs(B,&Bx,&s2);CHKERRQ(ierr);
35447fed29SStefano Zampini   }
36447fed29SStefano Zampini   if (add) {
37447fed29SStefano Zampini     ierr = VecDuplicate(s1,&Ay);CHKERRQ(ierr);
38447fed29SStefano Zampini     ierr = VecDuplicate(s2,&By);CHKERRQ(ierr);
39447fed29SStefano Zampini   }
40447fed29SStefano Zampini 
41447fed29SStefano Zampini   *flg = PETSC_TRUE;
42447fed29SStefano Zampini   for (k=0; k<n; k++) {
43447fed29SStefano Zampini     ierr = VecSetRandom(Ax,rctx);CHKERRQ(ierr);
44447fed29SStefano Zampini     ierr = VecCopy(Ax,Bx);CHKERRQ(ierr);
45447fed29SStefano Zampini     if (add) {
46447fed29SStefano Zampini       ierr = VecSetRandom(Ay,rctx);CHKERRQ(ierr);
47447fed29SStefano Zampini       ierr = VecCopy(Ay,By);CHKERRQ(ierr);
48447fed29SStefano Zampini     }
49e573050aSPierre Jolivet     if (t == 1) {
50447fed29SStefano Zampini       if (add) {
51447fed29SStefano Zampini         ierr = MatMultTransposeAdd(A,Ax,Ay,s1);CHKERRQ(ierr);
52447fed29SStefano Zampini         ierr = MatMultTransposeAdd(B,Bx,By,s2);CHKERRQ(ierr);
53447fed29SStefano Zampini       } else {
54447fed29SStefano Zampini         ierr = MatMultTranspose(A,Ax,s1);CHKERRQ(ierr);
55447fed29SStefano Zampini         ierr = MatMultTranspose(B,Bx,s2);CHKERRQ(ierr);
56447fed29SStefano Zampini       }
57e573050aSPierre Jolivet     } else if (t == 2) {
58e573050aSPierre Jolivet       if (add) {
59e573050aSPierre Jolivet         ierr = MatMultHermitianTransposeAdd(A,Ax,Ay,s1);CHKERRQ(ierr);
60e573050aSPierre Jolivet         ierr = MatMultHermitianTransposeAdd(B,Bx,By,s2);CHKERRQ(ierr);
61e573050aSPierre Jolivet       } else {
62e573050aSPierre Jolivet         ierr = MatMultHermitianTranspose(A,Ax,s1);CHKERRQ(ierr);
63e573050aSPierre Jolivet         ierr = MatMultHermitianTranspose(B,Bx,s2);CHKERRQ(ierr);
64e573050aSPierre Jolivet       }
65447fed29SStefano Zampini     } else {
66447fed29SStefano Zampini       if (add) {
67447fed29SStefano Zampini         ierr = MatMultAdd(A,Ax,Ay,s1);CHKERRQ(ierr);
68447fed29SStefano Zampini         ierr = MatMultAdd(B,Bx,By,s2);CHKERRQ(ierr);
69447fed29SStefano Zampini       } else {
70447fed29SStefano Zampini         ierr = MatMult(A,Ax,s1);CHKERRQ(ierr);
71447fed29SStefano Zampini         ierr = MatMult(B,Bx,s2);CHKERRQ(ierr);
72447fed29SStefano Zampini       }
73447fed29SStefano Zampini     }
74447fed29SStefano Zampini     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
75447fed29SStefano Zampini     if (r2 < tol) {
76447fed29SStefano Zampini       ierr = VecNorm(s1,NORM_INFINITY,&r1);CHKERRQ(ierr);
77447fed29SStefano Zampini     } else {
78447fed29SStefano Zampini       ierr = VecAXPY(s2,none,s1);CHKERRQ(ierr);
79447fed29SStefano Zampini       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
80447fed29SStefano Zampini       r1  /= r2;
81447fed29SStefano Zampini     }
82447fed29SStefano Zampini     if (r1 > tol) {
83447fed29SStefano Zampini       *flg = PETSC_FALSE;
84*7d3de750SJacob Faibussowitsch       ierr = PetscInfo(A,"Error: %" PetscInt_FMT "-th %s() %g\n",k,sop,(double)r1);CHKERRQ(ierr);
85447fed29SStefano Zampini       break;
86447fed29SStefano Zampini     }
87447fed29SStefano Zampini   }
88447fed29SStefano Zampini   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
89447fed29SStefano Zampini   ierr = VecDestroy(&Ax);CHKERRQ(ierr);
90447fed29SStefano Zampini   ierr = VecDestroy(&Bx);CHKERRQ(ierr);
91447fed29SStefano Zampini   ierr = VecDestroy(&Ay);CHKERRQ(ierr);
92447fed29SStefano Zampini   ierr = VecDestroy(&By);CHKERRQ(ierr);
93447fed29SStefano Zampini   ierr = VecDestroy(&s1);CHKERRQ(ierr);
94447fed29SStefano Zampini   ierr = VecDestroy(&s2);CHKERRQ(ierr);
95447fed29SStefano Zampini   PetscFunctionReturn(0);
96447fed29SStefano Zampini }
97447fed29SStefano Zampini 
98447fed29SStefano Zampini static PetscErrorCode MatMatMultEqual_Private(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg,PetscBool At,PetscBool Bt)
99447fed29SStefano Zampini {
100447fed29SStefano Zampini   PetscErrorCode ierr;
101447fed29SStefano Zampini   Vec            Ax,Bx,Cx,s1,s2,s3;
102447fed29SStefano Zampini   PetscRandom    rctx;
103447fed29SStefano Zampini   PetscReal      r1,r2,tol=PETSC_SQRT_MACHINE_EPSILON;
104447fed29SStefano Zampini   PetscInt       am,an,bm,bn,cm,cn,k;
105447fed29SStefano Zampini   PetscScalar    none = -1.0;
106447fed29SStefano Zampini   const char*    sops[] = {"MatMatMult","MatTransposeMatMult","MatMatTransposeMult","MatTransposeMatTranposeMult"};
107447fed29SStefano Zampini   const char*    sop;
108447fed29SStefano Zampini 
109447fed29SStefano Zampini   PetscFunctionBegin;
110447fed29SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
111447fed29SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
112447fed29SStefano Zampini   PetscCheckSameComm(A,1,B,2);
113447fed29SStefano Zampini   PetscValidHeaderSpecific(C,MAT_CLASSID,3);
114447fed29SStefano Zampini   PetscCheckSameComm(A,1,C,3);
115447fed29SStefano Zampini   PetscValidLogicalCollectiveInt(A,n,4);
116447fed29SStefano Zampini   PetscValidPointer(flg,5);
117447fed29SStefano Zampini   PetscValidLogicalCollectiveBool(A,At,6);
118447fed29SStefano Zampini   PetscValidLogicalCollectiveBool(B,Bt,7);
119447fed29SStefano Zampini   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
120447fed29SStefano Zampini   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
121447fed29SStefano Zampini   ierr = MatGetLocalSize(C,&cm,&cn);CHKERRQ(ierr);
122447fed29SStefano Zampini   if (At) { PetscInt tt = an; an = am; am = tt; };
123447fed29SStefano Zampini   if (Bt) { PetscInt tt = bn; bn = bm; bm = tt; };
12498921bdaSJacob Faibussowitsch   if (PetscUnlikely(an != bm || am != cm || bn != cn)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A, B, C local dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT,am,an,bm,bn,cm,cn);
125447fed29SStefano Zampini 
126447fed29SStefano Zampini   sop  = sops[(At ? 1 : 0) + 2 * (Bt ? 1 : 0)];
127447fed29SStefano Zampini   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)C),&rctx);CHKERRQ(ierr);
128447fed29SStefano Zampini   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
129447fed29SStefano Zampini   if (Bt) {
130447fed29SStefano Zampini     ierr = MatCreateVecs(B,&s1,&Bx);CHKERRQ(ierr);
131447fed29SStefano Zampini   } else {
132447fed29SStefano Zampini     ierr = MatCreateVecs(B,&Bx,&s1);CHKERRQ(ierr);
133447fed29SStefano Zampini   }
134447fed29SStefano Zampini   if (At) {
135447fed29SStefano Zampini     ierr = MatCreateVecs(A,&s2,&Ax);CHKERRQ(ierr);
136447fed29SStefano Zampini   } else {
137447fed29SStefano Zampini     ierr = MatCreateVecs(A,&Ax,&s2);CHKERRQ(ierr);
138447fed29SStefano Zampini   }
139447fed29SStefano Zampini   ierr = MatCreateVecs(C,&Cx,&s3);CHKERRQ(ierr);
140447fed29SStefano Zampini 
141447fed29SStefano Zampini   *flg = PETSC_TRUE;
142447fed29SStefano Zampini   for (k=0; k<n; k++) {
143447fed29SStefano Zampini     ierr = VecSetRandom(Bx,rctx);CHKERRQ(ierr);
144447fed29SStefano Zampini     if (Bt) {
145447fed29SStefano Zampini       ierr = MatMultTranspose(B,Bx,s1);CHKERRQ(ierr);
146447fed29SStefano Zampini     } else {
147447fed29SStefano Zampini       ierr = MatMult(B,Bx,s1);CHKERRQ(ierr);
148447fed29SStefano Zampini     }
149447fed29SStefano Zampini     ierr = VecCopy(s1,Ax);CHKERRQ(ierr);
150447fed29SStefano Zampini     if (At) {
151447fed29SStefano Zampini       ierr = MatMultTranspose(A,Ax,s2);CHKERRQ(ierr);
152447fed29SStefano Zampini     } else {
153447fed29SStefano Zampini       ierr = MatMult(A,Ax,s2);CHKERRQ(ierr);
154447fed29SStefano Zampini     }
155447fed29SStefano Zampini     ierr = VecCopy(Bx,Cx);CHKERRQ(ierr);
156447fed29SStefano Zampini     ierr = MatMult(C,Cx,s3);CHKERRQ(ierr);
157447fed29SStefano Zampini 
158447fed29SStefano Zampini     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
159447fed29SStefano Zampini     if (r2 < tol) {
160447fed29SStefano Zampini       ierr = VecNorm(s3,NORM_INFINITY,&r1);CHKERRQ(ierr);
161447fed29SStefano Zampini     } else {
162447fed29SStefano Zampini       ierr = VecAXPY(s2,none,s3);CHKERRQ(ierr);
163447fed29SStefano Zampini       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
164447fed29SStefano Zampini       r1  /= r2;
165447fed29SStefano Zampini     }
166447fed29SStefano Zampini     if (r1 > tol) {
167447fed29SStefano Zampini       *flg = PETSC_FALSE;
168*7d3de750SJacob Faibussowitsch       ierr = PetscInfo(A,"Error: %" PetscInt_FMT "-th %s %g\n",k,sop,(double)r1);CHKERRQ(ierr);
169447fed29SStefano Zampini       break;
170447fed29SStefano Zampini     }
171447fed29SStefano Zampini   }
172447fed29SStefano Zampini   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
173447fed29SStefano Zampini   ierr = VecDestroy(&Ax);CHKERRQ(ierr);
174447fed29SStefano Zampini   ierr = VecDestroy(&Bx);CHKERRQ(ierr);
175447fed29SStefano Zampini   ierr = VecDestroy(&Cx);CHKERRQ(ierr);
176447fed29SStefano Zampini   ierr = VecDestroy(&s1);CHKERRQ(ierr);
177447fed29SStefano Zampini   ierr = VecDestroy(&s2);CHKERRQ(ierr);
178447fed29SStefano Zampini   ierr = VecDestroy(&s3);CHKERRQ(ierr);
179447fed29SStefano Zampini   PetscFunctionReturn(0);
180447fed29SStefano Zampini }
181447fed29SStefano Zampini 
18286a22c91SHong Zhang /*@
18386a22c91SHong Zhang    MatMultEqual - Compares matrix-vector products of two matrices.
18486a22c91SHong Zhang 
18586a22c91SHong Zhang    Collective on Mat
18686a22c91SHong Zhang 
18786a22c91SHong Zhang    Input Parameters:
18886a22c91SHong Zhang +  A - the first matrix
1894222ddf1SHong Zhang .  B - the second matrix
19086a22c91SHong Zhang -  n - number of random vectors to be tested
19186a22c91SHong Zhang 
19286a22c91SHong Zhang    Output Parameter:
19386a22c91SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
19486a22c91SHong Zhang 
19586a22c91SHong Zhang    Level: intermediate
19686a22c91SHong Zhang 
19786a22c91SHong Zhang @*/
1987087cfbeSBarry Smith PetscErrorCode MatMultEqual(Mat A,Mat B,PetscInt n,PetscBool *flg)
19986a22c91SHong Zhang {
20086a22c91SHong Zhang   PetscErrorCode ierr;
20186a22c91SHong Zhang 
20286a22c91SHong Zhang   PetscFunctionBegin;
203e573050aSPierre Jolivet   ierr = MatMultEqual_Private(A,B,n,flg,0,PETSC_FALSE);CHKERRQ(ierr);
20486a22c91SHong Zhang   PetscFunctionReturn(0);
20586a22c91SHong Zhang }
20686a22c91SHong Zhang 
20786a22c91SHong Zhang /*@
20886a22c91SHong Zhang    MatMultAddEqual - Compares matrix-vector products of two matrices.
20986a22c91SHong Zhang 
21086a22c91SHong Zhang    Collective on Mat
21186a22c91SHong Zhang 
21286a22c91SHong Zhang    Input Parameters:
21386a22c91SHong Zhang +  A - the first matrix
2144222ddf1SHong Zhang .  B - the second matrix
21586a22c91SHong Zhang -  n - number of random vectors to be tested
21686a22c91SHong Zhang 
21786a22c91SHong Zhang    Output Parameter:
21886a22c91SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
21986a22c91SHong Zhang 
22086a22c91SHong Zhang    Level: intermediate
22186a22c91SHong Zhang 
22286a22c91SHong Zhang @*/
2237087cfbeSBarry Smith PetscErrorCode  MatMultAddEqual(Mat A,Mat B,PetscInt n,PetscBool *flg)
22486a22c91SHong Zhang {
22586a22c91SHong Zhang   PetscErrorCode ierr;
22686a22c91SHong Zhang 
22786a22c91SHong Zhang   PetscFunctionBegin;
228e573050aSPierre Jolivet   ierr = MatMultEqual_Private(A,B,n,flg,0,PETSC_TRUE);CHKERRQ(ierr);
22963879571SHong Zhang   PetscFunctionReturn(0);
23063879571SHong Zhang }
23163879571SHong Zhang 
23263879571SHong Zhang /*@
23363879571SHong Zhang    MatMultTransposeEqual - Compares matrix-vector products of two matrices.
23463879571SHong Zhang 
23563879571SHong Zhang    Collective on Mat
23663879571SHong Zhang 
23763879571SHong Zhang    Input Parameters:
23863879571SHong Zhang +  A - the first matrix
2394222ddf1SHong Zhang .  B - the second matrix
24063879571SHong Zhang -  n - number of random vectors to be tested
24163879571SHong Zhang 
24263879571SHong Zhang    Output Parameter:
24363879571SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
24463879571SHong Zhang 
24563879571SHong Zhang    Level: intermediate
24663879571SHong Zhang 
24763879571SHong Zhang @*/
2487087cfbeSBarry Smith PetscErrorCode  MatMultTransposeEqual(Mat A,Mat B,PetscInt n,PetscBool *flg)
24963879571SHong Zhang {
25063879571SHong Zhang   PetscErrorCode ierr;
25163879571SHong Zhang 
25263879571SHong Zhang   PetscFunctionBegin;
253e573050aSPierre Jolivet   ierr = MatMultEqual_Private(A,B,n,flg,1,PETSC_FALSE);CHKERRQ(ierr);
25463879571SHong Zhang   PetscFunctionReturn(0);
25563879571SHong Zhang }
25663879571SHong Zhang 
25763879571SHong Zhang /*@
25863879571SHong Zhang    MatMultTransposeAddEqual - Compares matrix-vector products of two matrices.
25963879571SHong Zhang 
26063879571SHong Zhang    Collective on Mat
26163879571SHong Zhang 
26263879571SHong Zhang    Input Parameters:
26363879571SHong Zhang +  A - the first matrix
2644222ddf1SHong Zhang .  B - the second matrix
26563879571SHong Zhang -  n - number of random vectors to be tested
26663879571SHong Zhang 
26763879571SHong Zhang    Output Parameter:
26863879571SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
26963879571SHong Zhang 
27063879571SHong Zhang    Level: intermediate
27163879571SHong Zhang 
27263879571SHong Zhang @*/
2737087cfbeSBarry Smith PetscErrorCode  MatMultTransposeAddEqual(Mat A,Mat B,PetscInt n,PetscBool *flg)
27463879571SHong Zhang {
27563879571SHong Zhang   PetscErrorCode ierr;
27663879571SHong Zhang 
27763879571SHong Zhang   PetscFunctionBegin;
278e573050aSPierre Jolivet   ierr = MatMultEqual_Private(A,B,n,flg,1,PETSC_TRUE);CHKERRQ(ierr);
279e573050aSPierre Jolivet   PetscFunctionReturn(0);
280e573050aSPierre Jolivet }
281e573050aSPierre Jolivet 
282e573050aSPierre Jolivet /*@
283e573050aSPierre Jolivet    MatMultHermitianTransposeEqual - Compares matrix-vector products of two matrices.
284e573050aSPierre Jolivet 
285e573050aSPierre Jolivet    Collective on Mat
286e573050aSPierre Jolivet 
287e573050aSPierre Jolivet    Input Parameters:
288e573050aSPierre Jolivet +  A - the first matrix
289e573050aSPierre Jolivet .  B - the second matrix
290e573050aSPierre Jolivet -  n - number of random vectors to be tested
291e573050aSPierre Jolivet 
292e573050aSPierre Jolivet    Output Parameter:
293e573050aSPierre Jolivet .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
294e573050aSPierre Jolivet 
295e573050aSPierre Jolivet    Level: intermediate
296e573050aSPierre Jolivet 
297e573050aSPierre Jolivet @*/
298e573050aSPierre Jolivet PetscErrorCode  MatMultHermitianTransposeEqual(Mat A,Mat B,PetscInt n,PetscBool *flg)
299e573050aSPierre Jolivet {
300e573050aSPierre Jolivet   PetscErrorCode ierr;
301e573050aSPierre Jolivet 
302e573050aSPierre Jolivet   PetscFunctionBegin;
303e573050aSPierre Jolivet   ierr = MatMultEqual_Private(A,B,n,flg,2,PETSC_FALSE);CHKERRQ(ierr);
304e573050aSPierre Jolivet   PetscFunctionReturn(0);
305e573050aSPierre Jolivet }
306e573050aSPierre Jolivet 
307e573050aSPierre Jolivet /*@
308e573050aSPierre Jolivet    MatMultHermitianTransposeAddEqual - Compares matrix-vector products of two matrices.
309e573050aSPierre Jolivet 
310e573050aSPierre Jolivet    Collective on Mat
311e573050aSPierre Jolivet 
312e573050aSPierre Jolivet    Input Parameters:
313e573050aSPierre Jolivet +  A - the first matrix
314e573050aSPierre Jolivet .  B - the second matrix
315e573050aSPierre Jolivet -  n - number of random vectors to be tested
316e573050aSPierre Jolivet 
317e573050aSPierre Jolivet    Output Parameter:
318e573050aSPierre Jolivet .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
319e573050aSPierre Jolivet 
320e573050aSPierre Jolivet    Level: intermediate
321e573050aSPierre Jolivet 
322e573050aSPierre Jolivet @*/
323e573050aSPierre Jolivet PetscErrorCode  MatMultHermitianTransposeAddEqual(Mat A,Mat B,PetscInt n,PetscBool *flg)
324e573050aSPierre Jolivet {
325e573050aSPierre Jolivet   PetscErrorCode ierr;
326e573050aSPierre Jolivet 
327e573050aSPierre Jolivet   PetscFunctionBegin;
328e573050aSPierre Jolivet   ierr = MatMultEqual_Private(A,B,n,flg,2,PETSC_TRUE);CHKERRQ(ierr);
32986a22c91SHong Zhang   PetscFunctionReturn(0);
33086a22c91SHong Zhang }
331a52676ecSHong Zhang 
332a52676ecSHong Zhang /*@
333a52676ecSHong Zhang    MatMatMultEqual - Test A*B*x = C*x for n random vector x
334a52676ecSHong Zhang 
335a52676ecSHong Zhang    Collective on Mat
336a52676ecSHong Zhang 
337a52676ecSHong Zhang    Input Parameters:
338a52676ecSHong Zhang +  A - the first matrix
339c2916339SPierre Jolivet .  B - the second matrix
340c2916339SPierre Jolivet .  C - the third matrix
341a52676ecSHong Zhang -  n - number of random vectors to be tested
342a52676ecSHong Zhang 
343a52676ecSHong Zhang    Output Parameter:
344f0fc11ceSJed Brown .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
345a52676ecSHong Zhang 
346a52676ecSHong Zhang    Level: intermediate
347a52676ecSHong Zhang 
348a52676ecSHong Zhang @*/
349a52676ecSHong Zhang PetscErrorCode MatMatMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
350a52676ecSHong Zhang {
351a52676ecSHong Zhang   PetscErrorCode ierr;
352a52676ecSHong Zhang 
353a52676ecSHong Zhang   PetscFunctionBegin;
354447fed29SStefano Zampini   ierr = MatMatMultEqual_Private(A,B,C,n,flg,PETSC_FALSE,PETSC_FALSE);CHKERRQ(ierr);
355a52676ecSHong Zhang   PetscFunctionReturn(0);
356a52676ecSHong Zhang }
357a52676ecSHong Zhang 
358a52676ecSHong Zhang /*@
359a52676ecSHong Zhang    MatTransposeMatMultEqual - Test A^T*B*x = C*x for n random vector x
360a52676ecSHong Zhang 
361a52676ecSHong Zhang    Collective on Mat
362a52676ecSHong Zhang 
363a52676ecSHong Zhang    Input Parameters:
364a52676ecSHong Zhang +  A - the first matrix
3654222ddf1SHong Zhang .  B - the second matrix
3664222ddf1SHong Zhang .  C - the third matrix
367a52676ecSHong Zhang -  n - number of random vectors to be tested
368a52676ecSHong Zhang 
369a52676ecSHong Zhang    Output Parameter:
370a52676ecSHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
371a52676ecSHong Zhang 
372a52676ecSHong Zhang    Level: intermediate
373a52676ecSHong Zhang 
374a52676ecSHong Zhang @*/
375a52676ecSHong Zhang PetscErrorCode MatTransposeMatMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
376a52676ecSHong Zhang {
377a52676ecSHong Zhang   PetscErrorCode ierr;
378a52676ecSHong Zhang 
379a52676ecSHong Zhang   PetscFunctionBegin;
380447fed29SStefano Zampini   ierr = MatMatMultEqual_Private(A,B,C,n,flg,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
381a52676ecSHong Zhang   PetscFunctionReturn(0);
382a52676ecSHong Zhang }
38386919fd6SHong Zhang 
38426546c1bSToby Isaac /*@
38526546c1bSToby Isaac    MatMatTransposeMultEqual - Test A*B^T*x = C*x for n random vector x
38626546c1bSToby Isaac 
38726546c1bSToby Isaac    Collective on Mat
38826546c1bSToby Isaac 
38926546c1bSToby Isaac    Input Parameters:
39026546c1bSToby Isaac +  A - the first matrix
3914222ddf1SHong Zhang .  B - the second matrix
3924222ddf1SHong Zhang .  C - the third matrix
39326546c1bSToby Isaac -  n - number of random vectors to be tested
39426546c1bSToby Isaac 
39526546c1bSToby Isaac    Output Parameter:
39626546c1bSToby Isaac .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
39726546c1bSToby Isaac 
39826546c1bSToby Isaac    Level: intermediate
39926546c1bSToby Isaac 
40026546c1bSToby Isaac @*/
401cc48ffa7SToby Isaac PetscErrorCode MatMatTransposeMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
402cc48ffa7SToby Isaac {
403cc48ffa7SToby Isaac   PetscErrorCode ierr;
404447fed29SStefano Zampini 
405447fed29SStefano Zampini   PetscFunctionBegin;
406447fed29SStefano Zampini   ierr = MatMatMultEqual_Private(A,B,C,n,flg,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
407447fed29SStefano Zampini   PetscFunctionReturn(0);
408447fed29SStefano Zampini }
409447fed29SStefano Zampini 
410447fed29SStefano Zampini static PetscErrorCode MatProjMultEqual_Private(Mat A,Mat B,Mat C,PetscInt n,PetscBool rart,PetscBool *flg)
411447fed29SStefano Zampini {
412447fed29SStefano Zampini   PetscErrorCode ierr;
413447fed29SStefano Zampini   Vec            x,v1,v2,v3,v4,Cx,Bx;
414447fed29SStefano Zampini   PetscReal      norm_abs,norm_rel,tol=PETSC_SQRT_MACHINE_EPSILON;
415447fed29SStefano Zampini   PetscInt       i,am,an,bm,bn,cm,cn;
416447fed29SStefano Zampini   PetscRandom    rdm;
417cc48ffa7SToby Isaac   PetscScalar    none = -1.0;
418cc48ffa7SToby Isaac 
419cc48ffa7SToby Isaac   PetscFunctionBegin;
420cc48ffa7SToby Isaac   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
421cc48ffa7SToby Isaac   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
422447fed29SStefano Zampini   if (rart) { PetscInt t = bm; bm = bn; bn = t; }
423cc48ffa7SToby Isaac   ierr = MatGetLocalSize(C,&cm,&cn);CHKERRQ(ierr);
42498921bdaSJacob Faibussowitsch   if (PetscUnlikely(an != bm || bn != cm || bn != cn)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A, B, C local dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT,am,an,bm,bn,cm,cn);
425cc48ffa7SToby Isaac 
426447fed29SStefano Zampini   /* Create left vector of A: v2 */
427447fed29SStefano Zampini   ierr = MatCreateVecs(A,&Bx,&v2);CHKERRQ(ierr);
428447fed29SStefano Zampini 
429447fed29SStefano Zampini   /* Create right vectors of B: x, v3, v4 */
430447fed29SStefano Zampini   if (rart) {
431447fed29SStefano Zampini     ierr = MatCreateVecs(B,&v1,&x);CHKERRQ(ierr);
432447fed29SStefano Zampini   } else {
433447fed29SStefano Zampini     ierr = MatCreateVecs(B,&x,&v1);CHKERRQ(ierr);
434447fed29SStefano Zampini   }
435447fed29SStefano Zampini   ierr = VecDuplicate(x,&v3);CHKERRQ(ierr);
436447fed29SStefano Zampini 
437447fed29SStefano Zampini   ierr = MatCreateVecs(C,&Cx,&v4);CHKERRQ(ierr);
438447fed29SStefano Zampini   ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rdm);CHKERRQ(ierr);
439447fed29SStefano Zampini   ierr = PetscRandomSetFromOptions(rdm);CHKERRQ(ierr);
440cc48ffa7SToby Isaac 
441cc48ffa7SToby Isaac   *flg = PETSC_TRUE;
442447fed29SStefano Zampini   for (i=0; i<n; i++) {
443447fed29SStefano Zampini     ierr = VecSetRandom(x,rdm);CHKERRQ(ierr);
444447fed29SStefano Zampini     ierr = VecCopy(x,Cx);CHKERRQ(ierr);
445447fed29SStefano Zampini     ierr = MatMult(C,Cx,v4);CHKERRQ(ierr);           /* v4 = C*x   */
446447fed29SStefano Zampini     if (rart) {
447447fed29SStefano Zampini       ierr = MatMultTranspose(B,x,v1);CHKERRQ(ierr);
448cc48ffa7SToby Isaac     } else {
449447fed29SStefano Zampini       ierr = MatMult(B,x,v1);CHKERRQ(ierr);
450cc48ffa7SToby Isaac     }
451447fed29SStefano Zampini     ierr = VecCopy(v1,Bx);CHKERRQ(ierr);
452447fed29SStefano Zampini     ierr = MatMult(A,Bx,v2);CHKERRQ(ierr);          /* v2 = A*B*x */
453447fed29SStefano Zampini     ierr = VecCopy(v2,v1);CHKERRQ(ierr);
454447fed29SStefano Zampini     if (rart) {
455447fed29SStefano Zampini       ierr = MatMult(B,v1,v3);CHKERRQ(ierr); /* v3 = R*A*R^t*x */
456447fed29SStefano Zampini     } else {
457447fed29SStefano Zampini       ierr = MatMultTranspose(B,v1,v3);CHKERRQ(ierr); /* v3 = Bt*A*B*x */
458447fed29SStefano Zampini     }
459447fed29SStefano Zampini     ierr = VecNorm(v4,NORM_2,&norm_abs);CHKERRQ(ierr);
460447fed29SStefano Zampini     ierr = VecAXPY(v4,none,v3);CHKERRQ(ierr);
461447fed29SStefano Zampini     ierr = VecNorm(v4,NORM_2,&norm_rel);CHKERRQ(ierr);
462447fed29SStefano Zampini 
463447fed29SStefano Zampini     if (norm_abs > tol) norm_rel /= norm_abs;
464447fed29SStefano Zampini     if (norm_rel > tol) {
465cc48ffa7SToby Isaac       *flg = PETSC_FALSE;
466*7d3de750SJacob Faibussowitsch       ierr = PetscInfo(A,"Error: %" PetscInt_FMT "-th Mat%sMult() %g\n",i,rart ? "RARt" : "PtAP",(double)norm_rel);CHKERRQ(ierr);
467cc48ffa7SToby Isaac       break;
468cc48ffa7SToby Isaac     }
469cc48ffa7SToby Isaac   }
470447fed29SStefano Zampini 
471447fed29SStefano Zampini   ierr = PetscRandomDestroy(&rdm);CHKERRQ(ierr);
472cc48ffa7SToby Isaac   ierr = VecDestroy(&x);CHKERRQ(ierr);
473447fed29SStefano Zampini   ierr = VecDestroy(&Bx);CHKERRQ(ierr);
474447fed29SStefano Zampini   ierr = VecDestroy(&Cx);CHKERRQ(ierr);
475447fed29SStefano Zampini   ierr = VecDestroy(&v1);CHKERRQ(ierr);
476447fed29SStefano Zampini   ierr = VecDestroy(&v2);CHKERRQ(ierr);
477447fed29SStefano Zampini   ierr = VecDestroy(&v3);CHKERRQ(ierr);
478447fed29SStefano Zampini   ierr = VecDestroy(&v4);CHKERRQ(ierr);
479cc48ffa7SToby Isaac   PetscFunctionReturn(0);
480cc48ffa7SToby Isaac }
481cc48ffa7SToby Isaac 
48286919fd6SHong Zhang /*@
4834222ddf1SHong Zhang    MatPtAPMultEqual - Compares matrix-vector products of C = Bt*A*B
4844222ddf1SHong Zhang 
4854222ddf1SHong Zhang    Collective on Mat
4864222ddf1SHong Zhang 
4874222ddf1SHong Zhang    Input Parameters:
4884222ddf1SHong Zhang +  A - the first matrix
4894222ddf1SHong Zhang .  B - the second matrix
4904222ddf1SHong Zhang .  C - the third matrix
4914222ddf1SHong Zhang -  n - number of random vectors to be tested
4924222ddf1SHong Zhang 
4934222ddf1SHong Zhang    Output Parameter:
4944222ddf1SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
4954222ddf1SHong Zhang 
4964222ddf1SHong Zhang    Level: intermediate
4974222ddf1SHong Zhang 
4984222ddf1SHong Zhang @*/
4994222ddf1SHong Zhang PetscErrorCode MatPtAPMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
5004222ddf1SHong Zhang {
5014222ddf1SHong Zhang   PetscErrorCode ierr;
5024222ddf1SHong Zhang 
5034222ddf1SHong Zhang   PetscFunctionBegin;
504447fed29SStefano Zampini   ierr = MatProjMultEqual_Private(A,B,C,n,PETSC_FALSE,flg);CHKERRQ(ierr);
505447fed29SStefano Zampini   PetscFunctionReturn(0);
5064222ddf1SHong Zhang }
5074222ddf1SHong Zhang 
508447fed29SStefano Zampini /*@
509447fed29SStefano Zampini    MatRARtMultEqual - Compares matrix-vector products of C = B*A*B^t
510447fed29SStefano Zampini 
511447fed29SStefano Zampini    Collective on Mat
512447fed29SStefano Zampini 
513447fed29SStefano Zampini    Input Parameters:
514447fed29SStefano Zampini +  A - the first matrix
515447fed29SStefano Zampini .  B - the second matrix
516447fed29SStefano Zampini .  C - the third matrix
517447fed29SStefano Zampini -  n - number of random vectors to be tested
518447fed29SStefano Zampini 
519447fed29SStefano Zampini    Output Parameter:
520447fed29SStefano Zampini .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
521447fed29SStefano Zampini 
522447fed29SStefano Zampini    Level: intermediate
523447fed29SStefano Zampini 
524447fed29SStefano Zampini @*/
525447fed29SStefano Zampini PetscErrorCode MatRARtMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
526447fed29SStefano Zampini {
527447fed29SStefano Zampini   PetscErrorCode ierr;
528447fed29SStefano Zampini 
529447fed29SStefano Zampini   PetscFunctionBegin;
530447fed29SStefano Zampini   ierr = MatProjMultEqual_Private(A,B,C,n,PETSC_TRUE,flg);CHKERRQ(ierr);
5314222ddf1SHong Zhang   PetscFunctionReturn(0);
5324222ddf1SHong Zhang }
5334222ddf1SHong Zhang 
5344222ddf1SHong Zhang /*@
53586919fd6SHong Zhang    MatIsLinear - Check if a shell matrix A is a linear operator.
53686919fd6SHong Zhang 
53786919fd6SHong Zhang    Collective on Mat
53886919fd6SHong Zhang 
53986919fd6SHong Zhang    Input Parameters:
54086919fd6SHong Zhang +  A - the shell matrix
54186919fd6SHong Zhang -  n - number of random vectors to be tested
54286919fd6SHong Zhang 
54386919fd6SHong Zhang    Output Parameter:
54486919fd6SHong Zhang .  flg - PETSC_TRUE if the shell matrix is linear; PETSC_FALSE otherwise.
54586919fd6SHong Zhang 
54686919fd6SHong Zhang    Level: intermediate
54786919fd6SHong Zhang @*/
54886919fd6SHong Zhang PetscErrorCode MatIsLinear(Mat A,PetscInt n,PetscBool *flg)
54986919fd6SHong Zhang {
55086919fd6SHong Zhang   PetscErrorCode ierr;
55186919fd6SHong Zhang   Vec            x,y,s1,s2;
55286919fd6SHong Zhang   PetscRandom    rctx;
55386919fd6SHong Zhang   PetscScalar    a;
55486919fd6SHong Zhang   PetscInt       k;
55586919fd6SHong Zhang   PetscReal      norm,normA;
55686919fd6SHong Zhang   MPI_Comm       comm;
55786919fd6SHong Zhang   PetscMPIInt    rank;
55886919fd6SHong Zhang 
55986919fd6SHong Zhang   PetscFunctionBegin;
56086919fd6SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
56186919fd6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
562ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
56386919fd6SHong Zhang 
56486919fd6SHong Zhang   ierr = PetscRandomCreate(comm,&rctx);CHKERRQ(ierr);
56586919fd6SHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
56686919fd6SHong Zhang   ierr = MatCreateVecs(A,&x,&s1);CHKERRQ(ierr);
56786919fd6SHong Zhang   ierr = VecDuplicate(x,&y);CHKERRQ(ierr);
56886919fd6SHong Zhang   ierr = VecDuplicate(s1,&s2);CHKERRQ(ierr);
56986919fd6SHong Zhang 
57086919fd6SHong Zhang   *flg = PETSC_TRUE;
57186919fd6SHong Zhang   for (k=0; k<n; k++) {
57286919fd6SHong Zhang     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
5736d5db48cSHong Zhang     ierr = VecSetRandom(y,rctx);CHKERRQ(ierr);
574dd400576SPatrick Sanan     if (rank == 0) {
57586919fd6SHong Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
57686919fd6SHong Zhang     }
577ffc4695bSBarry Smith     ierr = MPI_Bcast(&a, 1, MPIU_SCALAR, 0, comm);CHKERRMPI(ierr);
57886919fd6SHong Zhang 
57986919fd6SHong Zhang     /* s2 = a*A*x + A*y */
58086919fd6SHong Zhang     ierr = MatMult(A,y,s2);CHKERRQ(ierr); /* s2 = A*y */
58186919fd6SHong Zhang     ierr = MatMult(A,x,s1);CHKERRQ(ierr); /* s1 = A*x */
58286919fd6SHong Zhang     ierr = VecAXPY(s2,a,s1);CHKERRQ(ierr); /* s2 = a s1 + s2 */
58386919fd6SHong Zhang 
58486919fd6SHong Zhang     /* s1 = A * (a x + y) */
58586919fd6SHong Zhang     ierr = VecAXPY(y,a,x);CHKERRQ(ierr); /* y = a x + y */
58686919fd6SHong Zhang     ierr = MatMult(A,y,s1);CHKERRQ(ierr);
58786919fd6SHong Zhang     ierr = VecNorm(s1,NORM_INFINITY,&normA);CHKERRQ(ierr);
58886919fd6SHong Zhang 
58986919fd6SHong Zhang     ierr = VecAXPY(s2,-1.0,s1);CHKERRQ(ierr); /* s2 = - s1 + s2 */
59086919fd6SHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&norm);CHKERRQ(ierr);
5911b8dac88SHong Zhang     if (norm/normA > 100.*PETSC_MACHINE_EPSILON) {
59286919fd6SHong Zhang       *flg = PETSC_FALSE;
593*7d3de750SJacob Faibussowitsch       ierr = PetscInfo(A,"Error: %" PetscInt_FMT "-th |A*(ax+y) - (a*A*x+A*y)|/|A(ax+y)| %g > tol %g\n",k,(double)(norm/normA),(double)(100.*PETSC_MACHINE_EPSILON));CHKERRQ(ierr);
59486919fd6SHong Zhang       break;
59586919fd6SHong Zhang     }
59686919fd6SHong Zhang   }
59786919fd6SHong Zhang   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
59886919fd6SHong Zhang   ierr = VecDestroy(&x);CHKERRQ(ierr);
59986919fd6SHong Zhang   ierr = VecDestroy(&y);CHKERRQ(ierr);
60086919fd6SHong Zhang   ierr = VecDestroy(&s1);CHKERRQ(ierr);
60186919fd6SHong Zhang   ierr = VecDestroy(&s2);CHKERRQ(ierr);
60286919fd6SHong Zhang   PetscFunctionReturn(0);
60386919fd6SHong Zhang }
604