1c4762a1bSJed Brown static char help[] = "Tests MatCreateSubmatrix() in parallel.";
2c4762a1bSJed Brown
3c4762a1bSJed Brown #include <petscmat.h>
4c4762a1bSJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h>
5c4762a1bSJed Brown
ISGetSeqIS_SameColDist_Private(Mat mat,IS isrow,IS iscol,IS * isrow_d,IS * iscol_d,IS * iscol_o,const PetscInt * garray[])6d71ae5a4SJacob Faibussowitsch PetscErrorCode ISGetSeqIS_SameColDist_Private(Mat mat, IS isrow, IS iscol, IS *isrow_d, IS *iscol_d, IS *iscol_o, const PetscInt *garray[])
7d71ae5a4SJacob Faibussowitsch {
8c4762a1bSJed Brown Vec x, cmap;
9c4762a1bSJed Brown const PetscInt *is_idx;
10c4762a1bSJed Brown PetscScalar *xarray, *cmaparray;
11c4762a1bSJed Brown PetscInt ncols, isstart, *idx, m, rstart, count;
12c4762a1bSJed Brown Mat_MPIAIJ *a = (Mat_MPIAIJ *)mat->data;
13c4762a1bSJed Brown Mat B = a->B;
14c4762a1bSJed Brown Vec lvec = a->lvec, lcmap;
15c4762a1bSJed Brown PetscInt i, cstart, cend, Bn = B->cmap->N;
16c4762a1bSJed Brown MPI_Comm comm;
17c4762a1bSJed Brown PetscMPIInt rank;
18c4762a1bSJed Brown VecScatter Mvctx;
19c4762a1bSJed Brown
20c4762a1bSJed Brown PetscFunctionBegin;
219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
239566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &ncols));
24c4762a1bSJed Brown
25c4762a1bSJed Brown /* (1) iscol is a sub-column vector of mat, pad it with '-1.' to form a full vector x */
269566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat, &x, NULL));
279566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &cmap));
289566063dSJacob Faibussowitsch PetscCall(VecSet(x, -1.0));
299566063dSJacob Faibussowitsch PetscCall(VecSet(cmap, -1.0));
30c4762a1bSJed Brown
319566063dSJacob Faibussowitsch PetscCall(VecDuplicate(lvec, &lcmap));
32c4762a1bSJed Brown
33c4762a1bSJed Brown /* Get start indices */
349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&ncols, &isstart, 1, MPIU_INT, MPI_SUM, comm));
35c4762a1bSJed Brown isstart -= ncols;
369566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
37c4762a1bSJed Brown
389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &is_idx));
399566063dSJacob Faibussowitsch PetscCall(VecGetArray(x, &xarray));
409566063dSJacob Faibussowitsch PetscCall(VecGetArray(cmap, &cmaparray));
419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncols, &idx));
42c4762a1bSJed Brown for (i = 0; i < ncols; i++) {
43c4762a1bSJed Brown xarray[is_idx[i] - cstart] = (PetscScalar)is_idx[i];
44c4762a1bSJed Brown cmaparray[is_idx[i] - cstart] = (PetscScalar)(i + isstart); /* global index of iscol[i] */
45c4762a1bSJed Brown idx[i] = is_idx[i] - cstart; /* local index of iscol[i] */
46c4762a1bSJed Brown }
479566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(x, &xarray));
489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cmap, &cmaparray));
499566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &is_idx));
50c4762a1bSJed Brown
51c4762a1bSJed Brown /* Get iscol_d */
529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncols, idx, PETSC_OWN_POINTER, iscol_d));
539566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol, &i));
549566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(*iscol_d, i));
55c4762a1bSJed Brown
56c4762a1bSJed Brown /* Get isrow_d */
579566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &m));
58c4762a1bSJed Brown rstart = mat->rmap->rstart;
599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idx));
609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &is_idx));
61c4762a1bSJed Brown for (i = 0; i < m; i++) idx[i] = is_idx[i] - rstart;
629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &is_idx));
63c4762a1bSJed Brown
649566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idx, PETSC_OWN_POINTER, isrow_d));
659566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow, &i));
669566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(*isrow_d, i));
67c4762a1bSJed Brown
68c4762a1bSJed Brown /* (2) Scatter x and cmap using aij->Mvctx to get their off-process portions (see MatMult_MPIAIJ) */
69c4762a1bSJed Brown #if 0
70c4762a1bSJed Brown if (!a->Mvctx_mpi1) {
71c4762a1bSJed Brown /* a->Mvctx causes random 'count' in o-build? See src/mat/tests/runex59_2 */
72c4762a1bSJed Brown a->Mvctx_mpi1_flg = PETSC_TRUE;
739566063dSJacob Faibussowitsch PetscCall(MatSetUpMultiply_MPIAIJ(mat));
74c4762a1bSJed Brown }
75c4762a1bSJed Brown Mvctx = a->Mvctx_mpi1;
76c4762a1bSJed Brown #endif
77c4762a1bSJed Brown Mvctx = a->Mvctx;
789566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Mvctx, x, lvec, INSERT_VALUES, SCATTER_FORWARD));
799566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Mvctx, x, lvec, INSERT_VALUES, SCATTER_FORWARD));
80c4762a1bSJed Brown
819566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Mvctx, cmap, lcmap, INSERT_VALUES, SCATTER_FORWARD));
829566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Mvctx, cmap, lcmap, INSERT_VALUES, SCATTER_FORWARD));
83c4762a1bSJed Brown
84c4762a1bSJed Brown /* (3) create sequential iscol_o (a subset of iscol) and isgarray */
85c4762a1bSJed Brown /* off-process column indices */
86c4762a1bSJed Brown count = 0;
87c4762a1bSJed Brown PetscInt *cmap1;
889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Bn, &idx));
899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Bn, &cmap1));
90c4762a1bSJed Brown
919566063dSJacob Faibussowitsch PetscCall(VecGetArray(lvec, &xarray));
929566063dSJacob Faibussowitsch PetscCall(VecGetArray(lcmap, &cmaparray));
93c4762a1bSJed Brown for (i = 0; i < Bn; i++) {
94c4762a1bSJed Brown if (PetscRealPart(xarray[i]) > -1.0) {
95c4762a1bSJed Brown idx[count] = i; /* local column index in off-diagonal part B */
96c4762a1bSJed Brown cmap1[count] = (PetscInt)(PetscRealPart(cmaparray[i])); /* column index in submat */
97c4762a1bSJed Brown count++;
98c4762a1bSJed Brown }
99c4762a1bSJed Brown }
100c4762a1bSJed Brown printf("[%d] Bn %d, count %d\n", rank, Bn, count);
1019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(lvec, &xarray));
1029566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(lcmap, &cmaparray));
103c4762a1bSJed Brown if (count != 6) {
104c4762a1bSJed Brown printf("[%d] count %d != 6 lvec:\n", rank, count);
1059566063dSJacob Faibussowitsch PetscCall(VecView(lvec, 0));
106c4762a1bSJed Brown
107c4762a1bSJed Brown printf("[%d] count %d != 6 lcmap:\n", rank, count);
1089566063dSJacob Faibussowitsch PetscCall(VecView(lcmap, 0));
10998921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "count %d != 6", count);
110c4762a1bSJed Brown }
111c4762a1bSJed Brown
1129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, count, idx, PETSC_COPY_VALUES, iscol_o));
113c4762a1bSJed Brown /* cannot ensure iscol_o has same blocksize as iscol! */
114c4762a1bSJed Brown
1159566063dSJacob Faibussowitsch PetscCall(PetscFree(idx));
116c4762a1bSJed Brown
117c4762a1bSJed Brown *garray = cmap1;
118c4762a1bSJed Brown
1199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x));
1209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cmap));
1219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lcmap));
1223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
123c4762a1bSJed Brown }
124c4762a1bSJed Brown
main(int argc,char ** args)125d71ae5a4SJacob Faibussowitsch int main(int argc, char **args)
126d71ae5a4SJacob Faibussowitsch {
127c4762a1bSJed Brown Mat C, A;
128c4762a1bSJed Brown PetscInt i, j, m = 3, n = 2, rstart, rend;
129c4762a1bSJed Brown PetscMPIInt size, rank;
130c4762a1bSJed Brown PetscScalar v;
131c4762a1bSJed Brown IS isrow, iscol;
132c4762a1bSJed Brown
133327415f7SBarry Smith PetscFunctionBeginUser;
134*c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &args, NULL, help));
1359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
137c4762a1bSJed Brown n = 2 * size;
138c4762a1bSJed Brown
1399566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &C));
1409566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, PETSC_DECIDE, PETSC_DECIDE, m * n, m * n));
1419566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(C));
1429566063dSJacob Faibussowitsch PetscCall(MatSetUp(C));
143c4762a1bSJed Brown
144c4762a1bSJed Brown /*
145c4762a1bSJed Brown This is JUST to generate a nice test matrix, all processors fill up
146c4762a1bSJed Brown the entire matrix. This is not something one would ever do in practice.
147c4762a1bSJed Brown */
1489566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
149c4762a1bSJed Brown for (i = rstart; i < rend; i++) {
150c4762a1bSJed Brown for (j = 0; j < m * n; j++) {
151c4762a1bSJed Brown v = i + j + 1;
1529566063dSJacob Faibussowitsch PetscCall(MatSetValues(C, 1, &i, 1, &j, &v, INSERT_VALUES));
153c4762a1bSJed Brown }
154c4762a1bSJed Brown }
155c4762a1bSJed Brown
1569566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
1579566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
158c4762a1bSJed Brown
159c4762a1bSJed Brown /*
160c4762a1bSJed Brown Generate a new matrix consisting of every second row and column of
161c4762a1bSJed Brown the original matrix
162c4762a1bSJed Brown */
1639566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
164c4762a1bSJed Brown /* Create parallel IS with the rows we want on THIS processor */
1659566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_WORLD, (rend - rstart) / 2, rstart, 2, &isrow));
166c4762a1bSJed Brown /* Create parallel IS with the rows we want on THIS processor (same as rows for now) */
1679566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_WORLD, (rend - rstart) / 2, rstart, 2, &iscol));
168c4762a1bSJed Brown
169c4762a1bSJed Brown IS iscol_d, isrow_d, iscol_o;
170c4762a1bSJed Brown const PetscInt *garray;
1719566063dSJacob Faibussowitsch PetscCall(ISGetSeqIS_SameColDist_Private(C, isrow, iscol, &isrow_d, &iscol_d, &iscol_o, &garray));
172c4762a1bSJed Brown
1739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow_d));
1749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_d));
1759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_o));
1769566063dSJacob Faibussowitsch PetscCall(PetscFree(garray));
177c4762a1bSJed Brown
1789566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(C, isrow, iscol, MAT_INITIAL_MATRIX, &A));
1799566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(C, isrow, iscol, MAT_REUSE_MATRIX, &A));
180c4762a1bSJed Brown
1819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow));
1829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol));
1839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A));
1849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
1859566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
186b122ec5aSJacob Faibussowitsch return 0;
187c4762a1bSJed Brown }
188