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 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 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