1 static char help[] = "Test vecscatter of different block sizes across processes\n\n"; 2 3 #include <petscvec.h> 4 int main(int argc, char **argv) 5 { 6 PetscInt i, bs, n, low, high; 7 PetscMPIInt nproc, rank; 8 Vec x, y, z; 9 IS ix, iy; 10 VecScatter vscat; 11 const PetscScalar *yv; 12 13 PetscFunctionBeginUser; 14 PetscCall(PetscInitialize(&argc, &argv, (char *)0, help)); 15 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &nproc)); 16 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 17 PetscCheck(nproc == 2, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This test can only run on two MPI ranks"); 18 19 /* Create an MPI vector x of size 12 on two processes, and set x = {0, 1, 2, .., 11} */ 20 PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 6, PETSC_DECIDE, &x)); 21 PetscCall(VecGetOwnershipRange(x, &low, &high)); 22 for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i, INSERT_VALUES)); 23 PetscCall(VecAssemblyBegin(x)); 24 PetscCall(VecAssemblyEnd(x)); 25 26 /* Create a seq vector y, and a parallel to sequential (PtoS) vecscatter to scatter x to y */ 27 if (rank == 0) { 28 /* On rank 0, seq y is of size 6. We will scatter x[0,1,2,6,7,8] to y[0,1,2,3,4,5] using IS with bs=3 */ 29 PetscInt idx[2] = {0, 2}; 30 PetscInt idy[2] = {0, 1}; 31 n = 6; 32 bs = 3; 33 PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, &y)); 34 PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, 2, idx, PETSC_COPY_VALUES, &ix)); 35 PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, 2, idy, PETSC_COPY_VALUES, &iy)); 36 } else { 37 /* On rank 1, seq y is of size 4. We will scatter x[4,5,10,11] to y[0,1,2,3] using IS with bs=2 */ 38 PetscInt idx[2] = {2, 5}; 39 PetscInt idy[2] = {0, 1}; 40 n = 4; 41 bs = 2; 42 PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, &y)); 43 PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, 2, idx, PETSC_COPY_VALUES, &ix)); 44 PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, 2, idy, PETSC_COPY_VALUES, &iy)); 45 } 46 PetscCall(VecScatterCreate(x, ix, y, iy, &vscat)); 47 48 /* Do the vecscatter */ 49 PetscCall(VecScatterBegin(vscat, x, y, INSERT_VALUES, SCATTER_FORWARD)); 50 PetscCall(VecScatterEnd(vscat, x, y, INSERT_VALUES, SCATTER_FORWARD)); 51 52 /* Print y. Since y is sequential, we put y in a parallel z to print its value on both ranks */ 53 PetscCall(VecGetArrayRead(y, &yv)); 54 PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, n, PETSC_DECIDE, yv, &z)); 55 PetscCall(VecView(z, PETSC_VIEWER_STDOUT_WORLD)); 56 PetscCall(VecRestoreArrayRead(y, &yv)); 57 58 PetscCall(ISDestroy(&ix)); 59 PetscCall(ISDestroy(&iy)); 60 PetscCall(VecDestroy(&x)); 61 PetscCall(VecDestroy(&y)); 62 PetscCall(VecDestroy(&z)); 63 PetscCall(VecScatterDestroy(&vscat)); 64 65 PetscCall(PetscFinalize()); 66 return 0; 67 } 68 69 /*TEST 70 71 test: 72 nsize: 2 73 args: 74 requires: 75 TEST*/ 76