xref: /petsc/src/mat/utils/multequal.c (revision c2916339d3c5437df97526bab4e3cf11b3acd91c)
186a22c91SHong Zhang 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>  /*I   "petscmat.h"  I*/
386a22c91SHong Zhang 
486a22c91SHong Zhang /*@
586a22c91SHong Zhang    MatMultEqual - Compares matrix-vector products of two matrices.
686a22c91SHong Zhang 
786a22c91SHong Zhang    Collective on Mat
886a22c91SHong Zhang 
986a22c91SHong Zhang    Input Parameters:
1086a22c91SHong Zhang +  A - the first matrix
1186a22c91SHong Zhang -  B - the second matrix
1286a22c91SHong Zhang -  n - number of random vectors to be tested
1386a22c91SHong Zhang 
1486a22c91SHong Zhang    Output Parameter:
1586a22c91SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
1686a22c91SHong Zhang 
1786a22c91SHong Zhang    Level: intermediate
1886a22c91SHong Zhang 
1986a22c91SHong Zhang @*/
207087cfbeSBarry Smith PetscErrorCode MatMultEqual(Mat A,Mat B,PetscInt n,PetscBool  *flg)
2186a22c91SHong Zhang {
2286a22c91SHong Zhang   PetscErrorCode ierr;
2386a22c91SHong Zhang   Vec            x,s1,s2;
2486a22c91SHong Zhang   PetscRandom    rctx;
252a0b5429SBarry Smith   PetscReal      r1,r2,tol=PETSC_SQRT_MACHINE_EPSILON;
2686a22c91SHong Zhang   PetscInt       am,an,bm,bn,k;
27e6e6b1bdSHong Zhang   PetscScalar    none = -1.0;
2886a22c91SHong Zhang 
2986a22c91SHong Zhang   PetscFunctionBegin;
300700a824SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
310700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
3286a22c91SHong Zhang   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
3386a22c91SHong Zhang   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
34e32f2f54SBarry Smith   if (am != bm || an != bn) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %D %D %D %D",am,bm,an,bn);
35cb5d8e9eSHong Zhang   PetscCheckSameComm(A,1,B,2);
36ce94432eSBarry Smith   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)A),&rctx);CHKERRQ(ierr);
37c77d6671SHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
382a7a6963SBarry Smith   ierr = MatCreateVecs(A,&x,&s1);CHKERRQ(ierr);
39cb5d8e9eSHong Zhang   ierr = VecDuplicate(s1,&s2);CHKERRQ(ierr);
4086a22c91SHong Zhang 
414eb6d288SHong Zhang   *flg = PETSC_TRUE;
4286a22c91SHong Zhang   for (k=0; k<n; k++) {
43abb0e124SMatthew Knepley     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
4486a22c91SHong Zhang     ierr = MatMult(A,x,s1);CHKERRQ(ierr);
4586a22c91SHong Zhang     ierr = MatMult(B,x,s2);CHKERRQ(ierr);
46e6e6b1bdSHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
47e6e6b1bdSHong Zhang     if (r2 < tol) {
48e6e6b1bdSHong Zhang       ierr = VecNorm(s1,NORM_INFINITY,&r1);CHKERRQ(ierr);
49e6e6b1bdSHong Zhang     } else {
502dcb1b2aSMatthew Knepley       ierr = VecAXPY(s2,none,s1);CHKERRQ(ierr);
51e6e6b1bdSHong Zhang       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
52e6e6b1bdSHong Zhang       r1  /= r2;
53e6e6b1bdSHong Zhang     }
54e6e6b1bdSHong Zhang     if (r1 > tol) {
5586a22c91SHong Zhang       *flg = PETSC_FALSE;
5657622a8eSBarry Smith       ierr = PetscInfo2(A,"Error: %D-th MatMult() %g\n",k,(double)r1);CHKERRQ(ierr);
574eb6d288SHong Zhang       break;
5886a22c91SHong Zhang     }
5986a22c91SHong Zhang   }
606bf464f9SBarry Smith   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
616bf464f9SBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
626bf464f9SBarry Smith   ierr = VecDestroy(&s1);CHKERRQ(ierr);
636bf464f9SBarry Smith   ierr = VecDestroy(&s2);CHKERRQ(ierr);
6486a22c91SHong Zhang   PetscFunctionReturn(0);
6586a22c91SHong Zhang }
6686a22c91SHong Zhang 
6786a22c91SHong Zhang /*@
6886a22c91SHong Zhang    MatMultAddEqual - Compares matrix-vector products of two matrices.
6986a22c91SHong Zhang 
7086a22c91SHong Zhang    Collective on Mat
7186a22c91SHong Zhang 
7286a22c91SHong Zhang    Input Parameters:
7386a22c91SHong Zhang +  A - the first matrix
7486a22c91SHong Zhang -  B - the second matrix
7586a22c91SHong Zhang -  n - number of random vectors to be tested
7686a22c91SHong Zhang 
7786a22c91SHong Zhang    Output Parameter:
7886a22c91SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
7986a22c91SHong Zhang 
8086a22c91SHong Zhang    Level: intermediate
8186a22c91SHong Zhang 
8286a22c91SHong Zhang @*/
837087cfbeSBarry Smith PetscErrorCode  MatMultAddEqual(Mat A,Mat B,PetscInt n,PetscBool  *flg)
8486a22c91SHong Zhang {
8586a22c91SHong Zhang   PetscErrorCode ierr;
8686a22c91SHong Zhang   Vec            x,y,s1,s2;
8786a22c91SHong Zhang   PetscRandom    rctx;
882a0b5429SBarry Smith   PetscReal      r1,r2,tol = PETSC_SQRT_MACHINE_EPSILON;
8986a22c91SHong Zhang   PetscInt       am,an,bm,bn,k;
90e6e6b1bdSHong Zhang   PetscScalar    none = -1.0;
9186a22c91SHong Zhang 
9286a22c91SHong Zhang   PetscFunctionBegin;
9386a22c91SHong Zhang   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
9486a22c91SHong Zhang   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
95e32f2f54SBarry Smith   if (am != bm || an != bn) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %D %D %D %D",am,bm,an,bn);
96cb5d8e9eSHong Zhang   PetscCheckSameComm(A,1,B,2);
97ce94432eSBarry Smith   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)A),&rctx);CHKERRQ(ierr);
98c77d6671SHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
992a7a6963SBarry Smith   ierr = MatCreateVecs(A,&x,&s1);CHKERRQ(ierr);
10063879571SHong Zhang   ierr = VecDuplicate(s1,&s2);CHKERRQ(ierr);
10163879571SHong Zhang   ierr = VecDuplicate(s1,&y);CHKERRQ(ierr);
10286a22c91SHong Zhang 
1034eb6d288SHong Zhang   *flg = PETSC_TRUE;
10486a22c91SHong Zhang   for (k=0; k<n; k++) {
105abb0e124SMatthew Knepley     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
106abb0e124SMatthew Knepley     ierr = VecSetRandom(y,rctx);CHKERRQ(ierr);
10786a22c91SHong Zhang     ierr = MatMultAdd(A,x,y,s1);CHKERRQ(ierr);
10886a22c91SHong Zhang     ierr = MatMultAdd(B,x,y,s2);CHKERRQ(ierr);
109e6e6b1bdSHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
110e6e6b1bdSHong Zhang     if (r2 < tol) {
111e6e6b1bdSHong Zhang       ierr = VecNorm(s1,NORM_INFINITY,&r1);CHKERRQ(ierr);
112e6e6b1bdSHong Zhang     } else {
1132dcb1b2aSMatthew Knepley       ierr = VecAXPY(s2,none,s1);CHKERRQ(ierr);
114e6e6b1bdSHong Zhang       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
115e6e6b1bdSHong Zhang       r1  /= r2;
116e6e6b1bdSHong Zhang     }
117e6e6b1bdSHong Zhang     if (r1 > tol) {
11886a22c91SHong Zhang       *flg = PETSC_FALSE;
11957622a8eSBarry Smith       ierr = PetscInfo2(A,"Error: %d-th MatMultAdd() %g\n",k,(double)r1);CHKERRQ(ierr);
12063879571SHong Zhang       break;
12163879571SHong Zhang     }
12263879571SHong Zhang   }
1236bf464f9SBarry Smith   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
1246bf464f9SBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1256bf464f9SBarry Smith   ierr = VecDestroy(&y);CHKERRQ(ierr);
1266bf464f9SBarry Smith   ierr = VecDestroy(&s1);CHKERRQ(ierr);
1276bf464f9SBarry Smith   ierr = VecDestroy(&s2);CHKERRQ(ierr);
12863879571SHong Zhang   PetscFunctionReturn(0);
12963879571SHong Zhang }
13063879571SHong Zhang 
13163879571SHong Zhang /*@
13263879571SHong Zhang    MatMultTransposeEqual - Compares matrix-vector products of two matrices.
13363879571SHong Zhang 
13463879571SHong Zhang    Collective on Mat
13563879571SHong Zhang 
13663879571SHong Zhang    Input Parameters:
13763879571SHong Zhang +  A - the first matrix
13863879571SHong Zhang -  B - the second matrix
13963879571SHong Zhang -  n - number of random vectors to be tested
14063879571SHong Zhang 
14163879571SHong Zhang    Output Parameter:
14263879571SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
14363879571SHong Zhang 
14463879571SHong Zhang    Level: intermediate
14563879571SHong Zhang 
14663879571SHong Zhang @*/
1477087cfbeSBarry Smith PetscErrorCode  MatMultTransposeEqual(Mat A,Mat B,PetscInt n,PetscBool  *flg)
14863879571SHong Zhang {
14963879571SHong Zhang   PetscErrorCode ierr;
15063879571SHong Zhang   Vec            x,s1,s2;
15163879571SHong Zhang   PetscRandom    rctx;
1522a0b5429SBarry Smith   PetscReal      r1,r2,tol= PETSC_SQRT_MACHINE_EPSILON;
15363879571SHong Zhang   PetscInt       am,an,bm,bn,k;
154e6e6b1bdSHong Zhang   PetscScalar    none = -1.0;
15563879571SHong Zhang 
15663879571SHong Zhang   PetscFunctionBegin;
15763879571SHong Zhang   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
15863879571SHong Zhang   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
159e32f2f54SBarry Smith   if (am != bm || an != bn) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %D %D %D %D",am,bm,an,bn);
16063879571SHong Zhang   PetscCheckSameComm(A,1,B,2);
161ce94432eSBarry Smith   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)A),&rctx);CHKERRQ(ierr);
162c77d6671SHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
1632a7a6963SBarry Smith   ierr = MatCreateVecs(A,&s1,&x);CHKERRQ(ierr);
16463879571SHong Zhang   ierr = VecDuplicate(s1,&s2);CHKERRQ(ierr);
16563879571SHong Zhang 
16663879571SHong Zhang   *flg = PETSC_TRUE;
16763879571SHong Zhang   for (k=0; k<n; k++) {
168abb0e124SMatthew Knepley     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
16963879571SHong Zhang     ierr = MatMultTranspose(A,x,s1);CHKERRQ(ierr);
17063879571SHong Zhang     ierr = MatMultTranspose(B,x,s2);CHKERRQ(ierr);
171e6e6b1bdSHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
172e6e6b1bdSHong Zhang     if (r2 < tol) {
173e6e6b1bdSHong Zhang       ierr = VecNorm(s1,NORM_INFINITY,&r1);CHKERRQ(ierr);
174e6e6b1bdSHong Zhang     } else {
1752dcb1b2aSMatthew Knepley       ierr = VecAXPY(s2,none,s1);CHKERRQ(ierr);
176e6e6b1bdSHong Zhang       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
177e6e6b1bdSHong Zhang       r1  /= r2;
178e6e6b1bdSHong Zhang     }
179e6e6b1bdSHong Zhang     if (r1 > tol) {
18063879571SHong Zhang       *flg = PETSC_FALSE;
18157622a8eSBarry Smith       ierr = PetscInfo2(A,"Error: %d-th MatMultTranspose() %g\n",k,(double)r1);CHKERRQ(ierr);
18263879571SHong Zhang       break;
18363879571SHong Zhang     }
18463879571SHong Zhang   }
1856bf464f9SBarry Smith   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
1866bf464f9SBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1876bf464f9SBarry Smith   ierr = VecDestroy(&s1);CHKERRQ(ierr);
1886bf464f9SBarry Smith   ierr = VecDestroy(&s2);CHKERRQ(ierr);
18963879571SHong Zhang   PetscFunctionReturn(0);
19063879571SHong Zhang }
19163879571SHong Zhang 
19263879571SHong Zhang /*@
19363879571SHong Zhang    MatMultTransposeAddEqual - Compares matrix-vector products of two matrices.
19463879571SHong Zhang 
19563879571SHong Zhang    Collective on Mat
19663879571SHong Zhang 
19763879571SHong Zhang    Input Parameters:
19863879571SHong Zhang +  A - the first matrix
19963879571SHong Zhang -  B - the second matrix
20063879571SHong Zhang -  n - number of random vectors to be tested
20163879571SHong Zhang 
20263879571SHong Zhang    Output Parameter:
20363879571SHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
20463879571SHong Zhang 
20563879571SHong Zhang    Level: intermediate
20663879571SHong Zhang 
20763879571SHong Zhang @*/
2087087cfbeSBarry Smith PetscErrorCode  MatMultTransposeAddEqual(Mat A,Mat B,PetscInt n,PetscBool  *flg)
20963879571SHong Zhang {
21063879571SHong Zhang   PetscErrorCode ierr;
21163879571SHong Zhang   Vec            x,y,s1,s2;
21263879571SHong Zhang   PetscRandom    rctx;
2132a0b5429SBarry Smith   PetscReal      r1,r2,tol = PETSC_SQRT_MACHINE_EPSILON;
21463879571SHong Zhang   PetscInt       am,an,bm,bn,k;
215e6e6b1bdSHong Zhang   PetscScalar    none = -1.0;
21663879571SHong Zhang 
21763879571SHong Zhang   PetscFunctionBegin;
21863879571SHong Zhang   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
21963879571SHong Zhang   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
220e32f2f54SBarry Smith   if (am != bm || an != bn) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A,Mat B: local dim %D %D %D %D",am,bm,an,bn);
22163879571SHong Zhang   PetscCheckSameComm(A,1,B,2);
222ce94432eSBarry Smith   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)A),&rctx);CHKERRQ(ierr);
223c77d6671SHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
2242a7a6963SBarry Smith   ierr = MatCreateVecs(A,&s1,&x);CHKERRQ(ierr);
22563879571SHong Zhang   ierr = VecDuplicate(s1,&s2);CHKERRQ(ierr);
22663879571SHong Zhang   ierr = VecDuplicate(s1,&y);CHKERRQ(ierr);
22763879571SHong Zhang 
22863879571SHong Zhang   *flg = PETSC_TRUE;
22963879571SHong Zhang   for (k=0; k<n; k++) {
230abb0e124SMatthew Knepley     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
231abb0e124SMatthew Knepley     ierr = VecSetRandom(y,rctx);CHKERRQ(ierr);
23263879571SHong Zhang     ierr = MatMultTransposeAdd(A,x,y,s1);CHKERRQ(ierr);
23363879571SHong Zhang     ierr = MatMultTransposeAdd(B,x,y,s2);CHKERRQ(ierr);
234e6e6b1bdSHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
235e6e6b1bdSHong Zhang     if (r2 < tol) {
236e6e6b1bdSHong Zhang       ierr = VecNorm(s1,NORM_INFINITY,&r1);CHKERRQ(ierr);
237e6e6b1bdSHong Zhang     } else {
2382dcb1b2aSMatthew Knepley       ierr = VecAXPY(s2,none,s1);CHKERRQ(ierr);
239e6e6b1bdSHong Zhang       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
240e6e6b1bdSHong Zhang       r1  /= r2;
241e6e6b1bdSHong Zhang     }
242e6e6b1bdSHong Zhang     if (r1 > tol) {
24363879571SHong Zhang       *flg = PETSC_FALSE;
24457622a8eSBarry Smith       ierr = PetscInfo2(A,"Error: %d-th MatMultTransposeAdd() %g\n",k,(double)r1);CHKERRQ(ierr);
2454eb6d288SHong Zhang       break;
24686a22c91SHong Zhang     }
24786a22c91SHong Zhang   }
2486bf464f9SBarry Smith   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
2496bf464f9SBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
2506bf464f9SBarry Smith   ierr = VecDestroy(&y);CHKERRQ(ierr);
2516bf464f9SBarry Smith   ierr = VecDestroy(&s1);CHKERRQ(ierr);
2526bf464f9SBarry Smith   ierr = VecDestroy(&s2);CHKERRQ(ierr);
25386a22c91SHong Zhang   PetscFunctionReturn(0);
25486a22c91SHong Zhang }
255a52676ecSHong Zhang 
256a52676ecSHong Zhang /*@
257a52676ecSHong Zhang    MatMatMultEqual - Test A*B*x = C*x for n random vector x
258a52676ecSHong Zhang 
259a52676ecSHong Zhang    Collective on Mat
260a52676ecSHong Zhang 
261a52676ecSHong Zhang    Input Parameters:
262a52676ecSHong Zhang +  A - the first matrix
263*c2916339SPierre Jolivet .  B - the second matrix
264*c2916339SPierre Jolivet .  C - the third matrix
265a52676ecSHong Zhang -  n - number of random vectors to be tested
266a52676ecSHong Zhang 
267a52676ecSHong Zhang    Output Parameter:
268*c2916339SPierre Jolivet +  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
269a52676ecSHong Zhang 
270a52676ecSHong Zhang    Level: intermediate
271a52676ecSHong Zhang 
272a52676ecSHong Zhang @*/
273a52676ecSHong Zhang PetscErrorCode MatMatMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
274a52676ecSHong Zhang {
275a52676ecSHong Zhang   PetscErrorCode ierr;
276a52676ecSHong Zhang   Vec            x,s1,s2,s3;
277a52676ecSHong Zhang   PetscRandom    rctx;
278a52676ecSHong Zhang   PetscReal      r1,r2,tol=PETSC_SQRT_MACHINE_EPSILON;
279a52676ecSHong Zhang   PetscInt       am,an,bm,bn,cm,cn,k;
280a52676ecSHong Zhang   PetscScalar    none = -1.0;
281a52676ecSHong Zhang 
282a52676ecSHong Zhang   PetscFunctionBegin;
283a52676ecSHong Zhang   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
284a52676ecSHong Zhang   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
285a52676ecSHong Zhang   ierr = MatGetLocalSize(C,&cm,&cn);CHKERRQ(ierr);
286a52676ecSHong Zhang   if (an != bm || am != cm || bn != cn) SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A, B, C local dim %D %D %D %D",am,an,bm,bn,cm, cn);
287a52676ecSHong Zhang 
288a52676ecSHong Zhang   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)C),&rctx);CHKERRQ(ierr);
289a52676ecSHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
290a52676ecSHong Zhang   ierr = MatCreateVecs(B,&x,&s1);CHKERRQ(ierr);
291a52676ecSHong Zhang   ierr = MatCreateVecs(C,NULL,&s2);CHKERRQ(ierr);
292a52676ecSHong Zhang   ierr = VecDuplicate(s2,&s3);CHKERRQ(ierr);
293a52676ecSHong Zhang 
294a52676ecSHong Zhang   *flg = PETSC_TRUE;
295a52676ecSHong Zhang   for (k=0; k<n; k++) {
296a52676ecSHong Zhang     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
297a52676ecSHong Zhang     ierr = MatMult(B,x,s1);CHKERRQ(ierr);
298a52676ecSHong Zhang     ierr = MatMult(A,s1,s2);CHKERRQ(ierr);
299a52676ecSHong Zhang     ierr = MatMult(C,x,s3);CHKERRQ(ierr);
300a52676ecSHong Zhang 
301a52676ecSHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
302a52676ecSHong Zhang     if (r2 < tol) {
303a52676ecSHong Zhang       ierr = VecNorm(s3,NORM_INFINITY,&r1);CHKERRQ(ierr);
304a52676ecSHong Zhang     } else {
305a52676ecSHong Zhang       ierr = VecAXPY(s2,none,s3);CHKERRQ(ierr);
306a52676ecSHong Zhang       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
307a52676ecSHong Zhang       r1  /= r2;
308a52676ecSHong Zhang     }
309a52676ecSHong Zhang     if (r1 > tol) {
310a52676ecSHong Zhang       *flg = PETSC_FALSE;
311a52676ecSHong Zhang       ierr = PetscInfo2(A,"Error: %D-th MatMatMult() %g\n",k,(double)r1);CHKERRQ(ierr);
312a52676ecSHong Zhang       break;
313a52676ecSHong Zhang     }
314a52676ecSHong Zhang   }
315a52676ecSHong Zhang   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
316a52676ecSHong Zhang   ierr = VecDestroy(&x);CHKERRQ(ierr);
317a52676ecSHong Zhang   ierr = VecDestroy(&s1);CHKERRQ(ierr);
318a52676ecSHong Zhang   ierr = VecDestroy(&s2);CHKERRQ(ierr);
319a52676ecSHong Zhang   ierr = VecDestroy(&s3);CHKERRQ(ierr);
320a52676ecSHong Zhang   PetscFunctionReturn(0);
321a52676ecSHong Zhang }
322a52676ecSHong Zhang 
323a52676ecSHong Zhang /*@
324a52676ecSHong Zhang    MatTransposeMatMultEqual - Test A^T*B*x = C*x for n random vector x
325a52676ecSHong Zhang 
326a52676ecSHong Zhang    Collective on Mat
327a52676ecSHong Zhang 
328a52676ecSHong Zhang    Input Parameters:
329a52676ecSHong Zhang +  A - the first matrix
330a52676ecSHong Zhang -  B - the second matrix
331a52676ecSHong Zhang -  C - the third matrix
332a52676ecSHong Zhang -  n - number of random vectors to be tested
333a52676ecSHong Zhang 
334a52676ecSHong Zhang    Output Parameter:
335a52676ecSHong Zhang .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
336a52676ecSHong Zhang 
337a52676ecSHong Zhang    Level: intermediate
338a52676ecSHong Zhang 
339a52676ecSHong Zhang @*/
340a52676ecSHong Zhang PetscErrorCode MatTransposeMatMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
341a52676ecSHong Zhang {
342a52676ecSHong Zhang   PetscErrorCode ierr;
343a52676ecSHong Zhang   Vec            x,s1,s2,s3;
344a52676ecSHong Zhang   PetscRandom    rctx;
345a52676ecSHong Zhang   PetscReal      r1,r2,tol=PETSC_SQRT_MACHINE_EPSILON;
346a52676ecSHong Zhang   PetscInt       am,an,bm,bn,cm,cn,k;
347a52676ecSHong Zhang   PetscScalar    none = -1.0;
348a52676ecSHong Zhang 
349a52676ecSHong Zhang   PetscFunctionBegin;
350a52676ecSHong Zhang   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
351a52676ecSHong Zhang   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
352a52676ecSHong Zhang   ierr = MatGetLocalSize(C,&cm,&cn);CHKERRQ(ierr);
353a52676ecSHong Zhang   if (am != bm || an != cm || bn != cn) SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A, B, C local dim %D %D %D %D",am,an,bm,bn,cm, cn);
354a52676ecSHong Zhang 
355a52676ecSHong Zhang   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)C),&rctx);CHKERRQ(ierr);
356a52676ecSHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
357a52676ecSHong Zhang   ierr = MatCreateVecs(B,&x,&s1);CHKERRQ(ierr);
358a52676ecSHong Zhang   ierr = MatCreateVecs(C,NULL,&s2);CHKERRQ(ierr);
359a52676ecSHong Zhang   ierr = VecDuplicate(s2,&s3);CHKERRQ(ierr);
360a52676ecSHong Zhang 
361a52676ecSHong Zhang   *flg = PETSC_TRUE;
362a52676ecSHong Zhang   for (k=0; k<n; k++) {
363a52676ecSHong Zhang     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
364a52676ecSHong Zhang     ierr = MatMult(B,x,s1);CHKERRQ(ierr);
365a52676ecSHong Zhang     ierr = MatMultTranspose(A,s1,s2);CHKERRQ(ierr);
366a52676ecSHong Zhang     ierr = MatMult(C,x,s3);CHKERRQ(ierr);
367a52676ecSHong Zhang 
368a52676ecSHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
369a52676ecSHong Zhang     if (r2 < tol) {
370a52676ecSHong Zhang       ierr = VecNorm(s3,NORM_INFINITY,&r1);CHKERRQ(ierr);
371a52676ecSHong Zhang     } else {
372a52676ecSHong Zhang       ierr = VecAXPY(s2,none,s3);CHKERRQ(ierr);
373a52676ecSHong Zhang       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
374a52676ecSHong Zhang       r1  /= r2;
375a52676ecSHong Zhang     }
376a52676ecSHong Zhang     if (r1 > tol) {
377a52676ecSHong Zhang       *flg = PETSC_FALSE;
378a52676ecSHong Zhang       ierr = PetscInfo2(A,"Error: %D-th MatTransposeMatMult() %g\n",k,(double)r1);CHKERRQ(ierr);
379a52676ecSHong Zhang       break;
380a52676ecSHong Zhang     }
381a52676ecSHong Zhang   }
382a52676ecSHong Zhang   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
383a52676ecSHong Zhang   ierr = VecDestroy(&x);CHKERRQ(ierr);
384a52676ecSHong Zhang   ierr = VecDestroy(&s1);CHKERRQ(ierr);
385a52676ecSHong Zhang   ierr = VecDestroy(&s2);CHKERRQ(ierr);
386a52676ecSHong Zhang   ierr = VecDestroy(&s3);CHKERRQ(ierr);
387a52676ecSHong Zhang   PetscFunctionReturn(0);
388a52676ecSHong Zhang }
38986919fd6SHong Zhang 
39026546c1bSToby Isaac /*@
39126546c1bSToby Isaac    MatMatTransposeMultEqual - Test A*B^T*x = C*x for n random vector x
39226546c1bSToby Isaac 
39326546c1bSToby Isaac    Collective on Mat
39426546c1bSToby Isaac 
39526546c1bSToby Isaac    Input Parameters:
39626546c1bSToby Isaac +  A - the first matrix
39726546c1bSToby Isaac -  B - the second matrix
39826546c1bSToby Isaac -  C - the third matrix
39926546c1bSToby Isaac -  n - number of random vectors to be tested
40026546c1bSToby Isaac 
40126546c1bSToby Isaac    Output Parameter:
40226546c1bSToby Isaac .  flg - PETSC_TRUE if the products are equal; PETSC_FALSE otherwise.
40326546c1bSToby Isaac 
40426546c1bSToby Isaac    Level: intermediate
40526546c1bSToby Isaac 
40626546c1bSToby Isaac @*/
407cc48ffa7SToby Isaac PetscErrorCode MatMatTransposeMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool *flg)
408cc48ffa7SToby Isaac {
409cc48ffa7SToby Isaac   PetscErrorCode ierr;
410cc48ffa7SToby Isaac   Vec            x,s1,s2,s3;
411cc48ffa7SToby Isaac   PetscRandom    rctx;
412cc48ffa7SToby Isaac   PetscReal      r1,r2,tol=PETSC_SQRT_MACHINE_EPSILON;
413cc48ffa7SToby Isaac   PetscInt       am,an,bm,bn,cm,cn,k;
414cc48ffa7SToby Isaac   PetscScalar    none = -1.0;
415cc48ffa7SToby Isaac 
416cc48ffa7SToby Isaac   PetscFunctionBegin;
417cc48ffa7SToby Isaac   ierr = MatGetLocalSize(A,&am,&an);CHKERRQ(ierr);
418cc48ffa7SToby Isaac   ierr = MatGetLocalSize(B,&bm,&bn);CHKERRQ(ierr);
419cc48ffa7SToby Isaac   ierr = MatGetLocalSize(C,&cm,&cn);CHKERRQ(ierr);
420cc48ffa7SToby Isaac   if (an != bn || am != cm || bm != cn) SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat A, B, C local dim %D %D %D %D",am,an,bm,bn,cm, cn);
421cc48ffa7SToby Isaac 
422cc48ffa7SToby Isaac   ierr = PetscRandomCreate(PetscObjectComm((PetscObject)C),&rctx);CHKERRQ(ierr);
423cc48ffa7SToby Isaac   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
424cc48ffa7SToby Isaac   ierr = MatCreateVecs(B,&s1,&x);CHKERRQ(ierr);
425cc48ffa7SToby Isaac   ierr = MatCreateVecs(C,NULL,&s2);CHKERRQ(ierr);
426cc48ffa7SToby Isaac   ierr = VecDuplicate(s2,&s3);CHKERRQ(ierr);
427cc48ffa7SToby Isaac 
428cc48ffa7SToby Isaac   *flg = PETSC_TRUE;
429cc48ffa7SToby Isaac   for (k=0; k<n; k++) {
430cc48ffa7SToby Isaac     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
431cc48ffa7SToby Isaac     ierr = MatMultTranspose(B,x,s1);CHKERRQ(ierr);
432cc48ffa7SToby Isaac     ierr = MatMult(A,s1,s2);CHKERRQ(ierr);
433cc48ffa7SToby Isaac     ierr = MatMult(C,x,s3);CHKERRQ(ierr);
434cc48ffa7SToby Isaac 
435cc48ffa7SToby Isaac     ierr = VecNorm(s2,NORM_INFINITY,&r2);CHKERRQ(ierr);
436cc48ffa7SToby Isaac     if (r2 < tol) {
437cc48ffa7SToby Isaac       ierr = VecNorm(s3,NORM_INFINITY,&r1);CHKERRQ(ierr);
438cc48ffa7SToby Isaac     } else {
439cc48ffa7SToby Isaac       ierr = VecAXPY(s2,none,s3);CHKERRQ(ierr);
440cc48ffa7SToby Isaac       ierr = VecNorm(s2,NORM_INFINITY,&r1);CHKERRQ(ierr);
441cc48ffa7SToby Isaac       r1  /= r2;
442cc48ffa7SToby Isaac     }
443cc48ffa7SToby Isaac     if (r1 > tol) {
444cc48ffa7SToby Isaac       *flg = PETSC_FALSE;
445cc48ffa7SToby Isaac       ierr = PetscInfo2(A,"Error: %D-th MatMatTransposeMult() %g\n",k,(double)r1);CHKERRQ(ierr);
446cc48ffa7SToby Isaac       break;
447cc48ffa7SToby Isaac     }
448cc48ffa7SToby Isaac   }
449cc48ffa7SToby Isaac   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
450cc48ffa7SToby Isaac   ierr = VecDestroy(&x);CHKERRQ(ierr);
451cc48ffa7SToby Isaac   ierr = VecDestroy(&s1);CHKERRQ(ierr);
452cc48ffa7SToby Isaac   ierr = VecDestroy(&s2);CHKERRQ(ierr);
453cc48ffa7SToby Isaac   ierr = VecDestroy(&s3);CHKERRQ(ierr);
454cc48ffa7SToby Isaac   PetscFunctionReturn(0);
455cc48ffa7SToby Isaac }
456cc48ffa7SToby Isaac 
45786919fd6SHong Zhang /*@
45886919fd6SHong Zhang    MatIsLinear - Check if a shell matrix A is a linear operator.
45986919fd6SHong Zhang 
46086919fd6SHong Zhang    Collective on Mat
46186919fd6SHong Zhang 
46286919fd6SHong Zhang    Input Parameters:
46386919fd6SHong Zhang +  A - the shell matrix
46486919fd6SHong Zhang -  n - number of random vectors to be tested
46586919fd6SHong Zhang 
46686919fd6SHong Zhang    Output Parameter:
46786919fd6SHong Zhang .  flg - PETSC_TRUE if the shell matrix is linear; PETSC_FALSE otherwise.
46886919fd6SHong Zhang 
46986919fd6SHong Zhang    Level: intermediate
47086919fd6SHong Zhang @*/
47186919fd6SHong Zhang PetscErrorCode MatIsLinear(Mat A,PetscInt n,PetscBool  *flg)
47286919fd6SHong Zhang {
47386919fd6SHong Zhang   PetscErrorCode ierr;
47486919fd6SHong Zhang   Vec            x,y,s1,s2;
47586919fd6SHong Zhang   PetscRandom    rctx;
47686919fd6SHong Zhang   PetscScalar    a;
47786919fd6SHong Zhang   PetscInt       k;
47886919fd6SHong Zhang   PetscReal      norm,normA;
47986919fd6SHong Zhang   MPI_Comm       comm;
48086919fd6SHong Zhang   PetscMPIInt    rank;
48186919fd6SHong Zhang 
48286919fd6SHong Zhang   PetscFunctionBegin;
48386919fd6SHong Zhang   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
48486919fd6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
48586919fd6SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
48686919fd6SHong Zhang 
48786919fd6SHong Zhang   ierr = PetscRandomCreate(comm,&rctx);CHKERRQ(ierr);
48886919fd6SHong Zhang   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
48986919fd6SHong Zhang   ierr = MatCreateVecs(A,&x,&s1);CHKERRQ(ierr);
49086919fd6SHong Zhang   ierr = VecDuplicate(x,&y);CHKERRQ(ierr);
49186919fd6SHong Zhang   ierr = VecDuplicate(s1,&s2);CHKERRQ(ierr);
49286919fd6SHong Zhang 
49386919fd6SHong Zhang   *flg = PETSC_TRUE;
49486919fd6SHong Zhang   for (k=0; k<n; k++) {
49586919fd6SHong Zhang     ierr = VecSetRandom(x,rctx);CHKERRQ(ierr);
4966d5db48cSHong Zhang     ierr = VecSetRandom(y,rctx);CHKERRQ(ierr);
49786919fd6SHong Zhang     if (!rank) {
49886919fd6SHong Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
49986919fd6SHong Zhang     }
50086919fd6SHong Zhang     ierr = MPI_Bcast(&a, 1, MPIU_SCALAR, 0, comm);CHKERRQ(ierr);
50186919fd6SHong Zhang 
50286919fd6SHong Zhang     /* s2 = a*A*x + A*y */
50386919fd6SHong Zhang     ierr = MatMult(A,y,s2);CHKERRQ(ierr); /* s2 = A*y */
50486919fd6SHong Zhang     ierr = MatMult(A,x,s1);CHKERRQ(ierr); /* s1 = A*x */
50586919fd6SHong Zhang     ierr = VecAXPY(s2,a,s1);CHKERRQ(ierr); /* s2 = a s1 + s2 */
50686919fd6SHong Zhang 
50786919fd6SHong Zhang     /* s1 = A * (a x + y) */
50886919fd6SHong Zhang     ierr = VecAXPY(y,a,x);CHKERRQ(ierr); /* y = a x + y */
50986919fd6SHong Zhang     ierr = MatMult(A,y,s1);CHKERRQ(ierr);
51086919fd6SHong Zhang     ierr = VecNorm(s1,NORM_INFINITY,&normA);CHKERRQ(ierr);
51186919fd6SHong Zhang 
51286919fd6SHong Zhang     ierr = VecAXPY(s2,-1.0,s1);CHKERRQ(ierr); /* s2 = - s1 + s2 */
51386919fd6SHong Zhang     ierr = VecNorm(s2,NORM_INFINITY,&norm);CHKERRQ(ierr);
5141b8dac88SHong Zhang     if (norm/normA > 100.*PETSC_MACHINE_EPSILON) {
51586919fd6SHong Zhang       *flg = PETSC_FALSE;
5161b8dac88SHong Zhang       ierr = PetscInfo3(A,"Error: %D-th |A*(ax+y) - (a*A*x+A*y)|/|A(ax+y)| %g > tol %g\n",k,(double)norm/normA,100.*PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
51786919fd6SHong Zhang       break;
51886919fd6SHong Zhang     }
51986919fd6SHong Zhang   }
52086919fd6SHong Zhang   ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);
52186919fd6SHong Zhang   ierr = VecDestroy(&x);CHKERRQ(ierr);
52286919fd6SHong Zhang   ierr = VecDestroy(&y);CHKERRQ(ierr);
52386919fd6SHong Zhang   ierr = VecDestroy(&s1);CHKERRQ(ierr);
52486919fd6SHong Zhang   ierr = VecDestroy(&s2);CHKERRQ(ierr);
52586919fd6SHong Zhang   PetscFunctionReturn(0);
52686919fd6SHong Zhang }
527