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 */ 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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 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 @*/ 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 @*/ 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 @*/ 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