xref: /petsc/src/mat/utils/multequal.c (revision a4e01a8b1ea6aa127f3e22aee39c726cf71ba8b6) !
1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I   "petscmat.h"  I*/
286a22c91SHong Zhang 
3274439ffSJunchao Zhang /*
4d7c1f440SPierre Jolivet   n; try the MatMult variant n times
5274439ffSJunchao Zhang   flg: return the boolean result, equal or not
6274439ffSJunchao Zhang   t: 0 => no transpose; 1 => transpose; 2 => Hermitian transpose
7274439ffSJunchao Zhang   add:  0 => no add (e.g., y = Ax);  1 => add third vector (e.g., z = Ax + y); 2 => add update (e.g., y = Ax + y)
8274439ffSJunchao Zhang */
MatMultEqual_Private(Mat A,Mat B,PetscInt n,PetscBool * flg,PetscInt t,PetscInt add)936eb99e2SToby Isaac static PetscErrorCode MatMultEqual_Private(Mat A, Mat B, PetscInt n, PetscBool *flg, PetscInt t, PetscInt add)
10d71ae5a4SJacob Faibussowitsch {
11b84f494bSStefano Zampini   Vec         Ax = NULL, Bx = NULL, s1 = NULL, s2 = NULL, Ay = NULL, By = NULL;
12447fed29SStefano Zampini   PetscRandom rctx;
13447fed29SStefano Zampini   PetscReal   r1, r2, tol = PETSC_SQRT_MACHINE_EPSILON;
14447fed29SStefano Zampini   PetscInt    am, an, bm, bn, k;
15447fed29SStefano Zampini   PetscScalar none = -1.0;
164279555eSSatish Balay #if defined(PETSC_USE_INFO)
1736eb99e2SToby Isaac   const char *sops[] = {"MatMult", "MatMultAdd", "MatMultAdd (update)", "MatMultTranspose", "MatMultTransposeAdd", "MatMultTransposeAdd (update)", "MatMultHermitianTranspose", "MatMultHermitianTransposeAdd", "MatMultHermitianTransposeAdd (update)"};
18447fed29SStefano Zampini   const char *sop;
194279555eSSatish Balay #endif
20447fed29SStefano Zampini 
21447fed29SStefano Zampini   PetscFunctionBegin;
22447fed29SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23447fed29SStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
24447fed29SStefano Zampini   PetscCheckSameComm(A, 1, B, 2);
25447fed29SStefano Zampini   PetscValidLogicalCollectiveInt(A, n, 3);
264f572ea9SToby Isaac   PetscAssertPointer(flg, 4);
27e573050aSPierre Jolivet   PetscValidLogicalCollectiveInt(A, t, 5);
280d6f747bSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(A, add, 6);
299566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &am, &an));
309566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(B, &bm, &bn));
31aed4548fSBarry Smith   PetscCheck(am == bm && an == bn, 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);
324279555eSSatish Balay #if defined(PETSC_USE_INFO)
33274439ffSJunchao Zhang   sop = sops[add + 3 * t];
344279555eSSatish Balay #endif
359566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)A), &rctx));
369566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(rctx));
37447fed29SStefano Zampini   if (t) {
389566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A, &s1, &Ax));
399566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &s2, &Bx));
40447fed29SStefano Zampini   } else {
419566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A, &Ax, &s1));
429566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &Bx, &s2));
43447fed29SStefano Zampini   }
44447fed29SStefano Zampini   if (add) {
459566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(s1, &Ay));
469566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(s2, &By));
47447fed29SStefano Zampini   }
48447fed29SStefano Zampini 
49447fed29SStefano Zampini   *flg = PETSC_TRUE;
50447fed29SStefano Zampini   for (k = 0; k < n; k++) {
5136eb99e2SToby Isaac     Vec Aadd = NULL, Badd = NULL;
5236eb99e2SToby Isaac 
539566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(Ax, rctx));
549566063dSJacob Faibussowitsch     PetscCall(VecCopy(Ax, Bx));
55447fed29SStefano Zampini     if (add) {
569566063dSJacob Faibussowitsch       PetscCall(VecSetRandom(Ay, rctx));
579566063dSJacob Faibussowitsch       PetscCall(VecCopy(Ay, By));
5836eb99e2SToby Isaac       Aadd = Ay;
5936eb99e2SToby Isaac       Badd = By;
6036eb99e2SToby Isaac       if (add == 2) {
6136eb99e2SToby Isaac         PetscCall(VecCopy(Ay, s1));
6236eb99e2SToby Isaac         PetscCall(VecCopy(By, s2));
6336eb99e2SToby Isaac         Aadd = s1;
6436eb99e2SToby Isaac         Badd = s2;
6536eb99e2SToby Isaac       }
66447fed29SStefano Zampini     }
67e573050aSPierre Jolivet     if (t == 1) {
68447fed29SStefano Zampini       if (add) {
6936eb99e2SToby Isaac         PetscCall(MatMultTransposeAdd(A, Ax, Aadd, s1));
7036eb99e2SToby Isaac         PetscCall(MatMultTransposeAdd(B, Bx, Badd, s2));
71447fed29SStefano Zampini       } else {
729566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(A, Ax, s1));
739566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(B, Bx, s2));
74447fed29SStefano Zampini       }
75e573050aSPierre Jolivet     } else if (t == 2) {
76e573050aSPierre Jolivet       if (add) {
7736eb99e2SToby Isaac         PetscCall(MatMultHermitianTransposeAdd(A, Ax, Aadd, s1));
7836eb99e2SToby Isaac         PetscCall(MatMultHermitianTransposeAdd(B, Bx, Badd, s2));
79e573050aSPierre Jolivet       } else {
809566063dSJacob Faibussowitsch         PetscCall(MatMultHermitianTranspose(A, Ax, s1));
819566063dSJacob Faibussowitsch         PetscCall(MatMultHermitianTranspose(B, Bx, s2));
82e573050aSPierre Jolivet       }
83447fed29SStefano Zampini     } else {
84447fed29SStefano Zampini       if (add) {
8536eb99e2SToby Isaac         PetscCall(MatMultAdd(A, Ax, Aadd, s1));
8636eb99e2SToby Isaac         PetscCall(MatMultAdd(B, Bx, Badd, s2));
87447fed29SStefano Zampini       } else {
889566063dSJacob Faibussowitsch         PetscCall(MatMult(A, Ax, s1));
899566063dSJacob Faibussowitsch         PetscCall(MatMult(B, Bx, s2));
90447fed29SStefano Zampini       }
91447fed29SStefano Zampini     }
929566063dSJacob Faibussowitsch     PetscCall(VecNorm(s2, NORM_INFINITY, &r2));
93447fed29SStefano Zampini     if (r2 < tol) {
949566063dSJacob Faibussowitsch       PetscCall(VecNorm(s1, NORM_INFINITY, &r1));
95447fed29SStefano Zampini     } else {
969566063dSJacob Faibussowitsch       PetscCall(VecAXPY(s2, none, s1));
979566063dSJacob Faibussowitsch       PetscCall(VecNorm(s2, NORM_INFINITY, &r1));
98447fed29SStefano Zampini       r1 /= r2;
99447fed29SStefano Zampini     }
100447fed29SStefano Zampini     if (r1 > tol) {
101447fed29SStefano Zampini       *flg = PETSC_FALSE;
1029566063dSJacob Faibussowitsch       PetscCall(PetscInfo(A, "Error: %" PetscInt_FMT "-th %s() %g\n", k, sop, (double)r1));
103447fed29SStefano Zampini       break;
104447fed29SStefano Zampini     }
105447fed29SStefano Zampini   }
1069566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rctx));
1079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Ax));
1089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Bx));
1099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Ay));
1109566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&By));
1119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s1));
1129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s2));
1133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
114447fed29SStefano Zampini }
115447fed29SStefano Zampini 
MatMatMultEqual_Private(Mat A,Mat B,Mat C,PetscInt n,PetscBool * flg,PetscBool At,PetscBool Bt)116d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultEqual_Private(Mat A, Mat B, Mat C, PetscInt n, PetscBool *flg, PetscBool At, PetscBool Bt)
117d71ae5a4SJacob Faibussowitsch {
118447fed29SStefano Zampini   Vec         Ax, Bx, Cx, s1, s2, s3;
119447fed29SStefano Zampini   PetscRandom rctx;
120447fed29SStefano Zampini   PetscReal   r1, r2, tol = PETSC_SQRT_MACHINE_EPSILON;
121447fed29SStefano Zampini   PetscInt    am, an, bm, bn, cm, cn, k;
122447fed29SStefano Zampini   PetscScalar none = -1.0;
1234279555eSSatish Balay #if defined(PETSC_USE_INFO)
124580c7c76SPierre Jolivet   const char *sops[] = {"MatMatMult", "MatTransposeMatMult", "MatMatTransposeMult", "MatTransposeMatTransposeMult"};
125447fed29SStefano Zampini   const char *sop;
1264279555eSSatish Balay #endif
127447fed29SStefano Zampini 
128447fed29SStefano Zampini   PetscFunctionBegin;
129447fed29SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
130447fed29SStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
131447fed29SStefano Zampini   PetscCheckSameComm(A, 1, B, 2);
132447fed29SStefano Zampini   PetscValidHeaderSpecific(C, MAT_CLASSID, 3);
133447fed29SStefano Zampini   PetscCheckSameComm(A, 1, C, 3);
134447fed29SStefano Zampini   PetscValidLogicalCollectiveInt(A, n, 4);
1354f572ea9SToby Isaac   PetscAssertPointer(flg, 5);
136447fed29SStefano Zampini   PetscValidLogicalCollectiveBool(A, At, 6);
137447fed29SStefano Zampini   PetscValidLogicalCollectiveBool(B, Bt, 7);
1389566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &am, &an));
1399566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(B, &bm, &bn));
1409566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(C, &cm, &cn));
1419371c9d4SSatish Balay   if (At) {
1429371c9d4SSatish Balay     PetscInt tt = an;
1439371c9d4SSatish Balay     an          = am;
1449371c9d4SSatish Balay     am          = tt;
145a8f51744SPierre Jolivet   }
1469371c9d4SSatish Balay   if (Bt) {
1479371c9d4SSatish Balay     PetscInt tt = bn;
1489371c9d4SSatish Balay     bn          = bm;
1499371c9d4SSatish Balay     bm          = tt;
150a8f51744SPierre Jolivet   }
151aed4548fSBarry Smith   PetscCheck(an == bm && am == cm && bn == cn, 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);
152447fed29SStefano Zampini 
1534279555eSSatish Balay #if defined(PETSC_USE_INFO)
154447fed29SStefano Zampini   sop = sops[(At ? 1 : 0) + 2 * (Bt ? 1 : 0)];
1554279555eSSatish Balay #endif
1569566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)C), &rctx));
1579566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(rctx));
158447fed29SStefano Zampini   if (Bt) {
1599566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &s1, &Bx));
160447fed29SStefano Zampini   } else {
1619566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &Bx, &s1));
162447fed29SStefano Zampini   }
163447fed29SStefano Zampini   if (At) {
1649566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A, &s2, &Ax));
165447fed29SStefano Zampini   } else {
1669566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A, &Ax, &s2));
167447fed29SStefano Zampini   }
1689566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(C, &Cx, &s3));
169447fed29SStefano Zampini 
170447fed29SStefano Zampini   *flg = PETSC_TRUE;
171447fed29SStefano Zampini   for (k = 0; k < n; k++) {
1729566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(Bx, rctx));
173447fed29SStefano Zampini     if (Bt) {
1749566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(B, Bx, s1));
175447fed29SStefano Zampini     } else {
1769566063dSJacob Faibussowitsch       PetscCall(MatMult(B, Bx, s1));
177447fed29SStefano Zampini     }
1789566063dSJacob Faibussowitsch     PetscCall(VecCopy(s1, Ax));
179447fed29SStefano Zampini     if (At) {
1809566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(A, Ax, s2));
181447fed29SStefano Zampini     } else {
1829566063dSJacob Faibussowitsch       PetscCall(MatMult(A, Ax, s2));
183447fed29SStefano Zampini     }
1849566063dSJacob Faibussowitsch     PetscCall(VecCopy(Bx, Cx));
1859566063dSJacob Faibussowitsch     PetscCall(MatMult(C, Cx, s3));
186447fed29SStefano Zampini 
1879566063dSJacob Faibussowitsch     PetscCall(VecNorm(s2, NORM_INFINITY, &r2));
188447fed29SStefano Zampini     if (r2 < tol) {
1899566063dSJacob Faibussowitsch       PetscCall(VecNorm(s3, NORM_INFINITY, &r1));
190447fed29SStefano Zampini     } else {
1919566063dSJacob Faibussowitsch       PetscCall(VecAXPY(s2, none, s3));
1929566063dSJacob Faibussowitsch       PetscCall(VecNorm(s2, NORM_INFINITY, &r1));
193447fed29SStefano Zampini       r1 /= r2;
194447fed29SStefano Zampini     }
195447fed29SStefano Zampini     if (r1 > tol) {
196447fed29SStefano Zampini       *flg = PETSC_FALSE;
1979566063dSJacob Faibussowitsch       PetscCall(PetscInfo(A, "Error: %" PetscInt_FMT "-th %s %g\n", k, sop, (double)r1));
198447fed29SStefano Zampini       break;
199447fed29SStefano Zampini     }
200447fed29SStefano Zampini   }
2019566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rctx));
2029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Ax));
2039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Bx));
2049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Cx));
2059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s1));
2069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s2));
2079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s3));
2083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209447fed29SStefano Zampini }
210447fed29SStefano Zampini 
21186a22c91SHong Zhang /*@
2128d6650c0SBarry Smith   MatMultEqual - Compares matrix-vector products of two matrices using `n` random vectors
21386a22c91SHong Zhang 
214c3339decSBarry Smith   Collective
21586a22c91SHong Zhang 
21686a22c91SHong Zhang   Input Parameters:
21786a22c91SHong Zhang + A - the first matrix
2184222ddf1SHong Zhang . B - the second matrix
21986a22c91SHong Zhang - n - number of random vectors to be tested
22086a22c91SHong Zhang 
22186a22c91SHong Zhang   Output Parameter:
22220f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
22386a22c91SHong Zhang 
22486a22c91SHong Zhang   Level: intermediate
22586a22c91SHong Zhang 
2268d6650c0SBarry Smith   Note:
2278d6650c0SBarry Smith   The tolerance for equality is a generous `PETSC_SQRT_MACHINE_EPSILON` in the norm of the difference of the two computed vectors to
2288d6650c0SBarry Smith   allow for differences in the numerical computations. Hence this routine may indicate equality even if there is a small systematic difference
2298d6650c0SBarry Smith   between the two matrices.
2308d6650c0SBarry Smith 
2318d6650c0SBarry Smith .seealso: `Mat`, `MatMultAddEqual()`, `MatMultTransposeEqual()`, `MatMultTransposeAddEqual()`, `MatIsLinear()`, `MatEqual()`
23286a22c91SHong Zhang @*/
MatMultEqual(Mat A,Mat B,PetscInt n,PetscBool * flg)233d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultEqual(Mat A, Mat B, PetscInt n, PetscBool *flg)
234d71ae5a4SJacob Faibussowitsch {
23586a22c91SHong Zhang   PetscFunctionBegin;
23636eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 0, 0));
2373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23886a22c91SHong Zhang }
23986a22c91SHong Zhang 
24086a22c91SHong Zhang /*@
24120f4b53cSBarry Smith   MatMultAddEqual - Compares matrix-vector product plus vector add of two matrices.
24286a22c91SHong Zhang 
243c3339decSBarry Smith   Collective
24486a22c91SHong Zhang 
24586a22c91SHong Zhang   Input Parameters:
24686a22c91SHong Zhang + A - the first matrix
2474222ddf1SHong Zhang . B - the second matrix
24886a22c91SHong Zhang - n - number of random vectors to be tested
24986a22c91SHong Zhang 
25086a22c91SHong Zhang   Output Parameter:
25120f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
25286a22c91SHong Zhang 
25386a22c91SHong Zhang   Level: intermediate
25486a22c91SHong Zhang 
25520f4b53cSBarry Smith .seealso: `Mat`, `MatMultEqual()`, `MatMultTransposeEqual()`, `MatMultTransposeAddEqual()`
25686a22c91SHong Zhang @*/
MatMultAddEqual(Mat A,Mat B,PetscInt n,PetscBool * flg)257d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAddEqual(Mat A, Mat B, PetscInt n, PetscBool *flg)
258d71ae5a4SJacob Faibussowitsch {
25986a22c91SHong Zhang   PetscFunctionBegin;
26036eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 0, 1));
26136eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 0, 2));
2623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26363879571SHong Zhang }
26463879571SHong Zhang 
26563879571SHong Zhang /*@
26663879571SHong Zhang   MatMultTransposeEqual - Compares matrix-vector products of two matrices.
26763879571SHong Zhang 
268c3339decSBarry Smith   Collective
26963879571SHong Zhang 
27063879571SHong Zhang   Input Parameters:
27163879571SHong Zhang + A - the first matrix
2724222ddf1SHong Zhang . B - the second matrix
27363879571SHong Zhang - n - number of random vectors to be tested
27463879571SHong Zhang 
27563879571SHong Zhang   Output Parameter:
27620f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
27763879571SHong Zhang 
27863879571SHong Zhang   Level: intermediate
27963879571SHong Zhang 
28020f4b53cSBarry Smith .seealso: `Mat`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeAddEqual()`
28163879571SHong Zhang @*/
MatMultTransposeEqual(Mat A,Mat B,PetscInt n,PetscBool * flg)282d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeEqual(Mat A, Mat B, PetscInt n, PetscBool *flg)
283d71ae5a4SJacob Faibussowitsch {
28463879571SHong Zhang   PetscFunctionBegin;
28536eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 1, 0));
2863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28763879571SHong Zhang }
28863879571SHong Zhang 
28963879571SHong Zhang /*@
29063879571SHong Zhang   MatMultTransposeAddEqual - Compares matrix-vector products of two matrices.
29163879571SHong Zhang 
292c3339decSBarry Smith   Collective
29363879571SHong Zhang 
29463879571SHong Zhang   Input Parameters:
29563879571SHong Zhang + A - the first matrix
2964222ddf1SHong Zhang . B - the second matrix
29763879571SHong Zhang - n - number of random vectors to be tested
29863879571SHong Zhang 
29963879571SHong Zhang   Output Parameter:
30020f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
30163879571SHong Zhang 
30263879571SHong Zhang   Level: intermediate
30363879571SHong Zhang 
30420f4b53cSBarry Smith .seealso: `Mat`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
30563879571SHong Zhang @*/
MatMultTransposeAddEqual(Mat A,Mat B,PetscInt n,PetscBool * flg)306d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAddEqual(Mat A, Mat B, PetscInt n, PetscBool *flg)
307d71ae5a4SJacob Faibussowitsch {
30863879571SHong Zhang   PetscFunctionBegin;
30936eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 1, 1));
31036eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 1, 2));
3113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
312e573050aSPierre Jolivet }
313e573050aSPierre Jolivet 
314e573050aSPierre Jolivet /*@
315e573050aSPierre Jolivet   MatMultHermitianTransposeEqual - Compares matrix-vector products of two matrices.
316e573050aSPierre Jolivet 
317c3339decSBarry Smith   Collective
318e573050aSPierre Jolivet 
319e573050aSPierre Jolivet   Input Parameters:
320e573050aSPierre Jolivet + A - the first matrix
321e573050aSPierre Jolivet . B - the second matrix
322e573050aSPierre Jolivet - n - number of random vectors to be tested
323e573050aSPierre Jolivet 
324e573050aSPierre Jolivet   Output Parameter:
32520f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
326e573050aSPierre Jolivet 
327e573050aSPierre Jolivet   Level: intermediate
328e573050aSPierre Jolivet 
32952cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
330e573050aSPierre Jolivet @*/
MatMultHermitianTransposeEqual(Mat A,Mat B,PetscInt n,PetscBool * flg)331d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultHermitianTransposeEqual(Mat A, Mat B, PetscInt n, PetscBool *flg)
332d71ae5a4SJacob Faibussowitsch {
333e573050aSPierre Jolivet   PetscFunctionBegin;
33436eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 2, 0));
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
336e573050aSPierre Jolivet }
337e573050aSPierre Jolivet 
338e573050aSPierre Jolivet /*@
339e573050aSPierre Jolivet   MatMultHermitianTransposeAddEqual - Compares matrix-vector products of two matrices.
340e573050aSPierre Jolivet 
341c3339decSBarry Smith   Collective
342e573050aSPierre Jolivet 
343e573050aSPierre Jolivet   Input Parameters:
344e573050aSPierre Jolivet + A - the first matrix
345e573050aSPierre Jolivet . B - the second matrix
346e573050aSPierre Jolivet - n - number of random vectors to be tested
347e573050aSPierre Jolivet 
348e573050aSPierre Jolivet   Output Parameter:
34920f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
350e573050aSPierre Jolivet 
351e573050aSPierre Jolivet   Level: intermediate
352e573050aSPierre Jolivet 
35352cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
354e573050aSPierre Jolivet @*/
MatMultHermitianTransposeAddEqual(Mat A,Mat B,PetscInt n,PetscBool * flg)355d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultHermitianTransposeAddEqual(Mat A, Mat B, PetscInt n, PetscBool *flg)
356d71ae5a4SJacob Faibussowitsch {
357e573050aSPierre Jolivet   PetscFunctionBegin;
35836eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 2, 1));
35936eb99e2SToby Isaac   PetscCall(MatMultEqual_Private(A, B, n, flg, 2, 2));
3603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36186a22c91SHong Zhang }
362a52676ecSHong Zhang 
363a52676ecSHong Zhang /*@
364a52676ecSHong Zhang   MatMatMultEqual - Test A*B*x = C*x for n random vector x
365a52676ecSHong Zhang 
366c3339decSBarry Smith   Collective
367a52676ecSHong Zhang 
368a52676ecSHong Zhang   Input Parameters:
369a52676ecSHong Zhang + A - the first matrix
370c2916339SPierre Jolivet . B - the second matrix
371c2916339SPierre Jolivet . C - the third matrix
372a52676ecSHong Zhang - n - number of random vectors to be tested
373a52676ecSHong Zhang 
374a52676ecSHong Zhang   Output Parameter:
37520f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
376a52676ecSHong Zhang 
377a52676ecSHong Zhang   Level: intermediate
378a52676ecSHong Zhang 
37952cd20c4SPierre Jolivet .seealso: `Mat`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
380a52676ecSHong Zhang @*/
MatMatMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool * flg)381d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultEqual(Mat A, Mat B, Mat C, PetscInt n, PetscBool *flg)
382d71ae5a4SJacob Faibussowitsch {
383a52676ecSHong Zhang   PetscFunctionBegin;
3849566063dSJacob Faibussowitsch   PetscCall(MatMatMultEqual_Private(A, B, C, n, flg, PETSC_FALSE, PETSC_FALSE));
3853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
386a52676ecSHong Zhang }
387a52676ecSHong Zhang 
388a52676ecSHong Zhang /*@
389a52676ecSHong Zhang   MatTransposeMatMultEqual - Test A^T*B*x = C*x for n random vector x
390a52676ecSHong Zhang 
391c3339decSBarry Smith   Collective
392a52676ecSHong Zhang 
393a52676ecSHong Zhang   Input Parameters:
394a52676ecSHong Zhang + A - the first matrix
3954222ddf1SHong Zhang . B - the second matrix
3964222ddf1SHong Zhang . C - the third matrix
397a52676ecSHong Zhang - n - number of random vectors to be tested
398a52676ecSHong Zhang 
399a52676ecSHong Zhang   Output Parameter:
40020f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
401a52676ecSHong Zhang 
402a52676ecSHong Zhang   Level: intermediate
403a52676ecSHong Zhang 
40452cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
405a52676ecSHong Zhang @*/
MatTransposeMatMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool * flg)406d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultEqual(Mat A, Mat B, Mat C, PetscInt n, PetscBool *flg)
407d71ae5a4SJacob Faibussowitsch {
408a52676ecSHong Zhang   PetscFunctionBegin;
4099566063dSJacob Faibussowitsch   PetscCall(MatMatMultEqual_Private(A, B, C, n, flg, PETSC_TRUE, PETSC_FALSE));
4103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
411a52676ecSHong Zhang }
41286919fd6SHong Zhang 
41326546c1bSToby Isaac /*@
41426546c1bSToby Isaac   MatMatTransposeMultEqual - Test A*B^T*x = C*x for n random vector x
41526546c1bSToby Isaac 
416c3339decSBarry Smith   Collective
41726546c1bSToby Isaac 
41826546c1bSToby Isaac   Input Parameters:
41926546c1bSToby Isaac + A - the first matrix
4204222ddf1SHong Zhang . B - the second matrix
4214222ddf1SHong Zhang . C - the third matrix
42226546c1bSToby Isaac - n - number of random vectors to be tested
42326546c1bSToby Isaac 
42426546c1bSToby Isaac   Output Parameter:
42520f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
42626546c1bSToby Isaac 
42726546c1bSToby Isaac   Level: intermediate
42826546c1bSToby Isaac 
42952cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
43026546c1bSToby Isaac @*/
MatMatTransposeMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool * flg)431d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultEqual(Mat A, Mat B, Mat C, PetscInt n, PetscBool *flg)
432d71ae5a4SJacob Faibussowitsch {
433447fed29SStefano Zampini   PetscFunctionBegin;
4349566063dSJacob Faibussowitsch   PetscCall(MatMatMultEqual_Private(A, B, C, n, flg, PETSC_FALSE, PETSC_TRUE));
4353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
436447fed29SStefano Zampini }
437447fed29SStefano Zampini 
MatProjMultEqual_Private(Mat A,Mat B,Mat C,PetscInt n,PetscBool rart,PetscBool * flg)438d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProjMultEqual_Private(Mat A, Mat B, Mat C, PetscInt n, PetscBool rart, PetscBool *flg)
439d71ae5a4SJacob Faibussowitsch {
440447fed29SStefano Zampini   Vec         x, v1, v2, v3, v4, Cx, Bx;
441447fed29SStefano Zampini   PetscReal   norm_abs, norm_rel, tol = PETSC_SQRT_MACHINE_EPSILON;
442447fed29SStefano Zampini   PetscInt    i, am, an, bm, bn, cm, cn;
443447fed29SStefano Zampini   PetscRandom rdm;
444cc48ffa7SToby Isaac 
445cc48ffa7SToby Isaac   PetscFunctionBegin;
4469566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &am, &an));
4479566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(B, &bm, &bn));
4489371c9d4SSatish Balay   if (rart) {
4499371c9d4SSatish Balay     PetscInt t = bm;
4509371c9d4SSatish Balay     bm         = bn;
4519371c9d4SSatish Balay     bn         = t;
4529371c9d4SSatish Balay   }
4539566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(C, &cm, &cn));
454aed4548fSBarry Smith   PetscCheck(an == bm && bn == cm && bn == cn, 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);
455cc48ffa7SToby Isaac 
456447fed29SStefano Zampini   /* Create left vector of A: v2 */
4579566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A, &Bx, &v2));
458447fed29SStefano Zampini 
459447fed29SStefano Zampini   /* Create right vectors of B: x, v3, v4 */
460447fed29SStefano Zampini   if (rart) {
4619566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &v1, &x));
462447fed29SStefano Zampini   } else {
4639566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &x, &v1));
464447fed29SStefano Zampini   }
4659566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &v3));
466447fed29SStefano Zampini 
4679566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(C, &Cx, &v4));
4689566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rdm));
4699566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(rdm));
470cc48ffa7SToby Isaac 
471cc48ffa7SToby Isaac   *flg = PETSC_TRUE;
472447fed29SStefano Zampini   for (i = 0; i < n; i++) {
4739566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(x, rdm));
4749566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, Cx));
4759566063dSJacob Faibussowitsch     PetscCall(MatMult(C, Cx, v4)); /* v4 = C*x   */
476447fed29SStefano Zampini     if (rart) {
4779566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(B, x, v1));
478cc48ffa7SToby Isaac     } else {
4799566063dSJacob Faibussowitsch       PetscCall(MatMult(B, x, v1));
480cc48ffa7SToby Isaac     }
4819566063dSJacob Faibussowitsch     PetscCall(VecCopy(v1, Bx));
4829566063dSJacob Faibussowitsch     PetscCall(MatMult(A, Bx, v2)); /* v2 = A*B*x */
4839566063dSJacob Faibussowitsch     PetscCall(VecCopy(v2, v1));
484447fed29SStefano Zampini     if (rart) {
4859566063dSJacob Faibussowitsch       PetscCall(MatMult(B, v1, v3)); /* v3 = R*A*R^t*x */
486447fed29SStefano Zampini     } else {
4879566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(B, v1, v3)); /* v3 = Bt*A*B*x */
488447fed29SStefano Zampini     }
4899566063dSJacob Faibussowitsch     PetscCall(VecNorm(v4, NORM_2, &norm_abs));
490*80449f2dSJunchao Zhang     PetscCall(VecAXPY(v4, -1.0, v3));
4919566063dSJacob Faibussowitsch     PetscCall(VecNorm(v4, NORM_2, &norm_rel));
492447fed29SStefano Zampini 
493447fed29SStefano Zampini     if (norm_abs > tol) norm_rel /= norm_abs;
494*80449f2dSJunchao Zhang     if (norm_rel > tol || PetscIsInfOrNanReal(norm_rel)) {
495cc48ffa7SToby Isaac       *flg = PETSC_FALSE;
4969566063dSJacob Faibussowitsch       PetscCall(PetscInfo(A, "Error: %" PetscInt_FMT "-th Mat%sMult() %g\n", i, rart ? "RARt" : "PtAP", (double)norm_rel));
497cc48ffa7SToby Isaac       break;
498cc48ffa7SToby Isaac     }
499cc48ffa7SToby Isaac   }
500447fed29SStefano Zampini 
5019566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rdm));
5029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
5039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Bx));
5049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Cx));
5059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v1));
5069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v2));
5079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v3));
5089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v4));
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
510cc48ffa7SToby Isaac }
511cc48ffa7SToby Isaac 
51286919fd6SHong Zhang /*@
5134222ddf1SHong Zhang   MatPtAPMultEqual - Compares matrix-vector products of C = Bt*A*B
5144222ddf1SHong Zhang 
515c3339decSBarry Smith   Collective
5164222ddf1SHong Zhang 
5174222ddf1SHong Zhang   Input Parameters:
5184222ddf1SHong Zhang + A - the first matrix
5194222ddf1SHong Zhang . B - the second matrix
5204222ddf1SHong Zhang . C - the third matrix
5214222ddf1SHong Zhang - n - number of random vectors to be tested
5224222ddf1SHong Zhang 
5234222ddf1SHong Zhang   Output Parameter:
52420f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
5254222ddf1SHong Zhang 
5264222ddf1SHong Zhang   Level: intermediate
5274222ddf1SHong Zhang 
52852cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
5294222ddf1SHong Zhang @*/
MatPtAPMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool * flg)530d71ae5a4SJacob Faibussowitsch PetscErrorCode MatPtAPMultEqual(Mat A, Mat B, Mat C, PetscInt n, PetscBool *flg)
531d71ae5a4SJacob Faibussowitsch {
5324222ddf1SHong Zhang   PetscFunctionBegin;
5339566063dSJacob Faibussowitsch   PetscCall(MatProjMultEqual_Private(A, B, C, n, PETSC_FALSE, flg));
5343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5354222ddf1SHong Zhang }
5364222ddf1SHong Zhang 
537447fed29SStefano Zampini /*@
538447fed29SStefano Zampini   MatRARtMultEqual - Compares matrix-vector products of C = B*A*B^t
539447fed29SStefano Zampini 
540c3339decSBarry Smith   Collective
541447fed29SStefano Zampini 
542447fed29SStefano Zampini   Input Parameters:
543447fed29SStefano Zampini + A - the first matrix
544447fed29SStefano Zampini . B - the second matrix
545447fed29SStefano Zampini . C - the third matrix
546447fed29SStefano Zampini - n - number of random vectors to be tested
547447fed29SStefano Zampini 
548447fed29SStefano Zampini   Output Parameter:
54920f4b53cSBarry Smith . flg - `PETSC_TRUE` if the products are equal; `PETSC_FALSE` otherwise.
550447fed29SStefano Zampini 
551447fed29SStefano Zampini   Level: intermediate
552447fed29SStefano Zampini 
55352cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
554447fed29SStefano Zampini @*/
MatRARtMultEqual(Mat A,Mat B,Mat C,PetscInt n,PetscBool * flg)555d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRARtMultEqual(Mat A, Mat B, Mat C, PetscInt n, PetscBool *flg)
556d71ae5a4SJacob Faibussowitsch {
557447fed29SStefano Zampini   PetscFunctionBegin;
5589566063dSJacob Faibussowitsch   PetscCall(MatProjMultEqual_Private(A, B, C, n, PETSC_TRUE, flg));
5593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5604222ddf1SHong Zhang }
5614222ddf1SHong Zhang 
5624222ddf1SHong Zhang /*@
56320f4b53cSBarry Smith   MatIsLinear - Check if a shell matrix `A` is a linear operator.
56486919fd6SHong Zhang 
565c3339decSBarry Smith   Collective
56686919fd6SHong Zhang 
56786919fd6SHong Zhang   Input Parameters:
56886919fd6SHong Zhang + A - the shell matrix
56986919fd6SHong Zhang - n - number of random vectors to be tested
57086919fd6SHong Zhang 
57186919fd6SHong Zhang   Output Parameter:
57220f4b53cSBarry Smith . flg - `PETSC_TRUE` if the shell matrix is linear; `PETSC_FALSE` otherwise.
57386919fd6SHong Zhang 
57486919fd6SHong Zhang   Level: intermediate
57520f4b53cSBarry Smith 
57652cd20c4SPierre Jolivet .seealso: `Mat`, `MatMatMultEqual()`, `MatMultEqual()`, `MatMultAddEqual()`, `MatMultTransposeEqual()`
57786919fd6SHong Zhang @*/
MatIsLinear(Mat A,PetscInt n,PetscBool * flg)578d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsLinear(Mat A, PetscInt n, PetscBool *flg)
579d71ae5a4SJacob Faibussowitsch {
58086919fd6SHong Zhang   Vec         x, y, s1, s2;
58186919fd6SHong Zhang   PetscRandom rctx;
58286919fd6SHong Zhang   PetscScalar a;
58386919fd6SHong Zhang   PetscInt    k;
58486919fd6SHong Zhang   PetscReal   norm, normA;
58586919fd6SHong Zhang   MPI_Comm    comm;
58686919fd6SHong Zhang   PetscMPIInt rank;
58786919fd6SHong Zhang 
58886919fd6SHong Zhang   PetscFunctionBegin;
58986919fd6SHong Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5909566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
5919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
59286919fd6SHong Zhang 
5939566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(comm, &rctx));
5949566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(rctx));
5959566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A, &x, &s1));
5969566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &y));
5979566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(s1, &s2));
59886919fd6SHong Zhang 
59986919fd6SHong Zhang   *flg = PETSC_TRUE;
60086919fd6SHong Zhang   for (k = 0; k < n; k++) {
6019566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(x, rctx));
6029566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(y, rctx));
60348a46eb9SPierre Jolivet     if (rank == 0) PetscCall(PetscRandomGetValue(rctx, &a));
6049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(&a, 1, MPIU_SCALAR, 0, comm));
60586919fd6SHong Zhang 
60686919fd6SHong Zhang     /* s2 = a*A*x + A*y */
6079566063dSJacob Faibussowitsch     PetscCall(MatMult(A, y, s2));  /* s2 = A*y */
6089566063dSJacob Faibussowitsch     PetscCall(MatMult(A, x, s1));  /* s1 = A*x */
6099566063dSJacob Faibussowitsch     PetscCall(VecAXPY(s2, a, s1)); /* s2 = a s1 + s2 */
61086919fd6SHong Zhang 
61186919fd6SHong Zhang     /* s1 = A * (a x + y) */
6129566063dSJacob Faibussowitsch     PetscCall(VecAXPY(y, a, x)); /* y = a x + y */
6139566063dSJacob Faibussowitsch     PetscCall(MatMult(A, y, s1));
6149566063dSJacob Faibussowitsch     PetscCall(VecNorm(s1, NORM_INFINITY, &normA));
61586919fd6SHong Zhang 
6169566063dSJacob Faibussowitsch     PetscCall(VecAXPY(s2, -1.0, s1)); /* s2 = - s1 + s2 */
6179566063dSJacob Faibussowitsch     PetscCall(VecNorm(s2, NORM_INFINITY, &norm));
6181b8dac88SHong Zhang     if (norm / normA > 100. * PETSC_MACHINE_EPSILON) {
61986919fd6SHong Zhang       *flg = PETSC_FALSE;
620835f2295SStefano Zampini       PetscCall(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)));
62186919fd6SHong Zhang       break;
62286919fd6SHong Zhang     }
62386919fd6SHong Zhang   }
6249566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rctx));
6259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
6269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
6279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s1));
6289566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&s2));
6293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63086919fd6SHong Zhang }
631