xref: /petsc/src/mat/tests/ex221.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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 
109371c9d4SSatish Balay static PetscErrorCode MatGetDiagonal_User(Mat A, Vec X) {
11c4762a1bSJed Brown   User user;
12c4762a1bSJed Brown 
13c4762a1bSJed Brown   PetscFunctionBegin;
149566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A, &user));
159566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(user->B, X));
16c4762a1bSJed Brown   PetscFunctionReturn(0);
17c4762a1bSJed Brown }
18c4762a1bSJed Brown 
199371c9d4SSatish Balay static PetscErrorCode MatMult_User(Mat A, Vec X, Vec Y) {
20c4762a1bSJed Brown   User user;
21c4762a1bSJed Brown 
22c4762a1bSJed Brown   PetscFunctionBegin;
239566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A, &user));
249566063dSJacob Faibussowitsch   PetscCall(MatMult(user->B, X, Y));
25c4762a1bSJed Brown   PetscFunctionReturn(0);
26c4762a1bSJed Brown }
27c4762a1bSJed Brown 
289371c9d4SSatish Balay static PetscErrorCode MatMultTranspose_User(Mat A, Vec X, Vec Y) {
29c4762a1bSJed Brown   User user;
30c4762a1bSJed Brown 
31c4762a1bSJed Brown   PetscFunctionBegin;
329566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A, &user));
339566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(user->B, X, Y));
34c4762a1bSJed Brown   PetscFunctionReturn(0);
35c4762a1bSJed Brown }
36c4762a1bSJed Brown 
379371c9d4SSatish Balay static PetscErrorCode MatCopy_User(Mat A, Mat X, MatStructure str) {
38c4762a1bSJed Brown   User user, userX;
39c4762a1bSJed Brown 
40c4762a1bSJed Brown   PetscFunctionBegin;
419566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A, &user));
429566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(X, &userX));
4308401ef6SPierre Jolivet   PetscCheck(user == userX, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "This should not happen");
449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)user->B));
45c4762a1bSJed Brown   PetscFunctionReturn(0);
46c4762a1bSJed Brown }
47c4762a1bSJed Brown 
489371c9d4SSatish Balay static PetscErrorCode MatDestroy_User(Mat A) {
49c4762a1bSJed Brown   User user;
50c4762a1bSJed Brown 
51c4762a1bSJed Brown   PetscFunctionBegin;
529566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(A, &user));
539566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)user->B));
54c4762a1bSJed Brown   PetscFunctionReturn(0);
55c4762a1bSJed Brown }
56c4762a1bSJed Brown 
579371c9d4SSatish Balay int main(int argc, char **args) {
58c4762a1bSJed Brown   User         user;
59c4762a1bSJed Brown   Mat          A, S;
60c4762a1bSJed Brown   PetscScalar *data, diag = 1.3;
61c4762a1bSJed Brown   PetscReal    tol = PETSC_SMALL;
62c4762a1bSJed Brown   PetscInt     i, j, m = PETSC_DECIDE, n = PETSC_DECIDE, M = 17, N = 15, s1, s2;
63c4762a1bSJed Brown   PetscInt     test, ntest = 2;
64c4762a1bSJed Brown   PetscMPIInt  rank, size;
65c4762a1bSJed Brown   PetscBool    nc        = PETSC_FALSE, cong, flg;
66c4762a1bSJed Brown   PetscBool    ronl      = PETSC_TRUE;
67c4762a1bSJed Brown   PetscBool    randomize = PETSC_FALSE, submat = PETSC_FALSE;
68c4762a1bSJed Brown   PetscBool    keep         = PETSC_FALSE;
69c4762a1bSJed Brown   PetscBool    testzerorows = PETSC_TRUE, testdiagscale = PETSC_TRUE, testgetdiag = PETSC_TRUE, testsubmat = PETSC_TRUE;
70c4762a1bSJed Brown   PetscBool    testshift = PETSC_TRUE, testscale = PETSC_TRUE, testdup = PETSC_TRUE, testreset = PETSC_TRUE;
71c4762a1bSJed Brown   PetscBool    testaxpy = PETSC_TRUE, testaxpyd = PETSC_TRUE, testaxpyerr = PETSC_FALSE;
72c4762a1bSJed Brown 
73327415f7SBarry Smith   PetscFunctionBeginUser;
749566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL));
789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL));
799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-ml", &m, NULL));
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-nl", &n, NULL));
819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-square_nc", &nc, NULL));
829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-rows_only", &ronl, NULL));
839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-randomize", &randomize, NULL));
849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-submat", &submat, NULL));
859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_zerorows", &testzerorows, NULL));
869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_diagscale", &testdiagscale, NULL));
879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_getdiag", &testgetdiag, NULL));
889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_shift", &testshift, NULL));
899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_scale", &testscale, NULL));
909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_dup", &testdup, NULL));
919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_reset", &testreset, NULL));
929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_submat", &testsubmat, NULL));
939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_axpy", &testaxpy, NULL));
949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_axpy_different", &testaxpyd, NULL));
959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_axpy_error", &testaxpyerr, NULL));
969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-loop", &ntest, NULL));
979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL, NULL, "-tol", &tol, NULL));
989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetScalar(NULL, NULL, "-diag", &diag, NULL));
999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-keep", &keep, NULL));
100c4762a1bSJed Brown   /* This tests square matrices with different row/col layout */
101c4762a1bSJed Brown   if (nc && size > 1) {
102c4762a1bSJed Brown     M = PetscMax(PetscMax(N, M), 1);
103c4762a1bSJed Brown     N = M;
104c4762a1bSJed Brown     m = n = 0;
1059371c9d4SSatish Balay     if (rank == 0) {
1069371c9d4SSatish Balay       m = M - 1;
1079371c9d4SSatish Balay       n = 1;
1089371c9d4SSatish Balay     } else if (rank == 1) {
1099371c9d4SSatish Balay       m = 1;
1109371c9d4SSatish Balay       n = N - 1;
1119371c9d4SSatish Balay     }
112c4762a1bSJed Brown   }
1139566063dSJacob Faibussowitsch   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, n, M, N, NULL, &A));
1149566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
1159566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M, &N));
1169566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &s1, NULL));
117c4762a1bSJed Brown   s2 = 1;
118c4762a1bSJed Brown   while (s2 < M) s2 *= 10;
1199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &data));
120c4762a1bSJed Brown   for (j = 0; j < N; j++) {
1219371c9d4SSatish Balay     for (i = 0; i < m; i++) { data[j * m + i] = s2 * j + i + s1 + 1; }
122c4762a1bSJed Brown   }
1239566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1249566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
125c4762a1bSJed Brown 
126c4762a1bSJed Brown   if (submat) {
127c4762a1bSJed Brown     Mat      A2;
128c4762a1bSJed Brown     IS       r, c;
129c4762a1bSJed Brown     PetscInt rst, ren, cst, cen;
130c4762a1bSJed Brown 
1319566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(A, &rst, &ren));
1329566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRangeColumn(A, &cst, &cen));
1339566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (ren - rst) / 2, rst, 1, &r));
1349566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (cen - cst) / 2, cst, 1, &c));
1359566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(A, r, c, MAT_INITIAL_MATRIX, &A2));
1369566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&r));
1379566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&c));
1389566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
139c4762a1bSJed Brown     A = A2;
140c4762a1bSJed Brown   }
141c4762a1bSJed Brown 
1429566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M, &N));
1439566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
1449566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
145c4762a1bSJed Brown 
1469566063dSJacob Faibussowitsch   PetscCall(MatConvert(A, MATAIJ, MAT_INPLACE_MATRIX, &A));
1479566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_KEEP_NONZERO_PATTERN, keep));
1489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)A, "initial"));
1499566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(A, NULL, "-view_mat"));
150c4762a1bSJed Brown 
1519566063dSJacob Faibussowitsch   PetscCall(PetscNew(&user));
1529566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(PETSC_COMM_WORLD, m, n, M, N, user, &S));
1539566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(S, MATOP_MULT, (void (*)(void))MatMult_User));
1549566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(S, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_User));
1551baa6e33SBarry Smith   if (cong) PetscCall(MatShellSetOperation(S, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_User));
1569566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(S, MATOP_COPY, (void (*)(void))MatCopy_User));
1579566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(S, MATOP_DESTROY, (void (*)(void))MatDestroy_User));
1589566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &user->B));
159c4762a1bSJed Brown 
160c4762a1bSJed Brown   /* Square and rows only scaling */
161c4762a1bSJed Brown   ronl = cong ? ronl : PETSC_TRUE;
162c4762a1bSJed Brown 
163c4762a1bSJed Brown   for (test = 0; test < ntest; test++) {
164c4762a1bSJed Brown     PetscReal err;
165c4762a1bSJed Brown 
1669566063dSJacob Faibussowitsch     PetscCall(MatMultAddEqual(A, S, 10, &flg));
167*48a46eb9SPierre Jolivet     if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mult add\n", test));
1689566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAddEqual(A, S, 10, &flg));
169*48a46eb9SPierre Jolivet     if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mult add (T)\n", test));
170c4762a1bSJed Brown     if (testzerorows) {
171c4762a1bSJed Brown       Mat       ST, B, C, BT, BTT;
172c4762a1bSJed Brown       IS        zr;
173c4762a1bSJed Brown       Vec       x = NULL, b1 = NULL, b2 = NULL;
174c4762a1bSJed Brown       PetscInt *idxs = NULL, nr = 0;
175c4762a1bSJed Brown 
176c4762a1bSJed Brown       if (rank == (test % size)) {
177c4762a1bSJed Brown         nr = 1;
1789566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nr, &idxs));
179c4762a1bSJed Brown         if (test % 2) {
180c4762a1bSJed Brown           idxs[0] = (2 * M - 1 - test / 2) % M;
181c4762a1bSJed Brown         } else {
182c4762a1bSJed Brown           idxs[0] = (test / 2) % M;
183c4762a1bSJed Brown         }
184c4762a1bSJed Brown         idxs[0] = PetscMax(idxs[0], 0);
185c4762a1bSJed Brown       }
1869566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, nr, idxs, PETSC_OWN_POINTER, &zr));
1879566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)zr, "ZR"));
1889566063dSJacob Faibussowitsch       PetscCall(ISViewFromOptions(zr, NULL, "-view_is"));
1899566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(A, &x, &b1));
190c4762a1bSJed Brown       if (randomize) {
1919566063dSJacob Faibussowitsch         PetscCall(VecSetRandom(x, NULL));
1929566063dSJacob Faibussowitsch         PetscCall(VecSetRandom(b1, NULL));
193c4762a1bSJed Brown       } else {
1949566063dSJacob Faibussowitsch         PetscCall(VecSet(x, 11.4));
1959566063dSJacob Faibussowitsch         PetscCall(VecSet(b1, -14.2));
196c4762a1bSJed Brown       }
1979566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b1, &b2));
1989566063dSJacob Faibussowitsch       PetscCall(VecCopy(b1, b2));
1999566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)b1, "A_B1"));
2009566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)b2, "A_B2"));
201c4762a1bSJed Brown       if (size > 1 && !cong) { /* MATMPIAIJ ZeroRows and ZeroRowsColumns are buggy in this case */
2029566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&b1));
203c4762a1bSJed Brown       }
204c4762a1bSJed Brown       if (ronl) {
2059566063dSJacob Faibussowitsch         PetscCall(MatZeroRowsIS(A, zr, diag, x, b1));
2069566063dSJacob Faibussowitsch         PetscCall(MatZeroRowsIS(S, zr, diag, x, b2));
207c4762a1bSJed Brown       } else {
2089566063dSJacob Faibussowitsch         PetscCall(MatZeroRowsColumnsIS(A, zr, diag, x, b1));
2099566063dSJacob Faibussowitsch         PetscCall(MatZeroRowsColumnsIS(S, zr, diag, x, b2));
2109566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&zr));
211c4762a1bSJed Brown         /* Mix zerorows and zerorowscols */
212c4762a1bSJed Brown         nr   = 0;
213c4762a1bSJed Brown         idxs = NULL;
214dd400576SPatrick Sanan         if (rank == 0) {
215c4762a1bSJed Brown           nr = 1;
2169566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(nr, &idxs));
217c4762a1bSJed Brown           if (test % 2) {
218c4762a1bSJed Brown             idxs[0] = (3 * M - 2 - test / 2) % M;
219c4762a1bSJed Brown           } else {
220c4762a1bSJed Brown             idxs[0] = (test / 2 + 1) % M;
221c4762a1bSJed Brown           }
222c4762a1bSJed Brown           idxs[0] = PetscMax(idxs[0], 0);
223c4762a1bSJed Brown         }
2249566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, nr, idxs, PETSC_OWN_POINTER, &zr));
2259566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)zr, "ZR2"));
2269566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(zr, NULL, "-view_is"));
2279566063dSJacob Faibussowitsch         PetscCall(MatZeroRowsIS(A, zr, diag * 2.0 + PETSC_SMALL, NULL, NULL));
2289566063dSJacob Faibussowitsch         PetscCall(MatZeroRowsIS(S, zr, diag * 2.0 + PETSC_SMALL, NULL, NULL));
229c4762a1bSJed Brown       }
2309566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zr));
231c4762a1bSJed Brown 
232c4762a1bSJed Brown       if (b1) {
233c4762a1bSJed Brown         Vec b;
234c4762a1bSJed Brown 
2359566063dSJacob Faibussowitsch         PetscCall(VecViewFromOptions(b1, NULL, "-view_b"));
2369566063dSJacob Faibussowitsch         PetscCall(VecViewFromOptions(b2, NULL, "-view_b"));
2379566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(b1, &b));
2389566063dSJacob Faibussowitsch         PetscCall(VecCopy(b1, b));
2399566063dSJacob Faibussowitsch         PetscCall(VecAXPY(b, -1.0, b2));
2409566063dSJacob Faibussowitsch         PetscCall(VecNorm(b, NORM_INFINITY, &err));
241*48a46eb9SPierre Jolivet         if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error b %g\n", test, (double)err));
2429566063dSJacob Faibussowitsch         PetscCall(VecDestroy(&b));
243c4762a1bSJed Brown       }
2449566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&b1));
2459566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&b2));
2469566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&x));
2479566063dSJacob Faibussowitsch       PetscCall(MatConvert(S, MATDENSE, MAT_INITIAL_MATRIX, &B));
248c4762a1bSJed Brown 
2499566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(S, &ST));
2509566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(ST, MATDENSE, &BT));
2519566063dSJacob Faibussowitsch       PetscCall(MatTranspose(BT, MAT_INITIAL_MATRIX, &BTT));
2529566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)B, "S"));
2539566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)BTT, "STT"));
2549566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATDENSE, MAT_INITIAL_MATRIX, &C));
2559566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)C, "A"));
256c4762a1bSJed Brown 
2579566063dSJacob Faibussowitsch       PetscCall(MatViewFromOptions(C, NULL, "-view_mat"));
2589566063dSJacob Faibussowitsch       PetscCall(MatViewFromOptions(B, NULL, "-view_mat"));
2599566063dSJacob Faibussowitsch       PetscCall(MatViewFromOptions(BTT, NULL, "-view_mat"));
260c4762a1bSJed Brown 
2619566063dSJacob Faibussowitsch       PetscCall(MatAXPY(C, -1.0, B, SAME_NONZERO_PATTERN));
2629566063dSJacob Faibussowitsch       PetscCall(MatNorm(C, NORM_FROBENIUS, &err));
263*48a46eb9SPierre 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));
264c4762a1bSJed Brown 
2659566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATDENSE, MAT_REUSE_MATRIX, &C));
2669566063dSJacob Faibussowitsch       PetscCall(MatAXPY(C, -1.0, BTT, SAME_NONZERO_PATTERN));
2679566063dSJacob Faibussowitsch       PetscCall(MatNorm(C, NORM_FROBENIUS, &err));
268*48a46eb9SPierre 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));
269c4762a1bSJed Brown 
2709566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&ST));
2719566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&BTT));
2729566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&BT));
2739566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B));
2749566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
275c4762a1bSJed Brown     }
276c4762a1bSJed Brown     if (testdiagscale) { /* MatDiagonalScale() */
277c4762a1bSJed Brown       Vec vr, vl;
278c4762a1bSJed Brown 
2799566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(A, &vr, &vl));
280c4762a1bSJed Brown       if (randomize) {
2819566063dSJacob Faibussowitsch         PetscCall(VecSetRandom(vr, NULL));
2829566063dSJacob Faibussowitsch         PetscCall(VecSetRandom(vl, NULL));
283c4762a1bSJed Brown       } else {
2849566063dSJacob Faibussowitsch         PetscCall(VecSet(vr, test % 2 ? 0.15 : 1.0 / 0.15));
2859566063dSJacob Faibussowitsch         PetscCall(VecSet(vl, test % 2 ? -1.2 : 1.0 / -1.2));
286c4762a1bSJed Brown       }
2879566063dSJacob Faibussowitsch       PetscCall(MatDiagonalScale(A, vl, vr));
2889566063dSJacob Faibussowitsch       PetscCall(MatDiagonalScale(S, vl, vr));
2899566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&vr));
2909566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&vl));
291c4762a1bSJed Brown     }
292c4762a1bSJed Brown 
293c4762a1bSJed Brown     if (testscale) { /* MatScale() */
2949566063dSJacob Faibussowitsch       PetscCall(MatScale(A, test % 2 ? 1.4 : 1.0 / 1.4));
2959566063dSJacob Faibussowitsch       PetscCall(MatScale(S, test % 2 ? 1.4 : 1.0 / 1.4));
296c4762a1bSJed Brown     }
297c4762a1bSJed Brown 
298c4762a1bSJed Brown     if (testshift && cong) { /* MatShift() : MATSHELL shift is broken when row/cols layout are not congruent and left/right scaling have been applied */
2999566063dSJacob Faibussowitsch       PetscCall(MatShift(A, test % 2 ? -77.5 : 77.5));
3009566063dSJacob Faibussowitsch       PetscCall(MatShift(S, test % 2 ? -77.5 : 77.5));
301c4762a1bSJed Brown     }
302c4762a1bSJed Brown 
303c4762a1bSJed Brown     if (testgetdiag && cong) { /* MatGetDiagonal() */
304c4762a1bSJed Brown       Vec dA, dS;
305c4762a1bSJed Brown 
3069566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(A, &dA, NULL));
3079566063dSJacob Faibussowitsch       PetscCall(MatCreateVecs(S, &dS, NULL));
3089566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(A, dA));
3099566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(S, dS));
3109566063dSJacob Faibussowitsch       PetscCall(VecAXPY(dA, -1.0, dS));
3119566063dSJacob Faibussowitsch       PetscCall(VecNorm(dA, NORM_INFINITY, &err));
312*48a46eb9SPierre Jolivet       if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error diag %g\n", test, (double)err));
3139566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&dA));
3149566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&dS));
315c4762a1bSJed Brown     }
316c4762a1bSJed Brown 
317c4762a1bSJed Brown     if (testdup && !test) {
318c4762a1bSJed Brown       Mat A2, S2;
319c4762a1bSJed Brown 
3209566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
3219566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(S, MAT_COPY_VALUES, &S2));
3229566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A));
3239566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&S));
324c4762a1bSJed Brown       A = A2;
325c4762a1bSJed Brown       S = S2;
326c4762a1bSJed Brown     }
327c4762a1bSJed Brown 
328c4762a1bSJed Brown     if (testsubmat) {
329c4762a1bSJed Brown       Mat      sA, sS, dA, dS, At, St;
330c4762a1bSJed Brown       IS       r, c;
331c4762a1bSJed Brown       PetscInt rst, ren, cst, cen;
332c4762a1bSJed Brown 
3339566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(A, &rst, &ren));
3349566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRangeColumn(A, &cst, &cen));
3359566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (ren - rst) / 2, rst, 1, &r));
3369566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), (cen - cst) / 2, cst, 1, &c));
3379566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(A, r, c, MAT_INITIAL_MATRIX, &sA));
3389566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(S, r, c, MAT_INITIAL_MATRIX, &sS));
3399566063dSJacob Faibussowitsch       PetscCall(MatMultAddEqual(sA, sS, 10, &flg));
340*48a46eb9SPierre Jolivet       if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix mult add\n", test));
3419566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAddEqual(sA, sS, 10, &flg));
342*48a46eb9SPierre Jolivet       if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix mult add (T)\n", test));
3439566063dSJacob Faibussowitsch       PetscCall(MatConvert(sA, MATDENSE, MAT_INITIAL_MATRIX, &dA));
3449566063dSJacob Faibussowitsch       PetscCall(MatConvert(sS, MATDENSE, MAT_INITIAL_MATRIX, &dS));
3459566063dSJacob Faibussowitsch       PetscCall(MatAXPY(dA, -1.0, dS, SAME_NONZERO_PATTERN));
3469566063dSJacob Faibussowitsch       PetscCall(MatNorm(dA, NORM_FROBENIUS, &err));
347*48a46eb9SPierre Jolivet       if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat submatrix %g\n", test, (double)err));
3489566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&sA));
3499566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&sS));
3509566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&dA));
3519566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&dS));
3529566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(A, &At));
3539566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(S, &St));
3549566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(At, c, r, MAT_INITIAL_MATRIX, &sA));
3559566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(St, c, r, MAT_INITIAL_MATRIX, &sS));
3569566063dSJacob Faibussowitsch       PetscCall(MatMultAddEqual(sA, sS, 10, &flg));
357*48a46eb9SPierre Jolivet       if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix (T) mult add\n", test));
3589566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAddEqual(sA, sS, 10, &flg));
359*48a46eb9SPierre Jolivet       if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error submatrix (T) mult add (T)\n", test));
3609566063dSJacob Faibussowitsch       PetscCall(MatConvert(sA, MATDENSE, MAT_INITIAL_MATRIX, &dA));
3619566063dSJacob Faibussowitsch       PetscCall(MatConvert(sS, MATDENSE, MAT_INITIAL_MATRIX, &dS));
3629566063dSJacob Faibussowitsch       PetscCall(MatAXPY(dA, -1.0, dS, SAME_NONZERO_PATTERN));
3639566063dSJacob Faibussowitsch       PetscCall(MatNorm(dA, NORM_FROBENIUS, &err));
364*48a46eb9SPierre Jolivet       if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat submatrix (T) %g\n", test, (double)err));
3659566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&sA));
3669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&sS));
3679566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&dA));
3689566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&dS));
3699566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&At));
3709566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&St));
3719566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&r));
3729566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&c));
373c4762a1bSJed Brown     }
374c4762a1bSJed Brown 
375c4762a1bSJed Brown     if (testaxpy) {
376c4762a1bSJed Brown       Mat          tA, tS, dA, dS;
377c4762a1bSJed Brown       MatStructure str[3] = {SAME_NONZERO_PATTERN, SUBSET_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN};
378c4762a1bSJed Brown 
3799566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &tA));
380c4762a1bSJed Brown       if (testaxpyd && !(test % 2)) {
3819566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)tA));
382c4762a1bSJed Brown         tS = tA;
383c4762a1bSJed Brown       } else {
3849566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)S));
385c4762a1bSJed Brown         tS = S;
386c4762a1bSJed Brown       }
3879566063dSJacob Faibussowitsch       PetscCall(MatAXPY(A, 0.5, tA, str[test % 3]));
3889566063dSJacob Faibussowitsch       PetscCall(MatAXPY(S, 0.5, tS, str[test % 3]));
389c4762a1bSJed Brown       /* this will trigger an error the next MatMult or MatMultTranspose call for S */
3909566063dSJacob Faibussowitsch       if (testaxpyerr) PetscCall(MatScale(tA, 0));
3919566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tA));
3929566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&tS));
3939566063dSJacob Faibussowitsch       PetscCall(MatMultAddEqual(A, S, 10, &flg));
394*48a46eb9SPierre Jolivet       if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error axpy mult add\n", test));
3959566063dSJacob Faibussowitsch       PetscCall(MatMultTransposeAddEqual(A, S, 10, &flg));
396*48a46eb9SPierre Jolivet       if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error axpy mult add (T)\n", test));
3979566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATDENSE, MAT_INITIAL_MATRIX, &dA));
3989566063dSJacob Faibussowitsch       PetscCall(MatConvert(S, MATDENSE, MAT_INITIAL_MATRIX, &dS));
3999566063dSJacob Faibussowitsch       PetscCall(MatAXPY(dA, -1.0, dS, SAME_NONZERO_PATTERN));
4009566063dSJacob Faibussowitsch       PetscCall(MatNorm(dA, NORM_FROBENIUS, &err));
401*48a46eb9SPierre Jolivet       if (err >= tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[test %" PetscInt_FMT "] Error mat submatrix %g\n", test, (double)err));
4029566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&dA));
4039566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&dS));
404c4762a1bSJed Brown     }
405c4762a1bSJed Brown 
406c4762a1bSJed Brown     if (testreset && (ntest == 1 || test == ntest - 2)) {
407c4762a1bSJed Brown       /* reset MATSHELL */
4089566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY));
4099566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY));
410c4762a1bSJed Brown       /* reset A */
4119566063dSJacob Faibussowitsch       PetscCall(MatCopy(user->B, A, DIFFERENT_NONZERO_PATTERN));
412c4762a1bSJed Brown     }
413c4762a1bSJed Brown   }
414c4762a1bSJed Brown 
4159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
4169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&S));
4179566063dSJacob Faibussowitsch   PetscCall(PetscFree(user));
4189566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
419b122ec5aSJacob Faibussowitsch   return 0;
420c4762a1bSJed Brown }
421c4762a1bSJed Brown 
422c4762a1bSJed Brown /*TEST
423c4762a1bSJed Brown 
424c4762a1bSJed Brown    testset:
425c4762a1bSJed Brown      suffix: rect
426c4762a1bSJed Brown      requires: !single
427c4762a1bSJed Brown      output_file: output/ex221_1.out
428c4762a1bSJed Brown      nsize: {{1 3}}
429c4762a1bSJed Brown      args: -loop 3 -keep {{0 1}} -M {{12 19}} -N {{19 12}} -submat {{0 1}} -test_axpy_different {{0 1}}
430c4762a1bSJed Brown 
431c4762a1bSJed Brown    testset:
432c4762a1bSJed Brown      suffix: square
433c4762a1bSJed Brown      requires: !single
434c4762a1bSJed Brown      output_file: output/ex221_1.out
435c4762a1bSJed Brown      nsize: {{1 3}}
436c4762a1bSJed Brown      args: -M 21 -N 21 -loop 4 -rows_only {{0 1}} -keep {{0 1}} -submat {{0 1}} -test_axpy_different {{0 1}}
437c4762a1bSJed Brown TEST*/
438