xref: /petsc/src/mat/tests/ex23.c (revision 57508ece14a6b1339c0bbf016ecd72f673a062b0)
1d0dbe9f7SStefano Zampini static char help[] = "Tests the use of interface functions for MATIS matrices and conversion routines.\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown #include <petscmat.h>
4c4762a1bSJed Brown 
5c4762a1bSJed Brown PetscErrorCode TestMatZeroRows(Mat, Mat, PetscBool, IS, PetscScalar);
6c4762a1bSJed Brown PetscErrorCode CheckMat(Mat, Mat, PetscBool, const char *);
7c4762a1bSJed Brown 
8d71ae5a4SJacob Faibussowitsch int main(int argc, char **args)
9d71ae5a4SJacob Faibussowitsch {
10c4762a1bSJed Brown   Mat                    A, B, A2, B2, T;
11c4762a1bSJed Brown   Mat                    Aee, Aeo, Aoe, Aoo;
12d0dbe9f7SStefano Zampini   Mat                   *mats, *Asub, *Bsub;
13c4762a1bSJed Brown   Vec                    x, y;
14c4762a1bSJed Brown   MatInfo                info;
15c4762a1bSJed Brown   ISLocalToGlobalMapping cmap, rmap;
16c4762a1bSJed Brown   IS                     is, is2, reven, rodd, ceven, codd;
17c4762a1bSJed Brown   IS                    *rows, *cols;
18d0dbe9f7SStefano Zampini   IS                     irow[2], icol[2];
19d0dbe9f7SStefano Zampini   PetscLayout            rlayout, clayout;
2084a95373SStefano Zampini   const PetscInt        *rrange, *crange, *idxs1, *idxs2;
21c4762a1bSJed Brown   MatType                lmtype;
2284a95373SStefano Zampini   PetscScalar            diag = 2., *vals;
23e432b41dSStefano Zampini   PetscInt               n, m, i, lm, ln;
24a50ef18cSStefano Zampini   PetscInt               rst, ren, cst, cen, nr, nc, rbs = 1, cbs = 1;
25d0dbe9f7SStefano Zampini   PetscMPIInt            rank, size, lrank, rrank;
26c4762a1bSJed Brown   PetscBool              testT, squaretest, isaij;
274f58015eSStefano Zampini   PetscBool              permute = PETSC_FALSE, negmap = PETSC_FALSE, repmap = PETSC_FALSE, allow_repeated = PETSC_TRUE;
2884a95373SStefano Zampini   PetscBool              diffmap = PETSC_TRUE, symmetric = PETSC_FALSE, issymmetric, test_matlab = PETSC_FALSE, test_setvalues = PETSC_TRUE;
29c4762a1bSJed Brown 
30327415f7SBarry Smith   PetscFunctionBeginUser;
31c8025a54SPierre Jolivet   PetscCall(PetscInitialize(&argc, &args, NULL, help));
329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
34c4762a1bSJed Brown   m = n = 2 * size;
359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-symmetric", &symmetric, NULL));
369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-m", &m, NULL));
379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-negmap", &negmap, NULL));
399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-repmap", &repmap, NULL));
409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-permmap", &permute, NULL));
419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-diffmap", &diffmap, NULL));
424f58015eSStefano Zampini   PetscCall(PetscOptionsGetBool(NULL, NULL, "-allow_repeated", &allow_repeated, NULL));
435042aa92SStefano Zampini   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_matlab", &test_matlab, NULL));
4484a95373SStefano Zampini   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_setvalues", &test_setvalues, NULL));
45a50ef18cSStefano Zampini   PetscCall(PetscOptionsGetInt(NULL, NULL, "-rbs", &rbs, NULL));
46a50ef18cSStefano Zampini   PetscCall(PetscOptionsGetInt(NULL, NULL, "-cbs", &cbs, NULL));
47e00437b9SBarry Smith   PetscCheck(size == 1 || m >= 4, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Number of rows should be larger or equal 4 for parallel runs");
48e00437b9SBarry Smith   PetscCheck(size != 1 || m >= 2, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Number of rows should be larger or equal 2 for uniprocessor runs");
49e00437b9SBarry Smith   PetscCheck(n >= 2, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Number of cols should be larger or equal 2");
50c4762a1bSJed Brown 
51c4762a1bSJed Brown   /* create a MATIS matrix */
529566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
539566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, m, n));
549566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, MATIS));
559566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(A));
56e432b41dSStefano Zampini   if (!negmap && !repmap) {
57fc989267SStefano Zampini     /* This is not the proper setting for MATIS for finite elements, it is just used to test the routines
58fc989267SStefano Zampini        Here we use a one-to-one correspondence between local row/column spaces and global row/column spaces
59fc989267SStefano Zampini        Equivalent to passing NULL for the mapping */
609566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n, 0, 1, &is));
61e432b41dSStefano Zampini   } else if (negmap && !repmap) { /* non repeated but with negative indices */
629566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n + 2, -2, 1, &is));
63e432b41dSStefano Zampini   } else if (!negmap && repmap) { /* non negative but repeated indices */
64e432b41dSStefano Zampini     IS isl[2];
65e432b41dSStefano Zampini 
669566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n, 0, 1, &isl[0]));
679566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n, n - 1, -1, &isl[1]));
689566063dSJacob Faibussowitsch     PetscCall(ISConcatenate(PETSC_COMM_WORLD, 2, isl, &is));
699566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&isl[0]));
709566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&isl[1]));
71e432b41dSStefano Zampini   } else { /* negative and repeated indices */
72e432b41dSStefano Zampini     IS isl[2];
73e432b41dSStefano Zampini 
749566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n + 1, -1, 1, &isl[0]));
759566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n + 1, n - 1, -1, &isl[1]));
769566063dSJacob Faibussowitsch     PetscCall(ISConcatenate(PETSC_COMM_WORLD, 2, isl, &is));
779566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&isl[0]));
789566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&isl[1]));
79e432b41dSStefano Zampini   }
809566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmap));
819566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
82c4762a1bSJed Brown 
83e432b41dSStefano Zampini   if (m != n || diffmap) {
849566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, m, permute ? m - 1 : 0, permute ? -1 : 1, &is));
859566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmap));
869566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
87c4762a1bSJed Brown   } else {
889566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)cmap));
89c4762a1bSJed Brown     rmap = cmap;
90c4762a1bSJed Brown   }
91e432b41dSStefano Zampini 
924f58015eSStefano Zampini   PetscCall(MatISSetAllowRepeated(A, allow_repeated));
939566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap));
94a50ef18cSStefano Zampini   PetscCall(MatSetBlockSizes(A, rbs, cbs));
959566063dSJacob Faibussowitsch   PetscCall(MatISStoreL2L(A, PETSC_FALSE));
969566063dSJacob Faibussowitsch   PetscCall(MatISSetPreallocation(A, 3, NULL, 3, NULL));
979566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, (PetscBool) !(repmap || negmap))); /* I do not want to precompute the pattern */
989566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(rmap, &lm));
999566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(cmap, &ln));
100e432b41dSStefano Zampini   for (i = 0; i < lm; i++) {
101c4762a1bSJed Brown     PetscScalar v[3];
102c4762a1bSJed Brown     PetscInt    cols[3];
103c4762a1bSJed Brown 
104c4762a1bSJed Brown     cols[0] = (i - 1 + n) % n;
105c4762a1bSJed Brown     cols[1] = i % n;
106c4762a1bSJed Brown     cols[2] = (i + 1) % n;
107c4762a1bSJed Brown     v[0]    = -1. * (symmetric ? PetscMin(i + 1, cols[0] + 1) : i + 1);
108c4762a1bSJed Brown     v[1]    = 2. * (symmetric ? PetscMin(i + 1, cols[1] + 1) : i + 1);
109c4762a1bSJed Brown     v[2]    = -1. * (symmetric ? PetscMin(i + 1, cols[2] + 1) : i + 1);
1109566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(cmap, IS_GTOLM_MASK, 3, cols, NULL, cols));
1119566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(A, 1, &i, 3, cols, v, ADD_VALUES));
112c4762a1bSJed Brown   }
1139566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1149566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
115c4762a1bSJed Brown 
116e432b41dSStefano Zampini   /* activate tests for square matrices with same maps only */
1179566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &squaretest));
118e432b41dSStefano Zampini   if (squaretest && rmap != cmap) {
119e432b41dSStefano Zampini     PetscInt nr, nc;
120e432b41dSStefano Zampini 
1219566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(rmap, &nr));
1229566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(cmap, &nc));
123e432b41dSStefano Zampini     if (nr != nc) squaretest = PETSC_FALSE;
124e432b41dSStefano Zampini     else {
1259566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(rmap, &idxs1));
1269566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(cmap, &idxs2));
1279566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(idxs1, idxs2, nr, &squaretest));
1289566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(rmap, &idxs1));
1299566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(cmap, &idxs2));
130e432b41dSStefano Zampini     }
131462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &squaretest, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
132e432b41dSStefano Zampini   }
1334f58015eSStefano Zampini   if (negmap && repmap) squaretest = PETSC_FALSE;
134e432b41dSStefano Zampini 
135e432b41dSStefano Zampini   /* test MatISGetLocalMat */
1369566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A, &B));
1379566063dSJacob Faibussowitsch   PetscCall(MatGetType(B, &lmtype));
138c4762a1bSJed Brown 
139c4762a1bSJed Brown   /* test MatGetInfo */
1409566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatGetInfo\n"));
1419566063dSJacob Faibussowitsch   PetscCall(MatGetInfo(A, MAT_LOCAL, &info));
1429566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(PETSC_VIEWER_STDOUT_WORLD));
1439371c9d4SSatish Balay   PetscCall(PetscViewerASCIISynchronizedPrintf(PETSC_VIEWER_STDOUT_WORLD, "Process  %2d: %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", PetscGlobalRank, (PetscInt)info.nz_used, (PetscInt)info.nz_allocated,
1449371c9d4SSatish Balay                                                (PetscInt)info.nz_unneeded, (PetscInt)info.assemblies, (PetscInt)info.mallocs));
1459566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD));
1469566063dSJacob Faibussowitsch   PetscCall(MatGetInfo(A, MAT_GLOBAL_MAX, &info));
1479371c9d4SSatish Balay   PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD, "GlobalMax  : %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", (PetscInt)info.nz_used, (PetscInt)info.nz_allocated, (PetscInt)info.nz_unneeded,
1489371c9d4SSatish Balay                                    (PetscInt)info.assemblies, (PetscInt)info.mallocs));
1499566063dSJacob Faibussowitsch   PetscCall(MatGetInfo(A, MAT_GLOBAL_SUM, &info));
1509371c9d4SSatish Balay   PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD, "GlobalSum  : %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", (PetscInt)info.nz_used, (PetscInt)info.nz_allocated, (PetscInt)info.nz_unneeded,
1519371c9d4SSatish Balay                                    (PetscInt)info.assemblies, (PetscInt)info.mallocs));
152c4762a1bSJed Brown 
153e432b41dSStefano Zampini   /* test MatIsSymmetric */
1549566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetric(A, 0.0, &issymmetric));
1559566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatIsSymmetric: %d\n", issymmetric));
156c4762a1bSJed Brown 
157c4762a1bSJed Brown   /* Create a MPIAIJ matrix, same as A */
1589566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, &B));
1599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n));
160a50ef18cSStefano Zampini   PetscCall(MatSetBlockSizes(B, rbs, cbs));
1619566063dSJacob Faibussowitsch   PetscCall(MatSetType(B, MATAIJ));
1629566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(B));
1639566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B, rmap, cmap));
1649566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(B, 3, NULL, 3, NULL));
1659566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(B, 1, 3, NULL, 3, NULL));
166c4762a1bSJed Brown #if defined(PETSC_HAVE_HYPRE)
1679566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(B, 3, NULL, 3, NULL));
168c4762a1bSJed Brown #endif
1699566063dSJacob Faibussowitsch   PetscCall(MatISSetPreallocation(B, 3, NULL, 3, NULL));
1709566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, (PetscBool) !(repmap || negmap))); /* I do not want to precompute the pattern */
171e432b41dSStefano Zampini   for (i = 0; i < lm; i++) {
172c4762a1bSJed Brown     PetscScalar v[3];
173c4762a1bSJed Brown     PetscInt    cols[3];
174c4762a1bSJed Brown 
175c4762a1bSJed Brown     cols[0] = (i - 1 + n) % n;
176c4762a1bSJed Brown     cols[1] = i % n;
177c4762a1bSJed Brown     cols[2] = (i + 1) % n;
178c4762a1bSJed Brown     v[0]    = -1. * (symmetric ? PetscMin(i + 1, cols[0] + 1) : i + 1);
179c4762a1bSJed Brown     v[1]    = 2. * (symmetric ? PetscMin(i + 1, cols[1] + 1) : i + 1);
180c4762a1bSJed Brown     v[2]    = -1. * (symmetric ? PetscMin(i + 1, cols[2] + 1) : i + 1);
1819566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(cmap, IS_GTOLM_MASK, 3, cols, NULL, cols));
1829566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(B, 1, &i, 3, cols, v, ADD_VALUES));
183c4762a1bSJed Brown   }
1849566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1859566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
186e432b41dSStefano Zampini 
187e432b41dSStefano Zampini   /* test MatView */
1889566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatView\n"));
1899566063dSJacob Faibussowitsch   PetscCall(MatView(A, NULL));
1909566063dSJacob Faibussowitsch   PetscCall(MatView(B, NULL));
191c4762a1bSJed Brown 
1925042aa92SStefano Zampini   /* test MATLAB ASCII view */
1935042aa92SStefano Zampini   if (test_matlab) { /* output is different when using real or complex numbers */
1945042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatView ASCII MATLAB\n"));
1955042aa92SStefano Zampini     PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_MATLAB));
1965042aa92SStefano Zampini     PetscCall(MatView(A, PETSC_VIEWER_STDOUT_WORLD));
1975042aa92SStefano Zampini     PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
1985042aa92SStefano Zampini   }
1995042aa92SStefano Zampini 
200c4762a1bSJed Brown   /* test CheckMat */
2019566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test CheckMat\n"));
2029566063dSJacob Faibussowitsch   PetscCall(CheckMat(A, B, PETSC_FALSE, "CheckMat"));
203c4762a1bSJed Brown 
2045042aa92SStefano Zampini   /* test binary MatView/MatLoad */
2055042aa92SStefano Zampini   {
2065042aa92SStefano Zampini     PetscMPIInt color = rank % 2;
2075042aa92SStefano Zampini     MPI_Comm    comm;
2085042aa92SStefano Zampini     char        name[PETSC_MAX_PATH_LEN];
2095042aa92SStefano Zampini     PetscViewer wview, cview, sview, view;
2105042aa92SStefano Zampini     Mat         A2;
2115042aa92SStefano Zampini 
2125042aa92SStefano Zampini     PetscCallMPI(MPI_Comm_split(PETSC_COMM_WORLD, color, rank, &comm));
2135042aa92SStefano Zampini 
2145042aa92SStefano Zampini     PetscCall(PetscSNPrintf(name, PETSC_STATIC_ARRAY_LENGTH(name), "world_is"));
2155042aa92SStefano Zampini     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_WRITE, &wview));
2165042aa92SStefano Zampini     PetscCall(PetscSNPrintf(name, PETSC_STATIC_ARRAY_LENGTH(name), "seq_is_%d", rank));
2175042aa92SStefano Zampini     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_SELF, name, FILE_MODE_WRITE, &sview));
2185042aa92SStefano Zampini     PetscCall(PetscSNPrintf(name, PETSC_STATIC_ARRAY_LENGTH(name), "color_is_%d", color));
2195042aa92SStefano Zampini     PetscCall(PetscViewerBinaryOpen(comm, name, FILE_MODE_WRITE, &cview));
2205042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatView on binary world\n"));
2215042aa92SStefano Zampini     PetscCall(MatView(A, wview));
2225042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatView on binary self\n"));
2235042aa92SStefano Zampini     PetscCall(MatView(A, sview));
2245042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatView on binary subcomm\n"));
2255042aa92SStefano Zampini     PetscCall(MatView(A, cview));
2265042aa92SStefano Zampini     PetscCall(PetscViewerDestroy(&wview));
2275042aa92SStefano Zampini     PetscCall(PetscViewerDestroy(&cview));
2285042aa92SStefano Zampini     PetscCall(PetscViewerDestroy(&sview));
2295042aa92SStefano Zampini 
2305042aa92SStefano Zampini     /* Load a world matrix */
2315042aa92SStefano Zampini     PetscCall(MatCreate(PETSC_COMM_WORLD, &A2));
2325042aa92SStefano Zampini     PetscCall(MatSetType(A2, MATIS));
2335042aa92SStefano Zampini     PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL));
2345042aa92SStefano Zampini 
2355042aa92SStefano Zampini     /* Read back the same matrix and check */
2365042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatLoad from world\n"));
2375042aa92SStefano Zampini     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, "world_is", FILE_MODE_READ, &view));
2385042aa92SStefano Zampini     PetscCall(MatLoad(A2, view));
2395042aa92SStefano Zampini     PetscCall(CheckMat(A, A2, PETSC_TRUE, "Load"));
2405042aa92SStefano Zampini     PetscCall(MatView(A2, PETSC_VIEWER_STDOUT_WORLD));
2415042aa92SStefano Zampini     PetscCall(PetscViewerDestroy(&view));
2425042aa92SStefano Zampini 
2435042aa92SStefano Zampini     /* Read the matrix from rank 0 only */
2445042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatLoad from self\n"));
2455042aa92SStefano Zampini     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, "seq_is_0", FILE_MODE_READ, &view));
2465042aa92SStefano Zampini     PetscCall(MatLoad(A2, view));
2475042aa92SStefano Zampini     PetscCall(MatView(A2, PETSC_VIEWER_STDOUT_WORLD));
2485042aa92SStefano Zampini     PetscCall(PetscViewerDestroy(&view));
2495042aa92SStefano Zampini 
2505042aa92SStefano Zampini     /* Read the matrix from subcomm */
2515042aa92SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatLoad from subcomm\n"));
2525042aa92SStefano Zampini     PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, "color_is_0", FILE_MODE_READ, &view));
2535042aa92SStefano Zampini     PetscCall(MatLoad(A2, view));
2545042aa92SStefano Zampini     PetscCall(MatView(A2, PETSC_VIEWER_STDOUT_WORLD));
2555042aa92SStefano Zampini     PetscCall(PetscViewerDestroy(&view));
2565042aa92SStefano Zampini 
2575042aa92SStefano Zampini     PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
2585042aa92SStefano Zampini     PetscCall(MatDestroy(&A2));
2595042aa92SStefano Zampini 
2605042aa92SStefano Zampini     /* now load the original matrix from color 0 only processes */
2615042aa92SStefano Zampini     if (!color) {
2625042aa92SStefano Zampini       PetscCall(PetscPrintf(comm, "Test subcomm MatLoad from world\n"));
2635042aa92SStefano Zampini       PetscCall(MatCreate(comm, &A2));
2645042aa92SStefano Zampini       PetscCall(MatSetType(A2, MATIS));
2655042aa92SStefano Zampini       PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(comm), PETSC_VIEWER_ASCII_INFO_DETAIL));
2665042aa92SStefano Zampini       PetscCall(PetscViewerBinaryOpen(comm, "world_is", FILE_MODE_READ, &view));
2675042aa92SStefano Zampini       PetscCall(MatLoad(A2, view));
2685042aa92SStefano Zampini       PetscCall(MatView(A2, PETSC_VIEWER_STDOUT_(comm)));
2695042aa92SStefano Zampini       PetscCall(PetscViewerDestroy(&view));
2705042aa92SStefano Zampini       PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(comm)));
2715042aa92SStefano Zampini       PetscCall(MatDestroy(&A2));
2725042aa92SStefano Zampini     }
2735042aa92SStefano Zampini 
2745042aa92SStefano Zampini     PetscCallMPI(MPI_Comm_free(&comm));
2755042aa92SStefano Zampini   }
2765042aa92SStefano Zampini 
277c4762a1bSJed Brown   /* test MatDuplicate and MatAXPY */
2789566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatDuplicate and MatAXPY\n"));
2799566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
2809566063dSJacob Faibussowitsch   PetscCall(CheckMat(A, A2, PETSC_FALSE, "MatDuplicate and MatAXPY"));
281c4762a1bSJed Brown 
282c4762a1bSJed Brown   /* test MatConvert */
2839566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatConvert_IS_XAIJ\n"));
2849566063dSJacob Faibussowitsch   PetscCall(MatConvert(A2, MATAIJ, MAT_INITIAL_MATRIX, &B2));
2859566063dSJacob Faibussowitsch   PetscCall(CheckMat(B, B2, PETSC_TRUE, "MatConvert_IS_XAIJ MAT_INITIAL_MATRIX"));
2869566063dSJacob Faibussowitsch   PetscCall(MatConvert(A2, MATAIJ, MAT_REUSE_MATRIX, &B2));
2879566063dSJacob Faibussowitsch   PetscCall(CheckMat(B, B2, PETSC_TRUE, "MatConvert_IS_XAIJ MAT_REUSE_MATRIX"));
2889566063dSJacob Faibussowitsch   PetscCall(MatConvert(A2, MATAIJ, MAT_INPLACE_MATRIX, &A2));
2899566063dSJacob Faibussowitsch   PetscCall(CheckMat(B, A2, PETSC_TRUE, "MatConvert_IS_XAIJ MAT_INPLACE_MATRIX"));
2909566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
2919566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
2929566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatConvert_XAIJ_IS\n"));
2939566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
2949566063dSJacob Faibussowitsch   PetscCall(MatConvert(B2, MATIS, MAT_INITIAL_MATRIX, &A2));
2959566063dSJacob Faibussowitsch   PetscCall(CheckMat(A, A2, PETSC_TRUE, "MatConvert_XAIJ_IS MAT_INITIAL_MATRIX"));
2969566063dSJacob Faibussowitsch   PetscCall(MatConvert(B2, MATIS, MAT_REUSE_MATRIX, &A2));
2979566063dSJacob Faibussowitsch   PetscCall(CheckMat(A, A2, PETSC_TRUE, "MatConvert_XAIJ_IS MAT_REUSE_MATRIX"));
2989566063dSJacob Faibussowitsch   PetscCall(MatConvert(B2, MATIS, MAT_INPLACE_MATRIX, &B2));
2999566063dSJacob Faibussowitsch   PetscCall(CheckMat(A, B2, PETSC_TRUE, "MatConvert_XAIJ_IS MAT_INPLACE_MATRIX"));
3009566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
3019566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
3029566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lmtype, MATSEQAIJ, &isaij));
303c4762a1bSJed Brown   if (size == 1 && isaij) { /* tests special code paths in MatConvert_IS_XAIJ */
304c4762a1bSJed Brown     PetscInt               ri, ci, rr[3] = {0, 1, 0}, cr[4] = {1, 2, 0, 1}, rk[3] = {0, 2, 1}, ck[4] = {1, 0, 3, 2};
305e432b41dSStefano Zampini     ISLocalToGlobalMapping tcmap, trmap;
306c4762a1bSJed Brown 
307c4762a1bSJed Brown     for (ri = 0; ri < 2; ri++) {
308c4762a1bSJed Brown       PetscInt *r;
309c4762a1bSJed Brown 
310c4762a1bSJed Brown       r = (PetscInt *)(ri == 0 ? rr : rk);
311c4762a1bSJed Brown       for (ci = 0; ci < 2; ci++) {
312c4762a1bSJed Brown         PetscInt *c, rb, cb;
313c4762a1bSJed Brown 
314c4762a1bSJed Brown         c = (PetscInt *)(ci == 0 ? cr : ck);
315c4762a1bSJed Brown         for (rb = 1; rb < 4; rb++) {
3169566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PETSC_COMM_SELF, rb, 3, r, PETSC_COPY_VALUES, &is));
3179566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingCreateIS(is, &trmap));
3189566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&is));
319c4762a1bSJed Brown           for (cb = 1; cb < 4; cb++) {
320c4762a1bSJed Brown             Mat  T, lT, T2;
321c4762a1bSJed Brown             char testname[256];
322c4762a1bSJed Brown 
3239566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(testname, sizeof(testname), "MatConvert_IS_XAIJ special case (%" PetscInt_FMT " %" PetscInt_FMT ", bs %" PetscInt_FMT " %" PetscInt_FMT ")", ri, ci, rb, cb));
3249566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test %s\n", testname));
325c4762a1bSJed Brown 
3269566063dSJacob Faibussowitsch             PetscCall(ISCreateBlock(PETSC_COMM_SELF, cb, 4, c, PETSC_COPY_VALUES, &is));
3279566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingCreateIS(is, &tcmap));
3289566063dSJacob Faibussowitsch             PetscCall(ISDestroy(&is));
329c4762a1bSJed Brown 
3309566063dSJacob Faibussowitsch             PetscCall(MatCreate(PETSC_COMM_SELF, &T));
3319566063dSJacob Faibussowitsch             PetscCall(MatSetSizes(T, PETSC_DECIDE, PETSC_DECIDE, rb * 3, cb * 4));
3329566063dSJacob Faibussowitsch             PetscCall(MatSetType(T, MATIS));
3339566063dSJacob Faibussowitsch             PetscCall(MatSetLocalToGlobalMapping(T, trmap, tcmap));
3349566063dSJacob Faibussowitsch             PetscCall(ISLocalToGlobalMappingDestroy(&tcmap));
3359566063dSJacob Faibussowitsch             PetscCall(MatISGetLocalMat(T, &lT));
3369566063dSJacob Faibussowitsch             PetscCall(MatSetType(lT, MATSEQAIJ));
3379566063dSJacob Faibussowitsch             PetscCall(MatSeqAIJSetPreallocation(lT, cb * 4, NULL));
3389566063dSJacob Faibussowitsch             PetscCall(MatSetRandom(lT, NULL));
3399566063dSJacob Faibussowitsch             PetscCall(MatConvert(lT, lmtype, MAT_INPLACE_MATRIX, &lT));
3409566063dSJacob Faibussowitsch             PetscCall(MatISRestoreLocalMat(T, &lT));
3419566063dSJacob Faibussowitsch             PetscCall(MatAssemblyBegin(T, MAT_FINAL_ASSEMBLY));
3429566063dSJacob Faibussowitsch             PetscCall(MatAssemblyEnd(T, MAT_FINAL_ASSEMBLY));
343c4762a1bSJed Brown 
3449566063dSJacob Faibussowitsch             PetscCall(MatConvert(T, MATAIJ, MAT_INITIAL_MATRIX, &T2));
3459566063dSJacob Faibussowitsch             PetscCall(CheckMat(T, T2, PETSC_TRUE, "MAT_INITIAL_MATRIX"));
3469566063dSJacob Faibussowitsch             PetscCall(MatConvert(T, MATAIJ, MAT_REUSE_MATRIX, &T2));
3479566063dSJacob Faibussowitsch             PetscCall(CheckMat(T, T2, PETSC_TRUE, "MAT_REUSE_MATRIX"));
3489566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&T2));
3499566063dSJacob Faibussowitsch             PetscCall(MatDuplicate(T, MAT_COPY_VALUES, &T2));
3509566063dSJacob Faibussowitsch             PetscCall(MatConvert(T2, MATAIJ, MAT_INPLACE_MATRIX, &T2));
3519566063dSJacob Faibussowitsch             PetscCall(CheckMat(T, T2, PETSC_TRUE, "MAT_INPLACE_MATRIX"));
3529566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&T));
3539566063dSJacob Faibussowitsch             PetscCall(MatDestroy(&T2));
354c4762a1bSJed Brown           }
3559566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingDestroy(&trmap));
356c4762a1bSJed Brown         }
357c4762a1bSJed Brown       }
358c4762a1bSJed Brown     }
359c4762a1bSJed Brown   }
360c4762a1bSJed Brown 
361c4762a1bSJed Brown   /* test MatDiagonalScale */
3629566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatDiagonalScale\n"));
3639566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
3649566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
3659566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A, &x, &y));
3669566063dSJacob Faibussowitsch   PetscCall(VecSetRandom(x, NULL));
367e432b41dSStefano Zampini   if (issymmetric) {
3689566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, y));
369c4762a1bSJed Brown   } else {
3709566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(y, NULL));
3719566063dSJacob Faibussowitsch     PetscCall(VecScale(y, 8.));
372c4762a1bSJed Brown   }
3739566063dSJacob Faibussowitsch   PetscCall(MatDiagonalScale(A2, y, x));
3749566063dSJacob Faibussowitsch   PetscCall(MatDiagonalScale(B2, y, x));
3759566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatDiagonalScale"));
3769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
3779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
3789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
3799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
380c4762a1bSJed Brown 
381c4762a1bSJed Brown   /* test MatPtAP (A IS and B AIJ) */
382c4762a1bSJed Brown   if (isaij && m == n) {
3839566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatPtAP\n"));
3844f58015eSStefano Zampini     /* There's a bug in MatCreateSubMatrices_MPIAIJ I cannot figure out */
3854f58015eSStefano Zampini     if (!allow_repeated || !repmap || size == 1) {
3869566063dSJacob Faibussowitsch       PetscCall(MatISStoreL2L(A, PETSC_TRUE));
387fb842aefSJose E. Roman       PetscCall(MatPtAP(A, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &A2));
388fb842aefSJose E. Roman       PetscCall(MatPtAP(B, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &B2));
3899566063dSJacob Faibussowitsch       PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatPtAP MAT_INITIAL_MATRIX"));
390fb842aefSJose E. Roman       PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DETERMINE, &A2));
3919566063dSJacob Faibussowitsch       PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatPtAP MAT_REUSE_MATRIX"));
3929566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A2));
3939566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B2));
394c4762a1bSJed Brown     }
3954f58015eSStefano Zampini   }
396c4762a1bSJed Brown 
397c4762a1bSJed Brown   /* test MatGetLocalSubMatrix */
3989566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatGetLocalSubMatrix\n"));
3999566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &A2));
4009566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, lm / 2 + lm % 2, 0, 2, &reven));
4019566063dSJacob Faibussowitsch   PetscCall(ISComplement(reven, 0, lm, &rodd));
4029566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, ln / 2 + ln % 2, 0, 2, &ceven));
4039566063dSJacob Faibussowitsch   PetscCall(ISComplement(ceven, 0, ln, &codd));
4049566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSubMatrix(A2, reven, ceven, &Aee));
4059566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSubMatrix(A2, reven, codd, &Aeo));
4069566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSubMatrix(A2, rodd, ceven, &Aoe));
4079566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSubMatrix(A2, rodd, codd, &Aoo));
408e432b41dSStefano Zampini   for (i = 0; i < lm; i++) {
409c4762a1bSJed Brown     PetscInt    j, je, jo, colse[3], colso[3];
410c4762a1bSJed Brown     PetscScalar ve[3], vo[3];
411c4762a1bSJed Brown     PetscScalar v[3];
412c4762a1bSJed Brown     PetscInt    cols[3];
413e432b41dSStefano Zampini     PetscInt    row = i / 2;
414c4762a1bSJed Brown 
415c4762a1bSJed Brown     cols[0] = (i - 1 + n) % n;
416c4762a1bSJed Brown     cols[1] = i % n;
417c4762a1bSJed Brown     cols[2] = (i + 1) % n;
418c4762a1bSJed Brown     v[0]    = -1. * (symmetric ? PetscMin(i + 1, cols[0] + 1) : i + 1);
419c4762a1bSJed Brown     v[1]    = 2. * (symmetric ? PetscMin(i + 1, cols[1] + 1) : i + 1);
420c4762a1bSJed Brown     v[2]    = -1. * (symmetric ? PetscMin(i + 1, cols[2] + 1) : i + 1);
4219566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(cmap, IS_GTOLM_MASK, 3, cols, NULL, cols));
422c4762a1bSJed Brown     for (j = 0, je = 0, jo = 0; j < 3; j++) {
423c4762a1bSJed Brown       if (cols[j] % 2) {
424c4762a1bSJed Brown         vo[jo]      = v[j];
425c4762a1bSJed Brown         colso[jo++] = cols[j] / 2;
426c4762a1bSJed Brown       } else {
427c4762a1bSJed Brown         ve[je]      = v[j];
428c4762a1bSJed Brown         colse[je++] = cols[j] / 2;
429c4762a1bSJed Brown       }
430c4762a1bSJed Brown     }
431c4762a1bSJed Brown     if (i % 2) {
4329566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Aoe, 1, &row, je, colse, ve, ADD_VALUES));
4339566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Aoo, 1, &row, jo, colso, vo, ADD_VALUES));
434c4762a1bSJed Brown     } else {
4359566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Aee, 1, &row, je, colse, ve, ADD_VALUES));
4369566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(Aeo, 1, &row, jo, colso, vo, ADD_VALUES));
437c4762a1bSJed Brown     }
438c4762a1bSJed Brown   }
4399566063dSJacob Faibussowitsch   PetscCall(MatRestoreLocalSubMatrix(A2, reven, ceven, &Aee));
4409566063dSJacob Faibussowitsch   PetscCall(MatRestoreLocalSubMatrix(A2, reven, codd, &Aeo));
4419566063dSJacob Faibussowitsch   PetscCall(MatRestoreLocalSubMatrix(A2, rodd, ceven, &Aoe));
4429566063dSJacob Faibussowitsch   PetscCall(MatRestoreLocalSubMatrix(A2, rodd, codd, &Aoo));
4439566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&reven));
4449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ceven));
4459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&rodd));
4469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&codd));
4479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY));
4489566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY));
4499566063dSJacob Faibussowitsch   PetscCall(MatAXPY(A2, -1., A, SAME_NONZERO_PATTERN));
4509566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, NULL, PETSC_FALSE, "MatGetLocalSubMatrix"));
4519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
452c4762a1bSJed Brown 
453c4762a1bSJed Brown   /* test MatConvert_Nest_IS */
454c4762a1bSJed Brown   testT = PETSC_FALSE;
4559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_trans", &testT, NULL));
456c4762a1bSJed Brown 
4579566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatConvert_Nest_IS\n"));
458c4762a1bSJed Brown   nr = 2;
459c4762a1bSJed Brown   nc = 2;
4609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-nr", &nr, NULL));
4619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-nc", &nc, NULL));
462c4762a1bSJed Brown   if (testT) {
4639566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(A, &cst, &cen));
4649566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRangeColumn(A, &rst, &ren));
465c4762a1bSJed Brown   } else {
4669566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(A, &rst, &ren));
4679566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRangeColumn(A, &cst, &cen));
468c4762a1bSJed Brown   }
4699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(nr, &rows, nc, &cols, 2 * nr * nc, &mats));
470c4762a1bSJed Brown   for (i = 0; i < nr * nc; i++) {
471c4762a1bSJed Brown     if (testT) {
4729566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(A, &mats[i]));
4739566063dSJacob Faibussowitsch       PetscCall(MatTranspose(B, MAT_INITIAL_MATRIX, &mats[i + nr * nc]));
474c4762a1bSJed Brown     } else {
4759566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &mats[i]));
4769566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &mats[i + nr * nc]));
477c4762a1bSJed Brown     }
478c4762a1bSJed Brown   }
47948a46eb9SPierre Jolivet   for (i = 0; i < nr; i++) PetscCall(ISCreateStride(PETSC_COMM_WORLD, ren - rst, i + rst, nr, &rows[i]));
48048a46eb9SPierre Jolivet   for (i = 0; i < nc; i++) PetscCall(ISCreateStride(PETSC_COMM_WORLD, cen - cst, i + cst, nc, &cols[i]));
4819566063dSJacob Faibussowitsch   PetscCall(MatCreateNest(PETSC_COMM_WORLD, nr, rows, nc, cols, mats, &A2));
4829566063dSJacob Faibussowitsch   PetscCall(MatCreateNest(PETSC_COMM_WORLD, nr, rows, nc, cols, mats + nr * nc, &B2));
48348a46eb9SPierre Jolivet   for (i = 0; i < nr; i++) PetscCall(ISDestroy(&rows[i]));
48448a46eb9SPierre Jolivet   for (i = 0; i < nc; i++) PetscCall(ISDestroy(&cols[i]));
48548a46eb9SPierre Jolivet   for (i = 0; i < 2 * nr * nc; i++) PetscCall(MatDestroy(&mats[i]));
4869566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, cols, mats));
4879566063dSJacob Faibussowitsch   PetscCall(MatConvert(B2, MATAIJ, MAT_INITIAL_MATRIX, &T));
4889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
4899566063dSJacob Faibussowitsch   PetscCall(MatConvert(A2, MATIS, MAT_INITIAL_MATRIX, &B2));
4909566063dSJacob Faibussowitsch   PetscCall(CheckMat(B2, T, PETSC_TRUE, "MatConvert_Nest_IS MAT_INITIAL_MATRIX"));
4919566063dSJacob Faibussowitsch   PetscCall(MatConvert(A2, MATIS, MAT_REUSE_MATRIX, &B2));
4929566063dSJacob Faibussowitsch   PetscCall(CheckMat(B2, T, PETSC_TRUE, "MatConvert_Nest_IS MAT_REUSE_MATRIX"));
4939566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
4949566063dSJacob Faibussowitsch   PetscCall(MatConvert(A2, MATIS, MAT_INPLACE_MATRIX, &A2));
4959566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, T, PETSC_TRUE, "MatConvert_Nest_IS MAT_INPLACE_MATRIX"));
4969566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&T));
4979566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
498c4762a1bSJed Brown 
499c4762a1bSJed Brown   /* test MatCreateSubMatrix */
5009566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatCreateSubMatrix\n"));
501dd400576SPatrick Sanan   if (rank == 0) {
5029566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 1, 1, 1, &is));
5039566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 2, 0, 1, &is2));
504c4762a1bSJed Brown   } else if (rank == 1) {
5059566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 1, 0, 1, &is));
506c4762a1bSJed Brown     if (n > 3) {
5079566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_WORLD, 1, 3, 1, &is2));
508c4762a1bSJed Brown     } else {
5099566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_WORLD, 0, 0, 1, &is2));
510c4762a1bSJed Brown     }
511c4762a1bSJed Brown   } else if (rank == 2 && n > 4) {
5129566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 0, 0, 1, &is));
5139566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, n - 4, 4, 1, &is2));
514c4762a1bSJed Brown   } else {
5159566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 0, 0, 1, &is));
5169566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 0, 0, 1, &is2));
517c4762a1bSJed Brown   }
5189566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A, is, is, MAT_INITIAL_MATRIX, &A2));
5199566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(B, is, is, MAT_INITIAL_MATRIX, &B2));
5209566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_TRUE, "first MatCreateSubMatrix"));
521c4762a1bSJed Brown 
5229566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A, is, is, MAT_REUSE_MATRIX, &A2));
5239566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(B, is, is, MAT_REUSE_MATRIX, &B2));
5249566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "reuse MatCreateSubMatrix"));
5259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
5269566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
527c4762a1bSJed Brown 
528e432b41dSStefano Zampini   if (!issymmetric) {
5299566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(A, is, is2, MAT_INITIAL_MATRIX, &A2));
5309566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(B, is, is2, MAT_INITIAL_MATRIX, &B2));
5319566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(A, is, is2, MAT_REUSE_MATRIX, &A2));
5329566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(B, is, is2, MAT_REUSE_MATRIX, &B2));
5339566063dSJacob Faibussowitsch     PetscCall(CheckMat(A2, B2, PETSC_FALSE, "second MatCreateSubMatrix"));
534c4762a1bSJed Brown   }
535c4762a1bSJed Brown 
5369566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
5379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
5389566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
5399566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is2));
540c4762a1bSJed Brown 
541d0dbe9f7SStefano Zampini   /* test MatCreateSubMatrices */
542d0dbe9f7SStefano Zampini   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatCreateSubMatrices\n"));
543d0dbe9f7SStefano Zampini   PetscCall(MatGetLayouts(A, &rlayout, &clayout));
544d0dbe9f7SStefano Zampini   PetscCall(PetscLayoutGetRanges(rlayout, &rrange));
545d0dbe9f7SStefano Zampini   PetscCall(PetscLayoutGetRanges(clayout, &crange));
546d0dbe9f7SStefano Zampini   lrank = (size + rank - 1) % size;
547d0dbe9f7SStefano Zampini   rrank = (rank + 1) % size;
548*57508eceSPierre Jolivet   PetscCall(ISCreateStride(PETSC_COMM_SELF, rrange[lrank + 1] - rrange[lrank], rrange[lrank], 1, &irow[0]));
549*57508eceSPierre Jolivet   PetscCall(ISCreateStride(PETSC_COMM_SELF, crange[rrank + 1] - crange[rrank], crange[rrank], 1, &icol[0]));
550*57508eceSPierre Jolivet   PetscCall(ISCreateStride(PETSC_COMM_SELF, rrange[rrank + 1] - rrange[rrank], rrange[rrank], 1, &irow[1]));
551*57508eceSPierre Jolivet   PetscCall(ISCreateStride(PETSC_COMM_SELF, crange[lrank + 1] - crange[lrank], crange[lrank], 1, &icol[1]));
552d0dbe9f7SStefano Zampini   PetscCall(MatCreateSubMatrices(A, 2, irow, icol, MAT_INITIAL_MATRIX, &Asub));
553d0dbe9f7SStefano Zampini   PetscCall(MatCreateSubMatrices(B, 2, irow, icol, MAT_INITIAL_MATRIX, &Bsub));
554d0dbe9f7SStefano Zampini   PetscCall(CheckMat(Asub[0], Bsub[0], PETSC_FALSE, "MatCreateSubMatrices[0]"));
555d0dbe9f7SStefano Zampini   PetscCall(CheckMat(Asub[1], Bsub[1], PETSC_FALSE, "MatCreateSubMatrices[1]"));
556d0dbe9f7SStefano Zampini   PetscCall(MatCreateSubMatrices(A, 2, irow, icol, MAT_REUSE_MATRIX, &Asub));
557d0dbe9f7SStefano Zampini   PetscCall(MatCreateSubMatrices(B, 2, irow, icol, MAT_REUSE_MATRIX, &Bsub));
558d0dbe9f7SStefano Zampini   PetscCall(CheckMat(Asub[0], Bsub[0], PETSC_FALSE, "MatCreateSubMatrices[0]"));
559d0dbe9f7SStefano Zampini   PetscCall(CheckMat(Asub[1], Bsub[1], PETSC_FALSE, "MatCreateSubMatrices[1]"));
560d0dbe9f7SStefano Zampini   PetscCall(MatDestroySubMatrices(2, &Asub));
561d0dbe9f7SStefano Zampini   PetscCall(MatDestroySubMatrices(2, &Bsub));
562d0dbe9f7SStefano Zampini   PetscCall(ISDestroy(&irow[0]));
563d0dbe9f7SStefano Zampini   PetscCall(ISDestroy(&irow[1]));
564d0dbe9f7SStefano Zampini   PetscCall(ISDestroy(&icol[0]));
565d0dbe9f7SStefano Zampini   PetscCall(ISDestroy(&icol[1]));
566d0dbe9f7SStefano Zampini 
567c4762a1bSJed Brown   /* Create an IS required by MatZeroRows(): just rank zero provides the rows to be eliminated */
568c4762a1bSJed Brown   if (size > 1) {
569dd400576SPatrick Sanan     if (rank == 0) {
570c4762a1bSJed Brown       PetscInt st, len;
571c4762a1bSJed Brown 
572c4762a1bSJed Brown       st  = (m + 1) / 2;
573c4762a1bSJed Brown       len = PetscMin(m / 2, PetscMax(m - (m + 1) / 2 - 1, 0));
5749566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_WORLD, len, st, 1, &is));
575c4762a1bSJed Brown     } else {
5769566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_WORLD, 0, 0, 1, &is));
577c4762a1bSJed Brown     }
578c4762a1bSJed Brown   } else {
5799566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_WORLD, 1, 0, 1, &is));
580c4762a1bSJed Brown   }
581c4762a1bSJed Brown 
582c4762a1bSJed Brown   if (squaretest) { /* tests for square matrices only, with same maps for rows and columns */
583d0dbe9f7SStefano Zampini     PetscInt *idx0, *idx1, n0, n1;
584d0dbe9f7SStefano Zampini     IS        Ais[2], Bis[2];
585d0dbe9f7SStefano Zampini 
586c4762a1bSJed Brown     /* test MatDiagonalSet */
5879566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatDiagonalSet\n"));
5889566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
5899566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
5909566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A, NULL, &x));
5919566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(x, NULL));
5924f58015eSStefano Zampini     PetscCall(MatDiagonalSet(A2, x, allow_repeated ? ADD_VALUES : INSERT_VALUES));
5934f58015eSStefano Zampini     PetscCall(MatDiagonalSet(B2, x, allow_repeated ? ADD_VALUES : INSERT_VALUES));
5949566063dSJacob Faibussowitsch     PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatDiagonalSet"));
5959566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&x));
5969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A2));
5979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B2));
598c4762a1bSJed Brown 
599c4762a1bSJed Brown     /* test MatShift (MatShift_IS internally uses MatDiagonalSet_IS with ADD_VALUES) */
6009566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatShift\n"));
6019566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
6029566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
6039566063dSJacob Faibussowitsch     PetscCall(MatShift(A2, 2.0));
6049566063dSJacob Faibussowitsch     PetscCall(MatShift(B2, 2.0));
6059566063dSJacob Faibussowitsch     PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatShift"));
6069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A2));
6079566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B2));
608c4762a1bSJed Brown 
609c4762a1bSJed Brown     /* nonzero diag value is supported for square matrices only */
6109566063dSJacob Faibussowitsch     PetscCall(TestMatZeroRows(A, B, PETSC_TRUE, is, diag));
611d0dbe9f7SStefano Zampini 
612d0dbe9f7SStefano Zampini     /* test MatIncreaseOverlap */
613d0dbe9f7SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatIncreaseOverlap\n"));
614d0dbe9f7SStefano Zampini     PetscCall(MatGetOwnershipRange(A, &rst, &ren));
615d0dbe9f7SStefano Zampini     n0 = (ren - rst) / 2;
616d0dbe9f7SStefano Zampini     n1 = (ren - rst) / 3;
617d0dbe9f7SStefano Zampini     PetscCall(PetscMalloc1(n0, &idx0));
618d0dbe9f7SStefano Zampini     PetscCall(PetscMalloc1(n1, &idx1));
619d0dbe9f7SStefano Zampini     for (i = 0; i < n0; i++) idx0[i] = ren - i - 1;
620d0dbe9f7SStefano Zampini     for (i = 0; i < n1; i++) idx1[i] = rst + i;
621d0dbe9f7SStefano Zampini     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, n0, idx0, PETSC_OWN_POINTER, &Ais[0]));
622d0dbe9f7SStefano Zampini     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, n1, idx1, PETSC_OWN_POINTER, &Ais[1]));
623d0dbe9f7SStefano Zampini     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, n0, idx0, PETSC_COPY_VALUES, &Bis[0]));
624d0dbe9f7SStefano Zampini     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, n1, idx1, PETSC_COPY_VALUES, &Bis[1]));
625d0dbe9f7SStefano Zampini     PetscCall(MatIncreaseOverlap(A, 2, Ais, 3));
626d0dbe9f7SStefano Zampini     PetscCall(MatIncreaseOverlap(B, 2, Bis, 3));
627d0dbe9f7SStefano Zampini     /* Non deterministic output! */
628d0dbe9f7SStefano Zampini     PetscCall(ISSort(Ais[0]));
629d0dbe9f7SStefano Zampini     PetscCall(ISSort(Ais[1]));
630d0dbe9f7SStefano Zampini     PetscCall(ISSort(Bis[0]));
631d0dbe9f7SStefano Zampini     PetscCall(ISSort(Bis[1]));
632d0dbe9f7SStefano Zampini     PetscCall(ISView(Ais[0], NULL));
633d0dbe9f7SStefano Zampini     PetscCall(ISView(Bis[0], NULL));
634d0dbe9f7SStefano Zampini     PetscCall(ISView(Ais[1], NULL));
635d0dbe9f7SStefano Zampini     PetscCall(ISView(Bis[1], NULL));
636d0dbe9f7SStefano Zampini     PetscCall(MatCreateSubMatrices(A, 2, Ais, Ais, MAT_INITIAL_MATRIX, &Asub));
637d0dbe9f7SStefano Zampini     PetscCall(MatCreateSubMatrices(B, 2, Bis, Ais, MAT_INITIAL_MATRIX, &Bsub));
638d0dbe9f7SStefano Zampini     PetscCall(CheckMat(Asub[0], Bsub[0], PETSC_FALSE, "MatIncreaseOverlap[0]"));
639d0dbe9f7SStefano Zampini     PetscCall(CheckMat(Asub[1], Bsub[1], PETSC_FALSE, "MatIncreaseOverlap[1]"));
640d0dbe9f7SStefano Zampini     PetscCall(MatDestroySubMatrices(2, &Asub));
641d0dbe9f7SStefano Zampini     PetscCall(MatDestroySubMatrices(2, &Bsub));
642d0dbe9f7SStefano Zampini     PetscCall(ISDestroy(&Ais[0]));
643d0dbe9f7SStefano Zampini     PetscCall(ISDestroy(&Ais[1]));
644d0dbe9f7SStefano Zampini     PetscCall(ISDestroy(&Bis[0]));
645d0dbe9f7SStefano Zampini     PetscCall(ISDestroy(&Bis[1]));
646c4762a1bSJed Brown   }
6479566063dSJacob Faibussowitsch   PetscCall(TestMatZeroRows(A, B, squaretest, is, 0.0));
6489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
649c4762a1bSJed Brown 
650c4762a1bSJed Brown   /* test MatTranspose */
6519566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatTranspose\n"));
6529566063dSJacob Faibussowitsch   PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &A2));
6539566063dSJacob Faibussowitsch   PetscCall(MatTranspose(B, MAT_INITIAL_MATRIX, &B2));
6549566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "initial matrix MatTranspose"));
655c4762a1bSJed Brown 
6569566063dSJacob Faibussowitsch   PetscCall(MatTranspose(A, MAT_REUSE_MATRIX, &A2));
6579566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "reuse matrix (not in place) MatTranspose"));
6589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
659c4762a1bSJed Brown 
6609566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
6619566063dSJacob Faibussowitsch   PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2));
6629566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "reuse matrix (in place) MatTranspose"));
6639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
664c4762a1bSJed Brown 
6659566063dSJacob Faibussowitsch   PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &A2));
6669566063dSJacob Faibussowitsch   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "reuse matrix (different type) MatTranspose"));
6679566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A2));
6689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B2));
669c4762a1bSJed Brown 
670c4762a1bSJed Brown   /* test MatISFixLocalEmpty */
671c4762a1bSJed Brown   if (isaij) {
672c4762a1bSJed Brown     PetscInt r[2];
673c4762a1bSJed Brown 
674c4762a1bSJed Brown     r[0] = 0;
675c4762a1bSJed Brown     r[1] = PetscMin(m, n) - 1;
6769566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatISFixLocalEmpty\n"));
6779566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
678e432b41dSStefano Zampini 
6799566063dSJacob Faibussowitsch     PetscCall(MatISFixLocalEmpty(A2, PETSC_TRUE));
6809566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY));
6819566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY));
6829566063dSJacob Faibussowitsch     PetscCall(CheckMat(A2, B, PETSC_FALSE, "MatISFixLocalEmpty (null)"));
683c4762a1bSJed Brown 
6849566063dSJacob Faibussowitsch     PetscCall(MatZeroRows(A2, 2, r, 0.0, NULL, NULL));
6859566063dSJacob Faibussowitsch     PetscCall(MatViewFromOptions(A2, NULL, "-fixempty_view"));
6869566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
6879566063dSJacob Faibussowitsch     PetscCall(MatZeroRows(B2, 2, r, 0.0, NULL, NULL));
6889566063dSJacob Faibussowitsch     PetscCall(MatISFixLocalEmpty(A2, PETSC_TRUE));
6899566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY));
6909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY));
6919566063dSJacob Faibussowitsch     PetscCall(MatViewFromOptions(A2, NULL, "-fixempty_view"));
6929566063dSJacob Faibussowitsch     PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatISFixLocalEmpty (rows)"));
6939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A2));
694c4762a1bSJed Brown 
6959566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
6969566063dSJacob Faibussowitsch     PetscCall(MatZeroRows(A2, 2, r, 0.0, NULL, NULL));
6979566063dSJacob Faibussowitsch     PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2));
6989566063dSJacob Faibussowitsch     PetscCall(MatTranspose(B2, MAT_INPLACE_MATRIX, &B2));
6999566063dSJacob Faibussowitsch     PetscCall(MatViewFromOptions(A2, NULL, "-fixempty_view"));
7009566063dSJacob Faibussowitsch     PetscCall(MatISFixLocalEmpty(A2, PETSC_TRUE));
7019566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY));
7029566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY));
7039566063dSJacob Faibussowitsch     PetscCall(MatViewFromOptions(A2, NULL, "-fixempty_view"));
7049566063dSJacob Faibussowitsch     PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatISFixLocalEmpty (cols)"));
705c4762a1bSJed Brown 
7069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A2));
7079566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B2));
708c4762a1bSJed Brown 
709c4762a1bSJed Brown     if (squaretest) {
7109566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
7119566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
7129566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumns(A2, 2, r, 0.0, NULL, NULL));
7139566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumns(B2, 2, r, 0.0, NULL, NULL));
7149566063dSJacob Faibussowitsch       PetscCall(MatViewFromOptions(A2, NULL, "-fixempty_view"));
7159566063dSJacob Faibussowitsch       PetscCall(MatISFixLocalEmpty(A2, PETSC_TRUE));
7169566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY));
7179566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY));
7189566063dSJacob Faibussowitsch       PetscCall(MatViewFromOptions(A2, NULL, "-fixempty_view"));
7199566063dSJacob Faibussowitsch       PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatISFixLocalEmpty (rows+cols)"));
7209566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A2));
7219566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&B2));
722c4762a1bSJed Brown     }
723c4762a1bSJed Brown   }
724c4762a1bSJed Brown 
725c4762a1bSJed Brown   /* test MatInvertBlockDiagonal
726c4762a1bSJed Brown        special cases for block-diagonal matrices */
727c4762a1bSJed Brown   if (m == n) {
728c4762a1bSJed Brown     ISLocalToGlobalMapping map;
729c4762a1bSJed Brown     Mat                    Abd, Bbd;
730c4762a1bSJed Brown     IS                     is, bis;
731c4762a1bSJed Brown     const PetscScalar     *isbd, *aijbd;
732c4762a1bSJed Brown     const PetscInt        *sts, *idxs;
733c4762a1bSJed Brown     PetscInt              *idxs2, diff, perm, nl, bs, st, en, in;
734c4762a1bSJed Brown     PetscBool              ok;
735c4762a1bSJed Brown 
736c4762a1bSJed Brown     for (diff = 0; diff < 3; diff++) {
737c4762a1bSJed Brown       for (perm = 0; perm < 3; perm++) {
738c4762a1bSJed Brown         for (bs = 1; bs < 4; bs++) {
7399566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatInvertBlockDiagonal blockdiag %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", n, diff, perm, bs));
7409566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(bs * bs, &vals));
7419566063dSJacob Faibussowitsch           PetscCall(MatGetOwnershipRanges(A, &sts));
742c4762a1bSJed Brown           switch (diff) {
743c4762a1bSJed Brown           case 1: /* inverted layout by processes */
744c4762a1bSJed Brown             in = 1;
745c4762a1bSJed Brown             st = sts[size - rank - 1];
746c4762a1bSJed Brown             en = sts[size - rank];
747c4762a1bSJed Brown             nl = en - st;
748c4762a1bSJed Brown             break;
749c4762a1bSJed Brown           case 2: /* round-robin layout */
750c4762a1bSJed Brown             in = size;
751c4762a1bSJed Brown             st = rank;
752c4762a1bSJed Brown             nl = n / size;
753c4762a1bSJed Brown             if (rank < n % size) nl++;
754c4762a1bSJed Brown             break;
755c4762a1bSJed Brown           default: /* same layout */
756c4762a1bSJed Brown             in = 1;
757c4762a1bSJed Brown             st = sts[rank];
758c4762a1bSJed Brown             en = sts[rank + 1];
759c4762a1bSJed Brown             nl = en - st;
760c4762a1bSJed Brown             break;
761c4762a1bSJed Brown           }
7629566063dSJacob Faibussowitsch           PetscCall(ISCreateStride(PETSC_COMM_WORLD, nl, st, in, &is));
7639566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(is, &nl));
7649566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(is, &idxs));
7659566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(nl, &idxs2));
766c4762a1bSJed Brown           for (i = 0; i < nl; i++) {
767c4762a1bSJed Brown             switch (perm) { /* invert some of the indices */
768d71ae5a4SJacob Faibussowitsch             case 2:
769d71ae5a4SJacob Faibussowitsch               idxs2[i] = rank % 2 ? idxs[i] : idxs[nl - i - 1];
770d71ae5a4SJacob Faibussowitsch               break;
771d71ae5a4SJacob Faibussowitsch             case 1:
772d71ae5a4SJacob Faibussowitsch               idxs2[i] = rank % 2 ? idxs[nl - i - 1] : idxs[i];
773d71ae5a4SJacob Faibussowitsch               break;
774d71ae5a4SJacob Faibussowitsch             default:
775d71ae5a4SJacob Faibussowitsch               idxs2[i] = idxs[i];
776d71ae5a4SJacob Faibussowitsch               break;
777c4762a1bSJed Brown             }
778c4762a1bSJed Brown           }
7799566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(is, &idxs));
7809566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PETSC_COMM_WORLD, bs, nl, idxs2, PETSC_OWN_POINTER, &bis));
7819566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingCreateIS(bis, &map));
7829566063dSJacob Faibussowitsch           PetscCall(MatCreateIS(PETSC_COMM_WORLD, bs, PETSC_DECIDE, PETSC_DECIDE, bs * n, bs * n, map, map, &Abd));
7839566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingDestroy(&map));
7849566063dSJacob Faibussowitsch           PetscCall(MatISSetPreallocation(Abd, bs, NULL, 0, NULL));
785c4762a1bSJed Brown           for (i = 0; i < nl; i++) {
786c4762a1bSJed Brown             PetscInt b1, b2;
787c4762a1bSJed Brown 
788c4762a1bSJed Brown             for (b1 = 0; b1 < bs; b1++) {
789ad540459SPierre Jolivet               for (b2 = 0; b2 < bs; b2++) vals[b1 * bs + b2] = i * bs * bs + b1 * bs + b2 + 1 + (b1 == b2 ? 1.0 : 0);
790c4762a1bSJed Brown             }
7919566063dSJacob Faibussowitsch             PetscCall(MatSetValuesBlockedLocal(Abd, 1, &i, 1, &i, vals, INSERT_VALUES));
792c4762a1bSJed Brown           }
7939566063dSJacob Faibussowitsch           PetscCall(MatAssemblyBegin(Abd, MAT_FINAL_ASSEMBLY));
7949566063dSJacob Faibussowitsch           PetscCall(MatAssemblyEnd(Abd, MAT_FINAL_ASSEMBLY));
7959566063dSJacob Faibussowitsch           PetscCall(MatConvert(Abd, MATAIJ, MAT_INITIAL_MATRIX, &Bbd));
7969566063dSJacob Faibussowitsch           PetscCall(MatInvertBlockDiagonal(Abd, &isbd));
7979566063dSJacob Faibussowitsch           PetscCall(MatInvertBlockDiagonal(Bbd, &aijbd));
7989566063dSJacob Faibussowitsch           PetscCall(MatGetLocalSize(Bbd, &nl, NULL));
799c4762a1bSJed Brown           ok = PETSC_TRUE;
800c4762a1bSJed Brown           for (i = 0; i < nl / bs; i++) {
801c4762a1bSJed Brown             PetscInt b1, b2;
802c4762a1bSJed Brown 
803c4762a1bSJed Brown             for (b1 = 0; b1 < bs; b1++) {
804c4762a1bSJed Brown               for (b2 = 0; b2 < bs; b2++) {
805c4762a1bSJed Brown                 if (PetscAbsScalar(isbd[i * bs * bs + b1 * bs + b2] - aijbd[i * bs * bs + b1 * bs + b2]) > PETSC_SMALL) ok = PETSC_FALSE;
806c4762a1bSJed Brown                 if (!ok) {
8079566063dSJacob Faibussowitsch                   PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] ERROR block %" PetscInt_FMT ", entry %" PetscInt_FMT " %" PetscInt_FMT ": %g %g\n", rank, i, b1, b2, (double)PetscAbsScalar(isbd[i * bs * bs + b1 * bs + b2]), (double)PetscAbsScalar(aijbd[i * bs * bs + b1 * bs + b2])));
808c4762a1bSJed Brown                   break;
809c4762a1bSJed Brown                 }
810c4762a1bSJed Brown               }
811c4762a1bSJed Brown               if (!ok) break;
812c4762a1bSJed Brown             }
813c4762a1bSJed Brown             if (!ok) break;
814c4762a1bSJed Brown           }
8159566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&Abd));
8169566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&Bbd));
8179566063dSJacob Faibussowitsch           PetscCall(PetscFree(vals));
8189566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&is));
8199566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&bis));
820c4762a1bSJed Brown         }
821c4762a1bSJed Brown       }
822c4762a1bSJed Brown     }
823c4762a1bSJed Brown   }
824d0dbe9f7SStefano Zampini 
825d0dbe9f7SStefano Zampini   /* test MatGetDiagonalBlock */
826d0dbe9f7SStefano Zampini   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatGetDiagonalBlock\n"));
827d0dbe9f7SStefano Zampini   PetscCall(MatGetDiagonalBlock(A, &A2));
828d0dbe9f7SStefano Zampini   PetscCall(MatGetDiagonalBlock(B, &B2));
829d0dbe9f7SStefano Zampini   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatGetDiagonalBlock"));
830d0dbe9f7SStefano Zampini   PetscCall(MatScale(A, 2.0));
831d0dbe9f7SStefano Zampini   PetscCall(MatScale(B, 2.0));
832d0dbe9f7SStefano Zampini   PetscCall(MatGetDiagonalBlock(A, &A2));
833d0dbe9f7SStefano Zampini   PetscCall(MatGetDiagonalBlock(B, &B2));
834d0dbe9f7SStefano Zampini   PetscCall(CheckMat(A2, B2, PETSC_FALSE, "MatGetDiagonalBlock"));
835d0dbe9f7SStefano Zampini 
8364f58015eSStefano Zampini   /* test MatISSetAllowRepeated on a MATIS */
8374f58015eSStefano Zampini   PetscCall(MatISSetAllowRepeated(A, allow_repeated));
8384f58015eSStefano Zampini   if (allow_repeated) { /* original MATIS maybe with repeated entries, test assembling of local matrices */
8394f58015eSStefano Zampini     Mat lA, lA2;
8404f58015eSStefano Zampini 
8414f58015eSStefano Zampini     for (PetscInt i = 0; i < 1; i++) { /* TODO: make MatScatter inherit from MATSHELL and support MatProducts */
8424f58015eSStefano Zampini       PetscBool usemult = PETSC_FALSE;
8434f58015eSStefano Zampini 
8444f58015eSStefano Zampini       PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
8454f58015eSStefano Zampini       if (i) {
8464f58015eSStefano Zampini         Mat tA;
8474f58015eSStefano Zampini 
8484f58015eSStefano Zampini         usemult = PETSC_TRUE;
8494f58015eSStefano Zampini         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatISSetAllowRepeated(false) with possibly repeated entries and local shell matrices\n"));
8504f58015eSStefano Zampini         PetscCall(MatISGetLocalMat(A2, &lA2));
8514f58015eSStefano Zampini         PetscCall(MatConvert(lA2, MATSHELL, MAT_INITIAL_MATRIX, &tA));
8524f58015eSStefano Zampini         PetscCall(MatISRestoreLocalMat(A2, &lA2));
8534f58015eSStefano Zampini         PetscCall(MatISSetLocalMat(A2, tA));
8544f58015eSStefano Zampini         PetscCall(MatDestroy(&tA));
8554f58015eSStefano Zampini       } else {
8564f58015eSStefano Zampini         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatISSetAllowRepeated(false) with possibly repeated entries\n"));
8574f58015eSStefano Zampini       }
8584f58015eSStefano Zampini       PetscCall(MatISSetAllowRepeated(A2, PETSC_FALSE));
8594f58015eSStefano Zampini       PetscCall(MatISGetLocalMat(A, &lA));
8604f58015eSStefano Zampini       PetscCall(MatISGetLocalMat(A2, &lA2));
8614f58015eSStefano Zampini       if (!repmap) PetscCall(CheckMat(lA, lA2, usemult, "MatISSetAllowRepeated(false) with non-repeated entries"));
8624f58015eSStefano Zampini       PetscCall(MatISRestoreLocalMat(A, &lA));
8634f58015eSStefano Zampini       PetscCall(MatISRestoreLocalMat(A2, &lA2));
8644f58015eSStefano Zampini       if (repmap) PetscCall(CheckMat(A2, B, usemult, "MatISSetAllowRepeated(false) with repeated entries"));
8654f58015eSStefano Zampini       else PetscCall(CheckMat(A2, B, usemult, "MatISSetAllowRepeated(false) with non-repeated entries"));
8664f58015eSStefano Zampini       PetscCall(MatDestroy(&A2));
8674f58015eSStefano Zampini     }
8684f58015eSStefano Zampini   } else { /* original matis with non-repeated entries, this should only recreate the local matrices */
8694f58015eSStefano Zampini     Mat       lA;
8704f58015eSStefano Zampini     PetscBool flg;
8714f58015eSStefano Zampini 
8724f58015eSStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatISSetAllowRepeated(true) with non repeated entries\n"));
8734f58015eSStefano Zampini     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2));
8744f58015eSStefano Zampini     PetscCall(MatISSetAllowRepeated(A2, PETSC_TRUE));
8754f58015eSStefano Zampini     PetscCall(MatISGetLocalMat(A2, &lA));
8764f58015eSStefano Zampini     PetscCall(MatAssembled(lA, &flg));
8774f58015eSStefano Zampini     PetscCheck(!flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local mat should be unassembled");
8784f58015eSStefano Zampini     PetscCall(MatISRestoreLocalMat(A2, &lA));
8794f58015eSStefano Zampini     PetscCall(MatDestroy(&A2));
8804f58015eSStefano Zampini   }
8814f58015eSStefano Zampini 
88284a95373SStefano Zampini   /* Test MatZeroEntries */
88384a95373SStefano Zampini   PetscCall(MatZeroEntries(A));
88484a95373SStefano Zampini   PetscCall(MatZeroEntries(B));
88584a95373SStefano Zampini   PetscCall(CheckMat(A, B, PETSC_FALSE, "MatZeroEntries"));
88684a95373SStefano Zampini 
88784a95373SStefano Zampini   /* Test MatSetValues and MatSetValuesBlocked */
88884a95373SStefano Zampini   if (test_setvalues) {
88984a95373SStefano Zampini     PetscCall(PetscMalloc1(lm * ln, &vals));
89084a95373SStefano Zampini     for (i = 0; i < lm * ln; i++) vals[i] = i + 1.0;
89184a95373SStefano Zampini     PetscCall(MatGetLocalSize(A, NULL, &ln));
89284a95373SStefano Zampini     PetscCall(MatISSetPreallocation(A, ln, NULL, n - ln, NULL));
89384a95373SStefano Zampini     PetscCall(MatSeqAIJSetPreallocation(B, ln, NULL));
89484a95373SStefano Zampini     PetscCall(MatMPIAIJSetPreallocation(B, ln, NULL, n - ln, NULL));
89584a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetSize(rmap, &lm));
89684a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetSize(cmap, &ln));
89784a95373SStefano Zampini 
89884a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetIndices(rmap, &idxs1));
89984a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetIndices(cmap, &idxs2));
90084a95373SStefano Zampini     PetscCall(MatSetValues(A, lm, idxs1, ln, idxs2, vals, ADD_VALUES));
90184a95373SStefano Zampini     PetscCall(MatSetValues(B, lm, idxs1, ln, idxs2, vals, ADD_VALUES));
90284a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingRestoreIndices(rmap, &idxs1));
90384a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingRestoreIndices(cmap, &idxs2));
90484a95373SStefano Zampini     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
90584a95373SStefano Zampini     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
90684a95373SStefano Zampini     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
90784a95373SStefano Zampini     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
90884a95373SStefano Zampini     PetscCall(CheckMat(A, B, PETSC_FALSE, "MatSetValues"));
90984a95373SStefano Zampini 
91084a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetBlockIndices(rmap, &idxs1));
91184a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetBlockIndices(cmap, &idxs2));
91284a95373SStefano Zampini     PetscCall(MatSetValuesBlocked(A, lm / rbs, idxs1, ln / cbs, idxs2, vals, ADD_VALUES));
91384a95373SStefano Zampini     PetscCall(MatSetValuesBlocked(B, lm / rbs, idxs1, ln / cbs, idxs2, vals, ADD_VALUES));
91484a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rmap, &idxs1));
91584a95373SStefano Zampini     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cmap, &idxs2));
91684a95373SStefano Zampini     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
91784a95373SStefano Zampini     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
91884a95373SStefano Zampini     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
91984a95373SStefano Zampini     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
92084a95373SStefano Zampini     PetscCall(CheckMat(A, B, PETSC_FALSE, "MatSetValuesBlocked"));
92184a95373SStefano Zampini     PetscCall(PetscFree(vals));
92284a95373SStefano Zampini   }
92384a95373SStefano Zampini 
924c4762a1bSJed Brown   /* free testing matrices */
9259566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cmap));
9269566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rmap));
9279566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
9289566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
9299566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
930b122ec5aSJacob Faibussowitsch   return 0;
931c4762a1bSJed Brown }
932c4762a1bSJed Brown 
933d71ae5a4SJacob Faibussowitsch PetscErrorCode CheckMat(Mat A, Mat B, PetscBool usemult, const char *func)
934d71ae5a4SJacob Faibussowitsch {
935c4762a1bSJed Brown   Mat       Bcheck;
936c4762a1bSJed Brown   PetscReal error;
937c4762a1bSJed Brown 
938c4762a1bSJed Brown   PetscFunctionBeginUser;
939c4762a1bSJed Brown   if (!usemult && B) {
940c4762a1bSJed Brown     PetscBool hasnorm;
941c4762a1bSJed Brown 
9429566063dSJacob Faibussowitsch     PetscCall(MatHasOperation(B, MATOP_NORM, &hasnorm));
943c4762a1bSJed Brown     if (!hasnorm) usemult = PETSC_TRUE;
944c4762a1bSJed Brown   }
945c4762a1bSJed Brown   if (!usemult) {
946c4762a1bSJed Brown     if (B) {
947c4762a1bSJed Brown       MatType Btype;
948c4762a1bSJed Brown 
9499566063dSJacob Faibussowitsch       PetscCall(MatGetType(B, &Btype));
9509566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, Btype, MAT_INITIAL_MATRIX, &Bcheck));
951c4762a1bSJed Brown     } else {
9529566063dSJacob Faibussowitsch       PetscCall(MatConvert(A, MATAIJ, MAT_INITIAL_MATRIX, &Bcheck));
953c4762a1bSJed Brown     }
954c4762a1bSJed Brown     if (B) { /* if B is present, subtract it */
9559566063dSJacob Faibussowitsch       PetscCall(MatAXPY(Bcheck, -1., B, DIFFERENT_NONZERO_PATTERN));
956c4762a1bSJed Brown     }
9579566063dSJacob Faibussowitsch     PetscCall(MatNorm(Bcheck, NORM_INFINITY, &error));
958c4762a1bSJed Brown     if (error > PETSC_SQRT_MACHINE_EPSILON) {
959c4762a1bSJed Brown       ISLocalToGlobalMapping rl2g, cl2g;
960c4762a1bSJed Brown 
961d0dbe9f7SStefano Zampini       PetscCall(PetscObjectSetName((PetscObject)Bcheck, "Bcheck"));
9629566063dSJacob Faibussowitsch       PetscCall(MatView(Bcheck, NULL));
963c4762a1bSJed Brown       if (B) {
964d0dbe9f7SStefano Zampini         PetscCall(PetscObjectSetName((PetscObject)B, "B"));
9659566063dSJacob Faibussowitsch         PetscCall(MatView(B, NULL));
9669566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&Bcheck));
9679566063dSJacob Faibussowitsch         PetscCall(MatConvert(A, MATAIJ, MAT_INITIAL_MATRIX, &Bcheck));
968d0dbe9f7SStefano Zampini         PetscCall(PetscObjectSetName((PetscObject)Bcheck, "Assembled A"));
9699566063dSJacob Faibussowitsch         PetscCall(MatView(Bcheck, NULL));
970c4762a1bSJed Brown       }
9719566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bcheck));
972d0dbe9f7SStefano Zampini       PetscCall(PetscObjectSetName((PetscObject)A, "A"));
9739566063dSJacob Faibussowitsch       PetscCall(MatView(A, NULL));
9749566063dSJacob Faibussowitsch       PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g));
975d0dbe9f7SStefano Zampini       if (rl2g) PetscCall(ISLocalToGlobalMappingView(rl2g, NULL));
976d0dbe9f7SStefano Zampini       if (cl2g) PetscCall(ISLocalToGlobalMappingView(cl2g, NULL));
977d0dbe9f7SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "ERROR ON %s: %g", func, (double)error);
978c4762a1bSJed Brown     }
9799566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bcheck));
980c4762a1bSJed Brown   } else {
981c4762a1bSJed Brown     PetscBool ok, okt;
982c4762a1bSJed Brown 
9839566063dSJacob Faibussowitsch     PetscCall(MatMultEqual(A, B, 3, &ok));
9849566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeEqual(A, B, 3, &okt));
985e00437b9SBarry Smith     PetscCheck(ok && okt, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "ERROR ON %s: mult ok ?  %d, multtranspose ok ? %d", func, ok, okt);
986c4762a1bSJed Brown   }
9873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
988c4762a1bSJed Brown }
989c4762a1bSJed Brown 
990d71ae5a4SJacob Faibussowitsch PetscErrorCode TestMatZeroRows(Mat A, Mat Afull, PetscBool squaretest, IS is, PetscScalar diag)
991d71ae5a4SJacob Faibussowitsch {
992c4762a1bSJed Brown   Mat                    B, Bcheck, B2 = NULL, lB;
993c4762a1bSJed Brown   Vec                    x = NULL, b = NULL, b2 = NULL;
994c4762a1bSJed Brown   ISLocalToGlobalMapping l2gr, l2gc;
995c4762a1bSJed Brown   PetscReal              error;
996c4762a1bSJed Brown   char                   diagstr[16];
997c4762a1bSJed Brown   const PetscInt        *idxs;
998c4762a1bSJed Brown   PetscInt               rst, ren, i, n, N, d;
999c4762a1bSJed Brown   PetscMPIInt            rank;
1000c4762a1bSJed Brown   PetscBool              miss, haszerorows;
1001c4762a1bSJed Brown 
1002c4762a1bSJed Brown   PetscFunctionBeginUser;
1003c4762a1bSJed Brown   if (diag == 0.) {
1004c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(diagstr, "zero", sizeof(diagstr)));
1005c4762a1bSJed Brown   } else {
1006c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(diagstr, "nonzero", sizeof(diagstr)));
1007c4762a1bSJed Brown   }
10089566063dSJacob Faibussowitsch   PetscCall(ISView(is, NULL));
10099566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(A, &l2gr, &l2gc));
1010c4762a1bSJed Brown   /* tests MatDuplicate and MatCopy */
1011c4762a1bSJed Brown   if (diag == 0.) {
10129566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B));
1013c4762a1bSJed Brown   } else {
10149566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
10159566063dSJacob Faibussowitsch     PetscCall(MatCopy(A, B, SAME_NONZERO_PATTERN));
1016c4762a1bSJed Brown   }
10179566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(B, &lB));
10189566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(lB, MATOP_ZERO_ROWS, &haszerorows));
1019c4762a1bSJed Brown   if (squaretest && haszerorows) {
10209566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(B, &x, &b));
10219566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2));
10229566063dSJacob Faibussowitsch     PetscCall(VecSetLocalToGlobalMapping(b, l2gr));
10239566063dSJacob Faibussowitsch     PetscCall(VecSetLocalToGlobalMapping(x, l2gc));
10249566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(x, NULL));
10259566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(b, NULL));
1026c4762a1bSJed Brown     /* mimic b[is] = x[is] */
10279566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(b, &b2));
10289566063dSJacob Faibussowitsch     PetscCall(VecSetLocalToGlobalMapping(b2, l2gr));
10299566063dSJacob Faibussowitsch     PetscCall(VecCopy(b, b2));
10309566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is, &n));
10319566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &idxs));
10329566063dSJacob Faibussowitsch     PetscCall(VecGetSize(x, &N));
1033c4762a1bSJed Brown     for (i = 0; i < n; i++) {
1034c4762a1bSJed Brown       if (0 <= idxs[i] && idxs[i] < N) {
10359566063dSJacob Faibussowitsch         PetscCall(VecSetValue(b2, idxs[i], diag, INSERT_VALUES));
10369566063dSJacob Faibussowitsch         PetscCall(VecSetValue(x, idxs[i], 1., INSERT_VALUES));
1037c4762a1bSJed Brown       }
1038c4762a1bSJed Brown     }
10399566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(b2));
10409566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(b2));
10419566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(x));
10429566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(x));
10439566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &idxs));
1044c4762a1bSJed Brown     /*  test ZeroRows on MATIS */
10459566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatZeroRows (diag %s)\n", diagstr));
10469566063dSJacob Faibussowitsch     PetscCall(MatZeroRowsIS(B, is, diag, x, b));
10479566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatZeroRowsColumns (diag %s)\n", diagstr));
10489566063dSJacob Faibussowitsch     PetscCall(MatZeroRowsColumnsIS(B2, is, diag, NULL, NULL));
1049c4762a1bSJed Brown   } else if (haszerorows) {
1050c4762a1bSJed Brown     /*  test ZeroRows on MATIS */
10519566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatZeroRows (diag %s)\n", diagstr));
10529566063dSJacob Faibussowitsch     PetscCall(MatZeroRowsIS(B, is, diag, NULL, NULL));
1053c4762a1bSJed Brown     b = b2 = x = NULL;
1054c4762a1bSJed Brown   } else {
10559566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Skipping MatZeroRows (diag %s)\n", diagstr));
1056c4762a1bSJed Brown     b = b2 = x = NULL;
1057c4762a1bSJed Brown   }
1058c4762a1bSJed Brown 
1059c4762a1bSJed Brown   if (squaretest && haszerorows) {
10609566063dSJacob Faibussowitsch     PetscCall(VecAXPY(b2, -1., b));
10619566063dSJacob Faibussowitsch     PetscCall(VecNorm(b2, NORM_INFINITY, &error));
1062e00437b9SBarry Smith     PetscCheck(error <= PETSC_SQRT_MACHINE_EPSILON, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "ERROR IN ZEROROWS ON B %g (diag %s)", (double)error, diagstr);
1063c4762a1bSJed Brown   }
1064c4762a1bSJed Brown 
1065c4762a1bSJed Brown   /* test MatMissingDiagonal */
10669566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test MatMissingDiagonal\n"));
10679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
10689566063dSJacob Faibussowitsch   PetscCall(MatMissingDiagonal(B, &miss, &d));
10699566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(B, &rst, &ren));
10709566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(PETSC_VIEWER_STDOUT_WORLD));
10719566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISynchronizedPrintf(PETSC_VIEWER_STDOUT_WORLD, "[%d] [%" PetscInt_FMT ",%" PetscInt_FMT ") Missing %d, row %" PetscInt_FMT " (diag %s)\n", rank, rst, ren, (int)miss, d, diagstr));
10729566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD));
10739566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(PETSC_VIEWER_STDOUT_WORLD));
1074c4762a1bSJed Brown 
10759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
10769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b));
10779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b2));
1078c4762a1bSJed Brown 
1079c4762a1bSJed Brown   /* check the result of ZeroRows with that from MPIAIJ routines
1080c4762a1bSJed Brown      assuming that MatConvert_IS_XAIJ and MatZeroRows_MPIAIJ work fine */
1081c4762a1bSJed Brown   if (haszerorows) {
10829566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(Afull, MAT_COPY_VALUES, &Bcheck));
10839566063dSJacob Faibussowitsch     PetscCall(MatSetOption(Bcheck, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
10849566063dSJacob Faibussowitsch     PetscCall(MatZeroRowsIS(Bcheck, is, diag, NULL, NULL));
10859566063dSJacob Faibussowitsch     PetscCall(CheckMat(B, Bcheck, PETSC_FALSE, "Zerorows"));
10869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bcheck));
1087c4762a1bSJed Brown   }
10889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
1089c4762a1bSJed Brown 
1090c4762a1bSJed Brown   if (B2) { /* test MatZeroRowsColumns */
10919566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(Afull, MAT_COPY_VALUES, &B));
10929566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
10939566063dSJacob Faibussowitsch     PetscCall(MatZeroRowsColumnsIS(B, is, diag, NULL, NULL));
10949566063dSJacob Faibussowitsch     PetscCall(CheckMat(B2, B, PETSC_FALSE, "MatZeroRowsColumns"));
10959566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
10969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B2));
1097c4762a1bSJed Brown   }
10983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1099c4762a1bSJed Brown }
1100c4762a1bSJed Brown 
1101c4762a1bSJed Brown /*TEST
1102c4762a1bSJed Brown 
1103c4762a1bSJed Brown    test:
11045042aa92SStefano Zampini       requires: !complex
11055042aa92SStefano Zampini       args: -test_matlab -test_trans
1106c4762a1bSJed Brown 
1107c4762a1bSJed Brown    test:
1108c4762a1bSJed Brown       suffix: 2
1109c4762a1bSJed Brown       nsize: 4
11104f58015eSStefano Zampini       args: -mat_is_convert_local_nest -nr 3 -nc 4
1111c4762a1bSJed Brown 
1112c4762a1bSJed Brown    test:
1113c4762a1bSJed Brown       suffix: 3
1114c4762a1bSJed Brown       nsize: 5
1115a50ef18cSStefano Zampini       args: -m 11 -n 10 -mat_is_convert_local_nest -nr 2 -nc 1 -cbs 2
1116c4762a1bSJed Brown 
1117c4762a1bSJed Brown    test:
1118c4762a1bSJed Brown       suffix: 4
1119c4762a1bSJed Brown       nsize: 6
1120c4762a1bSJed Brown       args: -m 9 -n 12 -test_trans -nr 2 -nc 7
1121c4762a1bSJed Brown 
1122c4762a1bSJed Brown    test:
1123c4762a1bSJed Brown       suffix: 5
1124c4762a1bSJed Brown       nsize: 6
1125a50ef18cSStefano Zampini       args: -m 12 -n 12 -test_trans -nr 3 -nc 1 -rbs 2
1126c4762a1bSJed Brown 
1127c4762a1bSJed Brown    test:
1128c4762a1bSJed Brown       suffix: 6
1129a50ef18cSStefano Zampini       args: -m 12 -n 12 -test_trans -nr 2 -nc 3 -diffmap -rbs 6 -cbs 3
1130c4762a1bSJed Brown 
1131c4762a1bSJed Brown    test:
1132c4762a1bSJed Brown       suffix: 7
1133c4762a1bSJed Brown       args: -m 12 -n 12 -test_trans -nr 2 -nc 3 -diffmap -permmap
1134c4762a1bSJed Brown 
1135c4762a1bSJed Brown    test:
1136c4762a1bSJed Brown       suffix: 8
1137c4762a1bSJed Brown       args: -m 12 -n 17 -test_trans -nr 2 -nc 3 -permmap
1138c4762a1bSJed Brown 
1139c4762a1bSJed Brown    test:
1140c4762a1bSJed Brown       suffix: 9
1141c4762a1bSJed Brown       nsize: 5
1142c4762a1bSJed Brown       args: -m 12 -n 12 -test_trans -nr 2 -nc 3 -diffmap
1143c4762a1bSJed Brown 
1144c4762a1bSJed Brown    test:
1145c4762a1bSJed Brown       suffix: 10
1146c4762a1bSJed Brown       nsize: 5
1147c4762a1bSJed Brown       args: -m 12 -n 12 -test_trans -nr 2 -nc 3 -diffmap -permmap
1148c4762a1bSJed Brown 
1149c20d7725SJed Brown    test:
1150c20d7725SJed Brown       suffix: vscat_default
1151c4762a1bSJed Brown       nsize: 5
1152c4762a1bSJed Brown       args: -m 12 -n 17 -test_trans -nr 2 -nc 3 -permmap
1153c4762a1bSJed Brown       output_file: output/ex23_11.out
1154c4762a1bSJed Brown 
1155c4762a1bSJed Brown    test:
1156c4762a1bSJed Brown       suffix: 12
1157c4762a1bSJed Brown       nsize: 3
115884a95373SStefano Zampini       args: -m 12 -n 12 -symmetric -mat_is_localmat_type sbaij -test_trans -nr 2 -nc 3 -test_setvalues 0
1159c4762a1bSJed Brown 
1160c4762a1bSJed Brown    testset:
1161c4762a1bSJed Brown       output_file: output/ex23_13.out
1162c4762a1bSJed Brown       nsize: 3
1163c4762a1bSJed Brown       args: -m 12 -n 17 -test_trans -nr 2 -nc 3 -diffmap -permmap
11645042aa92SStefano Zampini       filter: grep -v "type:" | grep -v "block size is 1" | grep -v "not using I-node routines"
1165c4762a1bSJed Brown       test:
1166c4762a1bSJed Brown         suffix: baij
11674f58015eSStefano Zampini         args: -mat_is_localmat_type baij
1168c4762a1bSJed Brown       test:
1169c4762a1bSJed Brown         requires: viennacl
1170c4762a1bSJed Brown         suffix: viennacl
11714f58015eSStefano Zampini         args: -mat_is_localmat_type aijviennacl
1172c4762a1bSJed Brown       test:
1173c4762a1bSJed Brown         requires: cuda
1174c4762a1bSJed Brown         suffix: cusparse
11754f58015eSStefano Zampini         args: -mat_is_localmat_type aijcusparse
11765042aa92SStefano Zampini       test:
11775042aa92SStefano Zampini         requires: kokkos_kernels
11785042aa92SStefano Zampini         suffix: kokkos
11795042aa92SStefano Zampini         args: -mat_is_localmat_type aijkokkos
1180c4762a1bSJed Brown 
1181e432b41dSStefano Zampini    test:
1182e432b41dSStefano Zampini       suffix: negrep
1183e432b41dSStefano Zampini       nsize: {{1 3}separate output}
11844f58015eSStefano Zampini       args: -m {{5 7}separate output} -n {{5 7}separate output} -test_trans -nr 2 -nc 3 -negmap {{0 1}separate output} -repmap {{0 1}separate output} -permmap -diffmap {{0 1}separate output} -allow_repeated 0
11854f58015eSStefano Zampini 
11864f58015eSStefano Zampini    test:
11874f58015eSStefano Zampini       suffix: negrep_allowrep
11884f58015eSStefano Zampini       nsize: {{1 3}separate output}
11894f58015eSStefano Zampini       args: -m {{5 7}separate output} -n {{5 7}separate output} -test_trans -nr 2 -nc 3 -negmap {{0 1}separate output} -repmap {{0 1}separate output} -permmap -diffmap {{0 1}separate output} -allow_repeated
1190e432b41dSStefano Zampini 
1191c4762a1bSJed Brown TEST*/
1192