1c4762a1bSJed Brown static char help[] = "Tests various routines for MATSHELL\n\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscmat.h> 4c4762a1bSJed Brown 5c4762a1bSJed Brown typedef struct _n_User *User; 6c4762a1bSJed Brown struct _n_User { 7c4762a1bSJed Brown Mat B; 8c4762a1bSJed Brown }; 9c4762a1bSJed Brown 10d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_User(Mat A, Vec X) 11d71ae5a4SJacob Faibussowitsch { 12c4762a1bSJed Brown User user; 13c4762a1bSJed Brown 14c4762a1bSJed Brown PetscFunctionBegin; 159566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &user)); 169566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(user->B, X)); 173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18c4762a1bSJed Brown } 19c4762a1bSJed Brown 20d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_User(Mat A, Vec X, Vec Y) 21d71ae5a4SJacob Faibussowitsch { 22c4762a1bSJed Brown User user; 23c4762a1bSJed Brown 24c4762a1bSJed Brown PetscFunctionBegin; 259566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &user)); 269566063dSJacob Faibussowitsch PetscCall(MatMult(user->B, X, Y)); 273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28c4762a1bSJed Brown } 29c4762a1bSJed Brown 30d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_User(Mat A, Vec X, Vec Y) 31d71ae5a4SJacob Faibussowitsch { 32c4762a1bSJed Brown User user; 33c4762a1bSJed Brown 34c4762a1bSJed Brown PetscFunctionBegin; 359566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &user)); 369566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(user->B, X, Y)); 373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38c4762a1bSJed Brown } 39c4762a1bSJed Brown 40d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_User(Mat A, Mat X, MatStructure str) 41d71ae5a4SJacob Faibussowitsch { 42c4762a1bSJed Brown User user, userX; 43c4762a1bSJed Brown 44c4762a1bSJed Brown PetscFunctionBegin; 459566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &user)); 469566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(X, &userX)); 4708401ef6SPierre Jolivet PetscCheck(user == userX, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "This should not happen"); 489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)user->B)); 493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50c4762a1bSJed Brown } 51c4762a1bSJed Brown 52d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_User(Mat A) 53d71ae5a4SJacob Faibussowitsch { 54c4762a1bSJed Brown User user; 55c4762a1bSJed Brown 56c4762a1bSJed Brown PetscFunctionBegin; 579566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &user)); 589566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)user->B)); 593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60c4762a1bSJed Brown } 61c4762a1bSJed Brown 62d71ae5a4SJacob Faibussowitsch int main(int argc, char **args) 63d71ae5a4SJacob Faibussowitsch { 64c4762a1bSJed Brown User user; 65c4762a1bSJed Brown Mat A, S; 66c4762a1bSJed Brown PetscScalar *data, diag = 1.3; 67c4762a1bSJed Brown PetscReal tol = PETSC_SMALL; 68c4762a1bSJed Brown PetscInt i, j, m = PETSC_DECIDE, n = PETSC_DECIDE, M = 17, N = 15, s1, s2; 69c4762a1bSJed Brown PetscInt test, ntest = 2; 70c4762a1bSJed Brown PetscMPIInt rank, size; 71c4762a1bSJed Brown PetscBool nc = PETSC_FALSE, cong, flg; 72c4762a1bSJed Brown PetscBool ronl = PETSC_TRUE; 73c4762a1bSJed Brown PetscBool randomize = PETSC_FALSE, submat = PETSC_FALSE; 74c4762a1bSJed Brown PetscBool keep = PETSC_FALSE; 75c4762a1bSJed Brown PetscBool testzerorows = PETSC_TRUE, testdiagscale = PETSC_TRUE, testgetdiag = PETSC_TRUE, testsubmat = PETSC_TRUE; 76c4762a1bSJed Brown PetscBool testshift = PETSC_TRUE, testscale = PETSC_TRUE, testdup = PETSC_TRUE, testreset = PETSC_TRUE; 77c4762a1bSJed Brown PetscBool testaxpy = PETSC_TRUE, testaxpyd = PETSC_TRUE, testaxpyerr = PETSC_FALSE; 78c4762a1bSJed Brown 79327415f7SBarry Smith PetscFunctionBeginUser; 80c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &args, NULL, help)); 819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL)); 849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL)); 859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-ml", &m, NULL)); 869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-nl", &n, NULL)); 879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-square_nc", &nc, NULL)); 889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-rows_only", &ronl, NULL)); 899566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-randomize", &randomize, NULL)); 909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-submat", &submat, NULL)); 919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_zerorows", &testzerorows, NULL)); 929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_diagscale", &testdiagscale, NULL)); 939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_getdiag", &testgetdiag, NULL)); 949566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_shift", &testshift, NULL)); 959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_scale", &testscale, NULL)); 969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_dup", &testdup, NULL)); 979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_reset", &testreset, NULL)); 989566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_submat", &testsubmat, NULL)); 999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_axpy", &testaxpy, NULL)); 1009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_axpy_different", &testaxpyd, NULL)); 1019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_axpy_error", &testaxpyerr, NULL)); 1029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-loop", &ntest, NULL)); 1039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-tol", &tol, NULL)); 1049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetScalar(NULL, NULL, "-diag", &diag, NULL)); 1059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-keep", &keep, NULL)); 106c4762a1bSJed Brown /* This tests square matrices with different row/col layout */ 107c4762a1bSJed Brown if (nc && size > 1) { 108c4762a1bSJed Brown M = PetscMax(PetscMax(N, M), 1); 109c4762a1bSJed Brown N = M; 110c4762a1bSJed Brown m = n = 0; 1119371c9d4SSatish Balay if (rank == 0) { 1129371c9d4SSatish Balay m = M - 1; 1139371c9d4SSatish Balay n = 1; 1149371c9d4SSatish Balay } else if (rank == 1) { 1159371c9d4SSatish Balay m = 1; 1169371c9d4SSatish Balay n = N - 1; 1179371c9d4SSatish Balay } 118c4762a1bSJed Brown } 1199566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, n, M, N, NULL, &A)); 1209566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 1219566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 1229566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &s1, NULL)); 123c4762a1bSJed Brown s2 = 1; 124c4762a1bSJed Brown while (s2 < M) s2 *= 10; 1259566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A, &data)); 126c4762a1bSJed Brown for (j = 0; j < N; j++) { 127f8e07d23SBlanca Mellado Pinto #if defined(PETSC_USE_COMPLEX) 128f8e07d23SBlanca Mellado Pinto for (i = 0; i < m; i++) data[j * m + i] = s2 * j + i + s1 + 1 + PETSC_i * (s1 - 1); 129f8e07d23SBlanca Mellado Pinto #else 130ad540459SPierre Jolivet for (i = 0; i < m; i++) data[j * m + i] = s2 * j + i + s1 + 1; 131f8e07d23SBlanca Mellado Pinto #endif 132c4762a1bSJed Brown } 1339566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 1349566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 135c4762a1bSJed Brown 136c4762a1bSJed Brown if (submat) { 137c4762a1bSJed Brown Mat A2; 138c4762a1bSJed Brown IS r, c; 139c4762a1bSJed Brown PetscInt rst, ren, cst, cen; 140c4762a1bSJed Brown 1419566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 1429566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &cst, &cen)); 1439566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (ren - rst) / 2, rst, 1, &r)); 1449566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (cen - cst) / 2, cst, 1, &c)); 1459566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, r, c, MAT_INITIAL_MATRIX, &A2)); 1469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&r)); 1479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&c)); 1489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 149c4762a1bSJed Brown A = A2; 150c4762a1bSJed Brown } 151c4762a1bSJed Brown 1529566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 1539566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 1549566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 155c4762a1bSJed Brown 1569566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATAIJ, MAT_INPLACE_MATRIX, &A)); 1579566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_KEEP_NONZERO_PATTERN, keep)); 1589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)A, "initial")); 1599566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(A, NULL, "-view_mat")); 160c4762a1bSJed Brown 1619566063dSJacob Faibussowitsch PetscCall(PetscNew(&user)); 1629566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, m, n, M, N, user, &S)); 16357d50842SBarry Smith PetscCall(MatShellSetOperation(S, MATOP_MULT, (PetscErrorCodeFn *)MatMult_User)); 16457d50842SBarry Smith PetscCall(MatShellSetOperation(S, MATOP_MULT_TRANSPOSE, (PetscErrorCodeFn *)MatMultTranspose_User)); 16557d50842SBarry Smith if (cong) PetscCall(MatShellSetOperation(S, MATOP_GET_DIAGONAL, (PetscErrorCodeFn *)MatGetDiagonal_User)); 16657d50842SBarry Smith PetscCall(MatShellSetOperation(S, MATOP_COPY, (PetscErrorCodeFn *)MatCopy_User)); 16757d50842SBarry Smith PetscCall(MatShellSetOperation(S, MATOP_DESTROY, (PetscErrorCodeFn *)MatDestroy_User)); 1689566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &user->B)); 169c4762a1bSJed Brown 170c4762a1bSJed Brown /* Square and rows only scaling */ 171c4762a1bSJed Brown ronl = cong ? ronl : PETSC_TRUE; 172c4762a1bSJed Brown 173c4762a1bSJed Brown for (test = 0; test < ntest; test++) { 174c4762a1bSJed Brown PetscReal err; 175c4762a1bSJed Brown 1769566063dSJacob Faibussowitsch PetscCall(MatMultAddEqual(A, S, 10, &flg)); 17748a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mult add\n", test)); 1789566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAddEqual(A, S, 10, &flg)); 179f8e07d23SBlanca Mellado Pinto if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mult transpose add\n", test)); 180f8e07d23SBlanca Mellado Pinto PetscCall(MatMultHermitianTransposeAddEqual(A, S, 10, &flg)); 181*b0c98d1dSPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mult Hermitian transpose add\n", test)); 182c4762a1bSJed Brown if (testzerorows) { 183c4762a1bSJed Brown Mat ST, B, C, BT, BTT; 184c4762a1bSJed Brown IS zr; 185c4762a1bSJed Brown Vec x = NULL, b1 = NULL, b2 = NULL; 186c4762a1bSJed Brown PetscInt *idxs = NULL, nr = 0; 187c4762a1bSJed Brown 188c4762a1bSJed Brown if (rank == (test % size)) { 189c4762a1bSJed Brown nr = 1; 1909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr, &idxs)); 191c4762a1bSJed Brown if (test % 2) { 192c4762a1bSJed Brown idxs[0] = (2 * M - 1 - test / 2) % M; 193c4762a1bSJed Brown } else { 194c4762a1bSJed Brown idxs[0] = (test / 2) % M; 195c4762a1bSJed Brown } 196c4762a1bSJed Brown idxs[0] = PetscMax(idxs[0], 0); 197c4762a1bSJed Brown } 1989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, nr, idxs, PETSC_OWN_POINTER, &zr)); 1999566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)zr, "ZR")); 2009566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(zr, NULL, "-view_is")); 2019566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &x, &b1)); 202c4762a1bSJed Brown if (randomize) { 2039566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 2049566063dSJacob Faibussowitsch PetscCall(VecSetRandom(b1, NULL)); 205c4762a1bSJed Brown } else { 2069566063dSJacob Faibussowitsch PetscCall(VecSet(x, 11.4)); 2079566063dSJacob Faibussowitsch PetscCall(VecSet(b1, -14.2)); 208c4762a1bSJed Brown } 2099566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b1, &b2)); 2109566063dSJacob Faibussowitsch PetscCall(VecCopy(b1, b2)); 2119566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)b1, "A_B1")); 2129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)b2, "A_B2")); 213c4762a1bSJed Brown if (size > 1 && !cong) { /* MATMPIAIJ ZeroRows and ZeroRowsColumns are buggy in this case */ 2149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b1)); 215c4762a1bSJed Brown } 216c4762a1bSJed Brown if (ronl) { 2179566063dSJacob Faibussowitsch PetscCall(MatZeroRowsIS(A, zr, diag, x, b1)); 2189566063dSJacob Faibussowitsch PetscCall(MatZeroRowsIS(S, zr, diag, x, b2)); 219c4762a1bSJed Brown } else { 2209566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(A, zr, diag, x, b1)); 2219566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(S, zr, diag, x, b2)); 2229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 223c4762a1bSJed Brown /* Mix zerorows and zerorowscols */ 224c4762a1bSJed Brown nr = 0; 225c4762a1bSJed Brown idxs = NULL; 226dd400576SPatrick Sanan if (rank == 0) { 227c4762a1bSJed Brown nr = 1; 2289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr, &idxs)); 229c4762a1bSJed Brown if (test % 2) { 230c4762a1bSJed Brown idxs[0] = (3 * M - 2 - test / 2) % M; 231c4762a1bSJed Brown } else { 232c4762a1bSJed Brown idxs[0] = (test / 2 + 1) % M; 233c4762a1bSJed Brown } 234c4762a1bSJed Brown idxs[0] = PetscMax(idxs[0], 0); 235c4762a1bSJed Brown } 2369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, nr, idxs, PETSC_OWN_POINTER, &zr)); 2379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)zr, "ZR2")); 2389566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(zr, NULL, "-view_is")); 2399566063dSJacob Faibussowitsch PetscCall(MatZeroRowsIS(A, zr, diag * 2.0 + PETSC_SMALL, NULL, NULL)); 2409566063dSJacob Faibussowitsch PetscCall(MatZeroRowsIS(S, zr, diag * 2.0 + PETSC_SMALL, NULL, NULL)); 241c4762a1bSJed Brown } 2429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 243c4762a1bSJed Brown 244c4762a1bSJed Brown if (b1) { 245c4762a1bSJed Brown Vec b; 246c4762a1bSJed Brown 2479566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(b1, NULL, "-view_b")); 2489566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(b2, NULL, "-view_b")); 2499566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b1, &b)); 2509566063dSJacob Faibussowitsch PetscCall(VecCopy(b1, b)); 2519566063dSJacob Faibussowitsch PetscCall(VecAXPY(b, -1.0, b2)); 2529566063dSJacob Faibussowitsch PetscCall(VecNorm(b, NORM_INFINITY, &err)); 25348a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error b %g\n", test, (double)err)); 2549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b)); 255c4762a1bSJed Brown } 2569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b1)); 2579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b2)); 2589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 2599566063dSJacob Faibussowitsch PetscCall(MatConvert(S, MATDENSE, MAT_INITIAL_MATRIX, &B)); 260c4762a1bSJed Brown 2619566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(S, &ST)); 2629566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(ST, MATDENSE, &BT)); 2639566063dSJacob Faibussowitsch PetscCall(MatTranspose(BT, MAT_INITIAL_MATRIX, &BTT)); 2649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B, "S")); 2659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)BTT, "STT")); 2669566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATDENSE, MAT_INITIAL_MATRIX, &C)); 2679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)C, "A")); 268c4762a1bSJed Brown 2699566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(C, NULL, "-view_mat")); 2709566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(B, NULL, "-view_mat")); 2719566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(BTT, NULL, "-view_mat")); 272c4762a1bSJed Brown 2739566063dSJacob Faibussowitsch PetscCall(MatAXPY(C, -1.0, B, SAME_NONZERO_PATTERN)); 2749566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_FROBENIUS, &err)); 27548a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat mult after %s %g\n", test, ronl ? "MatZeroRows" : "MatZeroRowsColumns", (double)err)); 276c4762a1bSJed Brown 2779566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATDENSE, MAT_REUSE_MATRIX, &C)); 2789566063dSJacob Faibussowitsch PetscCall(MatAXPY(C, -1.0, BTT, SAME_NONZERO_PATTERN)); 2799566063dSJacob Faibussowitsch PetscCall(MatNorm(C, NORM_FROBENIUS, &err)); 28048a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat mult transpose after %s %g\n", test, ronl ? "MatZeroRows" : "MatZeroRowsColumns", (double)err)); 281c4762a1bSJed Brown 2829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ST)); 2839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&BTT)); 2849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&BT)); 2859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 2869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 287c4762a1bSJed Brown } 288c4762a1bSJed Brown if (testdiagscale) { /* MatDiagonalScale() */ 289c4762a1bSJed Brown Vec vr, vl; 290c4762a1bSJed Brown 2919566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &vr, &vl)); 292c4762a1bSJed Brown if (randomize) { 2939566063dSJacob Faibussowitsch PetscCall(VecSetRandom(vr, NULL)); 2949566063dSJacob Faibussowitsch PetscCall(VecSetRandom(vl, NULL)); 295c4762a1bSJed Brown } else { 2969566063dSJacob Faibussowitsch PetscCall(VecSet(vr, test % 2 ? 0.15 : 1.0 / 0.15)); 2979566063dSJacob Faibussowitsch PetscCall(VecSet(vl, test % 2 ? -1.2 : 1.0 / -1.2)); 298c4762a1bSJed Brown } 2999566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(A, vl, vr)); 3009566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(S, vl, vr)); 3019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vr)); 3029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vl)); 303c4762a1bSJed Brown } 304c4762a1bSJed Brown 305c4762a1bSJed Brown if (testscale) { /* MatScale() */ 3069566063dSJacob Faibussowitsch PetscCall(MatScale(A, test % 2 ? 1.4 : 1.0 / 1.4)); 3079566063dSJacob Faibussowitsch PetscCall(MatScale(S, test % 2 ? 1.4 : 1.0 / 1.4)); 308c4762a1bSJed Brown } 309c4762a1bSJed Brown 310c4762a1bSJed Brown if (testshift && cong) { /* MatShift() : MATSHELL shift is broken when row/cols layout are not congruent and left/right scaling have been applied */ 3119566063dSJacob Faibussowitsch PetscCall(MatShift(A, test % 2 ? -77.5 : 77.5)); 3129566063dSJacob Faibussowitsch PetscCall(MatShift(S, test % 2 ? -77.5 : 77.5)); 313c4762a1bSJed Brown } 314c4762a1bSJed Brown 315c4762a1bSJed Brown if (testgetdiag && cong) { /* MatGetDiagonal() */ 316c4762a1bSJed Brown Vec dA, dS; 317c4762a1bSJed Brown 3189566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &dA, NULL)); 3199566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(S, &dS, NULL)); 3209566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, dA)); 3219566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(S, dS)); 3229566063dSJacob Faibussowitsch PetscCall(VecAXPY(dA, -1.0, dS)); 3239566063dSJacob Faibussowitsch PetscCall(VecNorm(dA, NORM_INFINITY, &err)); 32448a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error diag %g\n", test, (double)err)); 3259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dA)); 3269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dS)); 327c4762a1bSJed Brown } 328c4762a1bSJed Brown 329c4762a1bSJed Brown if (testdup && !test) { 330c4762a1bSJed Brown Mat A2, S2; 331c4762a1bSJed Brown 3329566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2)); 3339566063dSJacob Faibussowitsch PetscCall(MatDuplicate(S, MAT_COPY_VALUES, &S2)); 3349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 3359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S)); 336c4762a1bSJed Brown A = A2; 337c4762a1bSJed Brown S = S2; 338c4762a1bSJed Brown } 339c4762a1bSJed Brown 340c4762a1bSJed Brown if (testsubmat) { 341c4762a1bSJed Brown Mat sA, sS, dA, dS, At, St; 342c4762a1bSJed Brown IS r, c; 343c4762a1bSJed Brown PetscInt rst, ren, cst, cen; 344c4762a1bSJed Brown 3459566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 3469566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &cst, &cen)); 3479566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (ren - rst) / 2, rst, 1, &r)); 3489566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (cen - cst) / 2, cst, 1, &c)); 3499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, r, c, MAT_INITIAL_MATRIX, &sA)); 3509566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(S, r, c, MAT_INITIAL_MATRIX, &sS)); 3519566063dSJacob Faibussowitsch PetscCall(MatMultAddEqual(sA, sS, 10, &flg)); 35248a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix mult add\n", test)); 3539566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAddEqual(sA, sS, 10, &flg)); 35448a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix mult add (T)\n", test)); 3559566063dSJacob Faibussowitsch PetscCall(MatConvert(sA, MATDENSE, MAT_INITIAL_MATRIX, &dA)); 3569566063dSJacob Faibussowitsch PetscCall(MatConvert(sS, MATDENSE, MAT_INITIAL_MATRIX, &dS)); 3579566063dSJacob Faibussowitsch PetscCall(MatAXPY(dA, -1.0, dS, SAME_NONZERO_PATTERN)); 3589566063dSJacob Faibussowitsch PetscCall(MatNorm(dA, NORM_FROBENIUS, &err)); 35948a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat submatrix %g\n", test, (double)err)); 3609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sA)); 3619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sS)); 3629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dA)); 3639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dS)); 3649566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A, &At)); 3659566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(S, &St)); 3669566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(At, c, r, MAT_INITIAL_MATRIX, &sA)); 3679566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(St, c, r, MAT_INITIAL_MATRIX, &sS)); 3689566063dSJacob Faibussowitsch PetscCall(MatMultAddEqual(sA, sS, 10, &flg)); 36948a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix (T) mult add\n", test)); 3709566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAddEqual(sA, sS, 10, &flg)); 37148a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix (T) mult add (T)\n", test)); 3729566063dSJacob Faibussowitsch PetscCall(MatConvert(sA, MATDENSE, MAT_INITIAL_MATRIX, &dA)); 3739566063dSJacob Faibussowitsch PetscCall(MatConvert(sS, MATDENSE, MAT_INITIAL_MATRIX, &dS)); 3749566063dSJacob Faibussowitsch PetscCall(MatAXPY(dA, -1.0, dS, SAME_NONZERO_PATTERN)); 3759566063dSJacob Faibussowitsch PetscCall(MatNorm(dA, NORM_FROBENIUS, &err)); 37648a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat submatrix (T) %g\n", test, (double)err)); 3779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sA)); 3789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sS)); 3799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dA)); 3809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dS)); 3819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&At)); 3829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&St)); 3839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&r)); 3849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&c)); 385c4762a1bSJed Brown } 386c4762a1bSJed Brown 387c4762a1bSJed Brown if (testaxpy) { 388c4762a1bSJed Brown Mat tA, tS, dA, dS; 389c4762a1bSJed Brown MatStructure str[3] = {SAME_NONZERO_PATTERN, SUBSET_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN}; 390c4762a1bSJed Brown 3919566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &tA)); 392c4762a1bSJed Brown if (testaxpyd && !(test % 2)) { 3939566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)tA)); 394c4762a1bSJed Brown tS = tA; 395c4762a1bSJed Brown } else { 3969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S)); 397c4762a1bSJed Brown tS = S; 398c4762a1bSJed Brown } 3999566063dSJacob Faibussowitsch PetscCall(MatAXPY(A, 0.5, tA, str[test % 3])); 4009566063dSJacob Faibussowitsch PetscCall(MatAXPY(S, 0.5, tS, str[test % 3])); 401c4762a1bSJed Brown /* this will trigger an error the next MatMult or MatMultTranspose call for S */ 4029566063dSJacob Faibussowitsch if (testaxpyerr) PetscCall(MatScale(tA, 0)); 4039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tA)); 4049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tS)); 4059566063dSJacob Faibussowitsch PetscCall(MatMultAddEqual(A, S, 10, &flg)); 40648a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error axpy mult add\n", test)); 4079566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAddEqual(A, S, 10, &flg)); 40848a46eb9SPierre Jolivet if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error axpy mult add (T)\n", test)); 4099566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATDENSE, MAT_INITIAL_MATRIX, &dA)); 4109566063dSJacob Faibussowitsch PetscCall(MatConvert(S, MATDENSE, MAT_INITIAL_MATRIX, &dS)); 4119566063dSJacob Faibussowitsch PetscCall(MatAXPY(dA, -1.0, dS, SAME_NONZERO_PATTERN)); 4129566063dSJacob Faibussowitsch PetscCall(MatNorm(dA, NORM_FROBENIUS, &err)); 41348a46eb9SPierre Jolivet if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat submatrix %g\n", test, (double)err)); 4149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dA)); 4159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dS)); 416c4762a1bSJed Brown } 417c4762a1bSJed Brown 418c4762a1bSJed Brown if (testreset && (ntest == 1 || test == ntest - 2)) { 419c4762a1bSJed Brown /* reset MATSHELL */ 4209566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY)); 4219566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY)); 422c4762a1bSJed Brown /* reset A */ 4239566063dSJacob Faibussowitsch PetscCall(MatCopy(user->B, A, DIFFERENT_NONZERO_PATTERN)); 424c4762a1bSJed Brown } 425c4762a1bSJed Brown } 426c4762a1bSJed Brown 4279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 4289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S)); 4299566063dSJacob Faibussowitsch PetscCall(PetscFree(user)); 4309566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 431b122ec5aSJacob Faibussowitsch return 0; 432c4762a1bSJed Brown } 433c4762a1bSJed Brown 434c4762a1bSJed Brown /*TEST 435c4762a1bSJed Brown 436c4762a1bSJed Brown testset: 437c4762a1bSJed Brown suffix: rect 438c4762a1bSJed Brown requires: !single 4393886731fSPierre Jolivet output_file: output/empty.out 440c4762a1bSJed Brown nsize: {{1 3}} 441c4762a1bSJed Brown args: -loop 3 -keep {{0 1}} -M {{12 19}} -N {{19 12}} -submat {{0 1}} -test_axpy_different {{0 1}} 442c4762a1bSJed Brown 443c4762a1bSJed Brown testset: 444c4762a1bSJed Brown suffix: square 445c4762a1bSJed Brown requires: !single 4463886731fSPierre Jolivet output_file: output/empty.out 447c4762a1bSJed Brown nsize: {{1 3}} 448c4762a1bSJed Brown args: -M 21 -N 21 -loop 4 -rows_only {{0 1}} -keep {{0 1}} -submat {{0 1}} -test_axpy_different {{0 1}} 449c4762a1bSJed Brown TEST*/ 450