1*97929ea7SJunchao Zhang static char help[]= "This example shows 1) how to transfer vectors from a parent communicator to vectors on a child communicator and vice versa;\n\ 2*97929ea7SJunchao Zhang 2) how to transfer vectors from a subcommunicator to vectors on another subcommunicator. The two subcommunicators are not\n\ 3*97929ea7SJunchao Zhang required to cover all processes in PETSC_COMM_WORLD; 3) how to copy a vector from a parent communicator to vectors on its child communicators.\n\n"; 4*97929ea7SJunchao Zhang 5*97929ea7SJunchao Zhang #include <petscvec.h> 6*97929ea7SJunchao Zhang int main(int argc,char **argv) 7*97929ea7SJunchao Zhang { 8*97929ea7SJunchao Zhang PetscErrorCode ierr; 9*97929ea7SJunchao Zhang PetscMPIInt nproc,grank,mycolor; 10*97929ea7SJunchao Zhang PetscInt i,n,N = 20,low,high; 11*97929ea7SJunchao Zhang MPI_Comm subcomm; 12*97929ea7SJunchao Zhang Vec x,yg; /* global vectors on PETSC_COMM_WORLD */ 13*97929ea7SJunchao Zhang VecScatter vscat; 14*97929ea7SJunchao Zhang IS ix,iy; 15*97929ea7SJunchao Zhang PetscBool world2sub = PETSC_FALSE; /* Copy a vector from WORLD to a subcomm? */ 16*97929ea7SJunchao Zhang PetscBool sub2sub = PETSC_FALSE; /* Copy a vector from a subcomm to another subcomm? */ 17*97929ea7SJunchao Zhang PetscBool world2subs = PETSC_FALSE; /* Copy a vector from WORLD to multiple subcomms? */ 18*97929ea7SJunchao Zhang 19*97929ea7SJunchao Zhang ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; 20*97929ea7SJunchao Zhang ierr = MPI_Comm_size(PETSC_COMM_WORLD,&nproc);CHKERRQ(ierr); 21*97929ea7SJunchao Zhang ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&grank);CHKERRQ(ierr); 22*97929ea7SJunchao Zhang 23*97929ea7SJunchao Zhang if (nproc < 2) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_SIZ,"This test must have at least two processes to run"); 24*97929ea7SJunchao Zhang 25*97929ea7SJunchao Zhang ierr = PetscOptionsGetBool(NULL,0,"-world2sub",&world2sub,NULL);CHKERRQ(ierr); 26*97929ea7SJunchao Zhang ierr = PetscOptionsGetBool(NULL,0,"-sub2sub",&sub2sub,NULL);CHKERRQ(ierr); 27*97929ea7SJunchao Zhang ierr = PetscOptionsGetBool(NULL,0,"-world2subs",&world2subs,NULL);CHKERRQ(ierr); 28*97929ea7SJunchao Zhang 29*97929ea7SJunchao Zhang /* Split PETSC_COMM_WORLD into three subcomms. Each process can only see the subcomm it belongs to */ 30*97929ea7SJunchao Zhang mycolor = grank % 3; 31*97929ea7SJunchao Zhang ierr = MPI_Comm_split(PETSC_COMM_WORLD,mycolor,grank,&subcomm);CHKERRQ(ierr); 32*97929ea7SJunchao Zhang 33*97929ea7SJunchao Zhang /*=========================================================================== 34*97929ea7SJunchao Zhang * Transfer a vector x defined on PETSC_COMM_WORLD to a vector y defined on 35*97929ea7SJunchao Zhang * a subcommunicator of PETSC_COMM_WORLD and vice versa. 36*97929ea7SJunchao Zhang *===========================================================================*/ 37*97929ea7SJunchao Zhang if (world2sub) { 38*97929ea7SJunchao Zhang ierr = VecCreateMPI(PETSC_COMM_WORLD,PETSC_DECIDE,N,&x);CHKERRQ(ierr); 39*97929ea7SJunchao Zhang ierr = PetscObjectSetName((PetscObject)x,"x_commworld");CHKERRQ(ierr); /* Give a name to view x clearly */ 40*97929ea7SJunchao Zhang 41*97929ea7SJunchao Zhang /* Initialize x to [-0.0, -1.0, -2.0, ..., -19.0] */ 42*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr); 43*97929ea7SJunchao Zhang for (i=low; i<high; i++) { 44*97929ea7SJunchao Zhang PetscScalar val = -i; 45*97929ea7SJunchao Zhang ierr = VecSetValue(x,i,val,INSERT_VALUES);CHKERRQ(ierr); 46*97929ea7SJunchao Zhang } 47*97929ea7SJunchao Zhang ierr = VecAssemblyBegin(x);CHKERRQ(ierr); 48*97929ea7SJunchao Zhang ierr = VecAssemblyEnd(x);CHKERRQ(ierr); 49*97929ea7SJunchao Zhang 50*97929ea7SJunchao Zhang /* Transfer x to a vector y only defined on subcomm0 and vice versa */ 51*97929ea7SJunchao Zhang if (mycolor == 0) { /* subcomm0 contains ranks 0, 3, 6, ... in PETSC_COMM_WORLD */ 52*97929ea7SJunchao Zhang Vec y; 53*97929ea7SJunchao Zhang PetscScalar *yvalue; 54*97929ea7SJunchao Zhang 55*97929ea7SJunchao Zhang ierr = VecCreateMPI(subcomm,PETSC_DECIDE,N,&y);CHKERRQ(ierr); 56*97929ea7SJunchao Zhang ierr = PetscObjectSetName((PetscObject)y,"y_subcomm_0");CHKERRQ(ierr); /* Give a name to view y clearly */ 57*97929ea7SJunchao Zhang ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr); 58*97929ea7SJunchao Zhang ierr = VecGetArray(y,&yvalue);CHKERRQ(ierr); 59*97929ea7SJunchao Zhang /* Create yg on PETSC_COMM_WORLD and alias yg with y. They share the memory pointed by yvalue. 60*97929ea7SJunchao Zhang Note this is a collective call. All processes have to call it and supply consistent N. 61*97929ea7SJunchao Zhang */ 62*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,1,n,N,yvalue,&yg);CHKERRQ(ierr); 63*97929ea7SJunchao Zhang 64*97929ea7SJunchao Zhang /* Create an identity map that makes yg[i] = x[i], i=0..N-1 */ 65*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(yg,&low,&high);CHKERRQ(ierr); /* low, high are global indices */ 66*97929ea7SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,high-low,low,1,&ix);CHKERRQ(ierr); 67*97929ea7SJunchao Zhang ierr = ISDuplicate(ix,&iy);CHKERRQ(ierr); 68*97929ea7SJunchao Zhang 69*97929ea7SJunchao Zhang /* Union of ix's on subcomm0 covers the full range of [0,N) */ 70*97929ea7SJunchao Zhang ierr = VecScatterCreate(x,ix,yg,iy,&vscat);CHKERRQ(ierr); 71*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,x,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 72*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,x,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 73*97929ea7SJunchao Zhang 74*97929ea7SJunchao Zhang /* Once yg got the data from x, we return yvalue to y so that we can use y in other operations. 75*97929ea7SJunchao Zhang VecGetArray must be paired with VecRestoreArray. 76*97929ea7SJunchao Zhang */ 77*97929ea7SJunchao Zhang ierr = VecRestoreArray(y,&yvalue);CHKERRQ(ierr); 78*97929ea7SJunchao Zhang 79*97929ea7SJunchao Zhang /* Libraries on subcomm0 can safely use y now, for example, view and scale it */ 80*97929ea7SJunchao Zhang ierr = VecView(y,PETSC_VIEWER_STDOUT_(subcomm));CHKERRQ(ierr); 81*97929ea7SJunchao Zhang ierr = VecScale(y,2.0);CHKERRQ(ierr); 82*97929ea7SJunchao Zhang 83*97929ea7SJunchao Zhang /* Send the new y back to x */ 84*97929ea7SJunchao Zhang ierr = VecGetArray(y,&yvalue);CHKERRQ(ierr); /* If VecScale is done on GPU, Petsc will prepare a valid yvalue for access */ 85*97929ea7SJunchao Zhang /* Supply new yvalue to yg without memory copying */ 86*97929ea7SJunchao Zhang ierr = VecPlaceArray(yg,yvalue);CHKERRQ(ierr); 87*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,yg,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 88*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,yg,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 89*97929ea7SJunchao Zhang ierr = VecResetArray(yg);CHKERRQ(ierr); 90*97929ea7SJunchao Zhang ierr = VecRestoreArray(y,&yvalue);CHKERRQ(ierr); 91*97929ea7SJunchao Zhang 92*97929ea7SJunchao Zhang ierr = VecDestroy(&y);CHKERRQ(ierr); 93*97929ea7SJunchao Zhang } else { 94*97929ea7SJunchao Zhang /* Ranks outside of subcomm0 do not supply values to yg */ 95*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,1,0/*n*/,N,NULL,&yg);CHKERRQ(ierr); 96*97929ea7SJunchao Zhang 97*97929ea7SJunchao Zhang /* Ranks in subcomm0 already specified the full range of the identity map. The remaining 98*97929ea7SJunchao Zhang ranks just need to create empty ISes to cheat VecScatterCreate. 99*97929ea7SJunchao Zhang */ 100*97929ea7SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&ix);CHKERRQ(ierr); 101*97929ea7SJunchao Zhang ierr = ISDuplicate(ix,&iy);CHKERRQ(ierr); 102*97929ea7SJunchao Zhang 103*97929ea7SJunchao Zhang ierr = VecScatterCreate(x,ix,yg,iy,&vscat);CHKERRQ(ierr); 104*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,x,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 105*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,x,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 106*97929ea7SJunchao Zhang 107*97929ea7SJunchao Zhang /* Send the new y back to x. Ranks outside of subcomm0 actually have nothing to send. 108*97929ea7SJunchao Zhang But they have to call VecScatterBegin/End since these routines are collective. 109*97929ea7SJunchao Zhang */ 110*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,yg,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 111*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,yg,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 112*97929ea7SJunchao Zhang } 113*97929ea7SJunchao Zhang 114*97929ea7SJunchao Zhang ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 115*97929ea7SJunchao Zhang ierr = ISDestroy(&ix);CHKERRQ(ierr); 116*97929ea7SJunchao Zhang ierr = ISDestroy(&iy);CHKERRQ(ierr); 117*97929ea7SJunchao Zhang ierr = VecDestroy(&x);CHKERRQ(ierr); 118*97929ea7SJunchao Zhang ierr = VecDestroy(&yg);CHKERRQ(ierr); 119*97929ea7SJunchao Zhang ierr = VecScatterDestroy(&vscat);CHKERRQ(ierr); 120*97929ea7SJunchao Zhang } /* world2sub */ 121*97929ea7SJunchao Zhang 122*97929ea7SJunchao Zhang /*=========================================================================== 123*97929ea7SJunchao Zhang * Transfer a vector x defined on subcomm0 to a vector y defined on 124*97929ea7SJunchao Zhang * subcomm1. The two subcomms are not overlapping and their union is 125*97929ea7SJunchao Zhang * not necessarily equal to PETSC_COMM_WORLD. 126*97929ea7SJunchao Zhang *===========================================================================*/ 127*97929ea7SJunchao Zhang if (sub2sub) { 128*97929ea7SJunchao Zhang if (mycolor == 0) { 129*97929ea7SJunchao Zhang /* Intentionally declare N as a local variable so that processes in subcomm1 do not know its value */ 130*97929ea7SJunchao Zhang PetscInt n,N = 22; 131*97929ea7SJunchao Zhang Vec x,xg,yg; 132*97929ea7SJunchao Zhang IS ix,iy; 133*97929ea7SJunchao Zhang VecScatter vscat; 134*97929ea7SJunchao Zhang const PetscScalar *xvalue; 135*97929ea7SJunchao Zhang MPI_Comm intercomm,parentcomm; 136*97929ea7SJunchao Zhang PetscMPIInt lrank; 137*97929ea7SJunchao Zhang 138*97929ea7SJunchao Zhang ierr = MPI_Comm_rank(subcomm,&lrank);CHKERRQ(ierr); 139*97929ea7SJunchao Zhang ierr = VecCreateMPI(subcomm,PETSC_DECIDE,N,&x);CHKERRQ(ierr); /* x is on subcomm */ 140*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr); 141*97929ea7SJunchao Zhang 142*97929ea7SJunchao Zhang /* initialize x = [0.0, 1.0, 2.0, ..., 21.0] */ 143*97929ea7SJunchao Zhang for (i=low; i<high; i++) { 144*97929ea7SJunchao Zhang PetscScalar val = i; 145*97929ea7SJunchao Zhang ierr = VecSetValue(x,i,val,INSERT_VALUES);CHKERRQ(ierr); 146*97929ea7SJunchao Zhang } 147*97929ea7SJunchao Zhang ierr = VecAssemblyBegin(x);CHKERRQ(ierr); 148*97929ea7SJunchao Zhang ierr = VecAssemblyEnd(x);CHKERRQ(ierr); 149*97929ea7SJunchao Zhang 150*97929ea7SJunchao Zhang ierr = MPI_Intercomm_create(subcomm,0,PETSC_COMM_WORLD/*peer_comm*/,1,100/*tag*/,&intercomm);CHKERRQ(ierr); 151*97929ea7SJunchao Zhang 152*97929ea7SJunchao Zhang /* Tell rank 0 of subcomm1 the global size of x */ 153*97929ea7SJunchao Zhang if (!lrank) {ierr = MPI_Send(&N,1,MPIU_INT,0/*receiver's rank in remote comm, i.e., subcomm1*/,200/*tag*/,intercomm);CHKERRQ(ierr);} 154*97929ea7SJunchao Zhang 155*97929ea7SJunchao Zhang /* Create an intracomm Petsc can work on. Ranks in subcomm0 are ordered before ranks in subcomm1 in parentcomm. 156*97929ea7SJunchao Zhang But this order actually does not matter, since what we care is vector y, which is defined on subcomm1. 157*97929ea7SJunchao Zhang */ 158*97929ea7SJunchao Zhang ierr = MPI_Intercomm_merge(intercomm,0/*low*/,&parentcomm);CHKERRQ(ierr); 159*97929ea7SJunchao Zhang 160*97929ea7SJunchao Zhang /* Create a vector xg on parentcomm, which shares memory with x */ 161*97929ea7SJunchao Zhang ierr = VecGetArrayRead(x,&xvalue);CHKERRQ(ierr); 162*97929ea7SJunchao Zhang ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr); 163*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(parentcomm,1,n,N,xvalue,&xg);CHKERRQ(ierr); 164*97929ea7SJunchao Zhang 165*97929ea7SJunchao Zhang /* Ranks in subcomm 0 have nothing on yg, so they simply have n=0, array=NULL */ 166*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(parentcomm,1,0/*n*/,N,NULL/*array*/,&yg);CHKERRQ(ierr); 167*97929ea7SJunchao Zhang 168*97929ea7SJunchao Zhang /* Create the vecscatter, which does identity map by setting yg[i] = xg[i], i=0..N-1. */ 169*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(xg,&low,&high);CHKERRQ(ierr); /* low, high are global indices of xg */ 170*97929ea7SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,high-low,low,1,&ix);CHKERRQ(ierr); 171*97929ea7SJunchao Zhang ierr = ISDuplicate(ix,&iy);CHKERRQ(ierr); 172*97929ea7SJunchao Zhang ierr = VecScatterCreate(xg,ix,yg,iy,&vscat);CHKERRQ(ierr); 173*97929ea7SJunchao Zhang 174*97929ea7SJunchao Zhang /* Scatter values from xg to yg */ 175*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,xg,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 176*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,xg,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 177*97929ea7SJunchao Zhang 178*97929ea7SJunchao Zhang /* After the VecScatter is done, xg is idle so we can safely return xvalue to x */ 179*97929ea7SJunchao Zhang ierr = VecRestoreArrayRead(x,&xvalue);CHKERRQ(ierr); 180*97929ea7SJunchao Zhang ierr = VecDestroy(&x);CHKERRQ(ierr); 181*97929ea7SJunchao Zhang ierr = ISDestroy(&ix);CHKERRQ(ierr); 182*97929ea7SJunchao Zhang ierr = ISDestroy(&iy);CHKERRQ(ierr); 183*97929ea7SJunchao Zhang ierr = VecDestroy(&xg);CHKERRQ(ierr); 184*97929ea7SJunchao Zhang ierr = VecDestroy(&yg);CHKERRQ(ierr); 185*97929ea7SJunchao Zhang ierr = VecScatterDestroy(&vscat);CHKERRQ(ierr); 186*97929ea7SJunchao Zhang ierr = MPI_Comm_free(&intercomm);CHKERRQ(ierr); 187*97929ea7SJunchao Zhang ierr = MPI_Comm_free(&parentcomm);CHKERRQ(ierr); 188*97929ea7SJunchao Zhang } else if (mycolor == 1) { /* subcomm 1, containing ranks 1, 4, 7, ... in PETSC_COMM_WORLD */ 189*97929ea7SJunchao Zhang PetscInt n,N; 190*97929ea7SJunchao Zhang Vec y,xg,yg; 191*97929ea7SJunchao Zhang IS ix,iy; 192*97929ea7SJunchao Zhang VecScatter vscat; 193*97929ea7SJunchao Zhang PetscScalar *yvalue; 194*97929ea7SJunchao Zhang MPI_Comm intercomm,parentcomm; 195*97929ea7SJunchao Zhang PetscMPIInt lrank; 196*97929ea7SJunchao Zhang 197*97929ea7SJunchao Zhang ierr = MPI_Comm_rank(subcomm,&lrank);CHKERRQ(ierr); 198*97929ea7SJunchao Zhang ierr = MPI_Intercomm_create(subcomm,0,PETSC_COMM_WORLD/*peer_comm*/,0/*remote_leader*/,100/*tag*/,&intercomm);CHKERRQ(ierr); 199*97929ea7SJunchao Zhang 200*97929ea7SJunchao Zhang /* Two rank-0 are talking */ 201*97929ea7SJunchao Zhang if (!lrank) {ierr = MPI_Recv(&N,1,MPIU_INT,0/*sender's rank in remote comm, i.e. subcomm0*/,200/*tag*/,intercomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);} 202*97929ea7SJunchao Zhang /* Rank 0 of subcomm1 bcasts N to its members */ 203*97929ea7SJunchao Zhang ierr = MPI_Bcast(&N,1,MPIU_INT,0/*local root*/,subcomm);CHKERRQ(ierr); 204*97929ea7SJunchao Zhang 205*97929ea7SJunchao Zhang /* Create a intracomm Petsc can work on */ 206*97929ea7SJunchao Zhang ierr = MPI_Intercomm_merge(intercomm,1/*high*/,&parentcomm);CHKERRQ(ierr); 207*97929ea7SJunchao Zhang 208*97929ea7SJunchao Zhang /* Ranks in subcomm1 have nothing on xg, so they simply have n=0, array=NULL.*/ 209*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(parentcomm,1/*bs*/,0/*n*/,N,NULL/*array*/,&xg);CHKERRQ(ierr); 210*97929ea7SJunchao Zhang 211*97929ea7SJunchao Zhang ierr = VecCreateMPI(subcomm,PETSC_DECIDE,N,&y);CHKERRQ(ierr); 212*97929ea7SJunchao Zhang ierr = PetscObjectSetName((PetscObject)y,"y_subcomm_1");CHKERRQ(ierr); /* Give a name to view y clearly */ 213*97929ea7SJunchao Zhang ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr); 214*97929ea7SJunchao Zhang ierr = VecGetArray(y,&yvalue);CHKERRQ(ierr); 215*97929ea7SJunchao Zhang /* Create a vector yg on parentcomm, which shares memory with y. xg and yg must be 216*97929ea7SJunchao Zhang created in the same order in subcomm0/1. For example, we can not reverse the order of 217*97929ea7SJunchao Zhang creating xg and yg in subcomm1. 218*97929ea7SJunchao Zhang */ 219*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(parentcomm,1/*bs*/,n,N,yvalue,&yg);CHKERRQ(ierr); 220*97929ea7SJunchao Zhang 221*97929ea7SJunchao Zhang /* Ranks in subcomm0 already specified the full range of the identity map. 222*97929ea7SJunchao Zhang ranks in subcomm1 just need to create empty ISes to cheat VecScatterCreate. 223*97929ea7SJunchao Zhang */ 224*97929ea7SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&ix);CHKERRQ(ierr); 225*97929ea7SJunchao Zhang ierr = ISDuplicate(ix,&iy);CHKERRQ(ierr); 226*97929ea7SJunchao Zhang ierr = VecScatterCreate(xg,ix,yg,iy,&vscat);CHKERRQ(ierr); 227*97929ea7SJunchao Zhang 228*97929ea7SJunchao Zhang /* Scatter values from xg to yg */ 229*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,xg,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 230*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,xg,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 231*97929ea7SJunchao Zhang 232*97929ea7SJunchao Zhang /* After the VecScatter is done, values in yg are available. y is our interest, so we return yvalue to y */ 233*97929ea7SJunchao Zhang ierr = VecRestoreArray(y,&yvalue);CHKERRQ(ierr); 234*97929ea7SJunchao Zhang 235*97929ea7SJunchao Zhang /* Libraries on subcomm1 can safely use y now, for example, view it */ 236*97929ea7SJunchao Zhang ierr = VecView(y,PETSC_VIEWER_STDOUT_(subcomm));CHKERRQ(ierr); 237*97929ea7SJunchao Zhang 238*97929ea7SJunchao Zhang ierr = VecDestroy(&y);CHKERRQ(ierr); 239*97929ea7SJunchao Zhang ierr = ISDestroy(&ix);CHKERRQ(ierr); 240*97929ea7SJunchao Zhang ierr = ISDestroy(&iy);CHKERRQ(ierr); 241*97929ea7SJunchao Zhang ierr = VecDestroy(&xg);CHKERRQ(ierr); 242*97929ea7SJunchao Zhang ierr = VecDestroy(&yg);CHKERRQ(ierr); 243*97929ea7SJunchao Zhang ierr = VecScatterDestroy(&vscat);CHKERRQ(ierr); 244*97929ea7SJunchao Zhang ierr = MPI_Comm_free(&intercomm);CHKERRQ(ierr); 245*97929ea7SJunchao Zhang ierr = MPI_Comm_free(&parentcomm);CHKERRQ(ierr); 246*97929ea7SJunchao Zhang } else if (mycolor == 2) { /* subcomm2 */ 247*97929ea7SJunchao Zhang /* Processes in subcomm2 do not participate in the VecScatter. They can freely do unrelated things on subcomm2 */ 248*97929ea7SJunchao Zhang } 249*97929ea7SJunchao Zhang } /* sub2sub */ 250*97929ea7SJunchao Zhang 251*97929ea7SJunchao Zhang /*=========================================================================== 252*97929ea7SJunchao Zhang * Copy a vector x defined on PETSC_COMM_WORLD to vectors y defined on 253*97929ea7SJunchao Zhang * every subcommunicator of PETSC_COMM_WORLD. We could use multiple transfers 254*97929ea7SJunchao Zhang * as we did in case 1, but that is not efficient. Instead, we use one vecscatter 255*97929ea7SJunchao Zhang * to achieve that. 256*97929ea7SJunchao Zhang *===========================================================================*/ 257*97929ea7SJunchao Zhang if (world2subs) { 258*97929ea7SJunchao Zhang Vec y,yg; 259*97929ea7SJunchao Zhang PetscInt n,N=15,xstart,ystart,low,high; 260*97929ea7SJunchao Zhang PetscScalar *yvalue; 261*97929ea7SJunchao Zhang 262*97929ea7SJunchao Zhang /* Initialize x to [0, 1, 2, 3, ..., N-1] */ 263*97929ea7SJunchao Zhang ierr = VecCreateMPI(PETSC_COMM_WORLD,PETSC_DECIDE,N,&x);CHKERRQ(ierr); 264*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr); 265*97929ea7SJunchao Zhang for (i=low; i<high; i++) {ierr = VecSetValue(x,i,(PetscScalar)i,INSERT_VALUES);CHKERRQ(ierr);} 266*97929ea7SJunchao Zhang ierr = VecAssemblyBegin(x);CHKERRQ(ierr); 267*97929ea7SJunchao Zhang ierr = VecAssemblyEnd(x);CHKERRQ(ierr); 268*97929ea7SJunchao Zhang 269*97929ea7SJunchao Zhang /* Every subcomm has a y as long as x */ 270*97929ea7SJunchao Zhang ierr = VecCreateMPI(subcomm,PETSC_DECIDE,N,&y);CHKERRQ(ierr); 271*97929ea7SJunchao Zhang ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr); 272*97929ea7SJunchao Zhang 273*97929ea7SJunchao Zhang /* Create a global vector yg on PETSC_COMM_WORLD using y's memory. yg's global size = N*(number of subcommunicators). 274*97929ea7SJunchao Zhang Eeach rank in subcomms contributes a piece to construct the global yg. Keep in mind that pieces from a subcomm are not 275*97929ea7SJunchao Zhang necessarily consecutive in yg. That depends on how PETSC_COMM_WORLD is split. In our case, subcomm0 is made of rank 276*97929ea7SJunchao Zhang 0, 3, 6 etc from PETSC_COMM_WORLD. So subcomm0's pieces are interleaved with pieces from other subcomms in yg. 277*97929ea7SJunchao Zhang */ 278*97929ea7SJunchao Zhang ierr = VecGetArray(y,&yvalue);CHKERRQ(ierr); 279*97929ea7SJunchao Zhang ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,1,n,PETSC_DECIDE,yvalue,&yg);CHKERRQ(ierr); 280*97929ea7SJunchao Zhang ierr = PetscObjectSetName((PetscObject)yg,"yg_on_subcomms");CHKERRQ(ierr); /* Give a name to view yg clearly */ 281*97929ea7SJunchao Zhang 282*97929ea7SJunchao Zhang /* The following two lines are key. From xstart, we know where to pull entries from x. Note that we get xstart from y, 283*97929ea7SJunchao Zhang since first entry of y on this rank is from x[xstart]. From ystart, we know where ot put entries to yg. 284*97929ea7SJunchao Zhang */ 285*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(y,&xstart,NULL);CHKERRQ(ierr); 286*97929ea7SJunchao Zhang ierr = VecGetOwnershipRange(yg,&ystart,NULL);CHKERRQ(ierr); 287*97929ea7SJunchao Zhang 288*97929ea7SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,n,xstart,1,&ix);CHKERRQ(ierr); 289*97929ea7SJunchao Zhang ierr = ISCreateStride(PETSC_COMM_SELF,n,ystart,1,&iy);CHKERRQ(ierr); 290*97929ea7SJunchao Zhang ierr = VecScatterCreate(x,ix,yg,iy,&vscat);CHKERRQ(ierr); 291*97929ea7SJunchao Zhang ierr = VecScatterBegin(vscat,x,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 292*97929ea7SJunchao Zhang ierr = VecScatterEnd(vscat,x,yg,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 293*97929ea7SJunchao Zhang 294*97929ea7SJunchao Zhang /* View yg on PETSC_COMM_WORLD before destroying it. We shall see the interleaving effect in output. */ 295*97929ea7SJunchao Zhang ierr = VecView(yg,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 296*97929ea7SJunchao Zhang ierr = VecDestroy(&yg);CHKERRQ(ierr); 297*97929ea7SJunchao Zhang 298*97929ea7SJunchao Zhang /* Restory yvalue so that processes in subcomm can use y from now on. */ 299*97929ea7SJunchao Zhang ierr = VecRestoreArray(y,&yvalue);CHKERRQ(ierr); 300*97929ea7SJunchao Zhang ierr = VecScale(y,3.0);CHKERRQ(ierr); 301*97929ea7SJunchao Zhang 302*97929ea7SJunchao Zhang ierr = ISDestroy(&ix);CHKERRQ(ierr); /* One can also destroy ix, iy immediately after VecScatterCreate() */ 303*97929ea7SJunchao Zhang ierr = ISDestroy(&iy);CHKERRQ(ierr); 304*97929ea7SJunchao Zhang ierr = VecDestroy(&x);CHKERRQ(ierr); 305*97929ea7SJunchao Zhang ierr = VecDestroy(&y);CHKERRQ(ierr); 306*97929ea7SJunchao Zhang ierr = VecScatterDestroy(&vscat);CHKERRQ(ierr); 307*97929ea7SJunchao Zhang } /* world2subs */ 308*97929ea7SJunchao Zhang 309*97929ea7SJunchao Zhang ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr); 310*97929ea7SJunchao Zhang ierr = PetscFinalize(); 311*97929ea7SJunchao Zhang return ierr; 312*97929ea7SJunchao Zhang } 313*97929ea7SJunchao Zhang 314*97929ea7SJunchao Zhang /*TEST 315*97929ea7SJunchao Zhang 316*97929ea7SJunchao Zhang build: 317*97929ea7SJunchao Zhang requires: !define(PETSC_HAVE_MPIUNI) 318*97929ea7SJunchao Zhang testset: 319*97929ea7SJunchao Zhang nsize: 7 320*97929ea7SJunchao Zhang 321*97929ea7SJunchao Zhang test: 322*97929ea7SJunchao Zhang suffix: 1 323*97929ea7SJunchao Zhang args: -world2sub 324*97929ea7SJunchao Zhang 325*97929ea7SJunchao Zhang test: 326*97929ea7SJunchao Zhang suffix: 2 327*97929ea7SJunchao Zhang args: -sub2sub 328*97929ea7SJunchao Zhang 329*97929ea7SJunchao Zhang test: 330*97929ea7SJunchao Zhang suffix: 3 331*97929ea7SJunchao Zhang args: -world2subs 332*97929ea7SJunchao Zhang 333*97929ea7SJunchao Zhang test: 334*97929ea7SJunchao Zhang suffix: 4 335*97929ea7SJunchao Zhang args: -world2sub -sf_type neighbor 336*97929ea7SJunchao Zhang output_file: output/ex9_1.out 337*97929ea7SJunchao Zhang # OpenMPI has a bug wrt MPI_Neighbor_alltoallv etc (https://github.com/open-mpi/ompi/pull/6782). Once the patch is in, we can remove !define(PETSC_HAVE_OMPI_MAJOR_VERSION) 338*97929ea7SJunchao Zhang requires: define(PETSC_HAVE_MPI_NEIGHBORHOOD_COLLECTIVES) !define(PETSC_HAVE_OMPI_MAJOR_VERSION) 339*97929ea7SJunchao Zhang TEST*/ 340*97929ea7SJunchao Zhang 341