1*47c6ae99SBarry Smith #define PETSCDM_DLL 2*47c6ae99SBarry Smith 3*47c6ae99SBarry Smith /* 4*47c6ae99SBarry Smith Code for manipulating distributed regular arrays in parallel. 5*47c6ae99SBarry Smith */ 6*47c6ae99SBarry Smith 7*47c6ae99SBarry Smith #include "private/daimpl.h" /*I "petscda.h" I*/ 8*47c6ae99SBarry Smith 9*47c6ae99SBarry Smith #undef __FUNCT__ 10*47c6ae99SBarry Smith #define __FUNCT__ "DAGetProcessorSubset" 11*47c6ae99SBarry Smith /*@C 12*47c6ae99SBarry Smith DAGetProcessorSubset - Returns a communicator consisting only of the 13*47c6ae99SBarry Smith processors in a DA that own a particular global x, y, or z grid point 14*47c6ae99SBarry Smith (corresponding to a logical plane in a 3D grid or a line in a 2D grid). 15*47c6ae99SBarry Smith 16*47c6ae99SBarry Smith Collective on DA 17*47c6ae99SBarry Smith 18*47c6ae99SBarry Smith Input Parameters: 19*47c6ae99SBarry Smith + da - the distributed array 20*47c6ae99SBarry Smith . dir - Cartesian direction, either DA_X, DA_Y, or DA_Z 21*47c6ae99SBarry Smith - gp - global grid point number in this direction 22*47c6ae99SBarry Smith 23*47c6ae99SBarry Smith Output Parameters: 24*47c6ae99SBarry Smith . comm - new communicator 25*47c6ae99SBarry Smith 26*47c6ae99SBarry Smith Level: advanced 27*47c6ae99SBarry Smith 28*47c6ae99SBarry Smith Notes: 29*47c6ae99SBarry Smith All processors that share the DA must call this with the same gp value 30*47c6ae99SBarry Smith 31*47c6ae99SBarry Smith This routine is particularly useful to compute boundary conditions 32*47c6ae99SBarry Smith or other application-specific calculations that require manipulating 33*47c6ae99SBarry Smith sets of data throughout a logical plane of grid points. 34*47c6ae99SBarry Smith 35*47c6ae99SBarry Smith .keywords: distributed array, get, processor subset 36*47c6ae99SBarry Smith @*/ 37*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAGetProcessorSubset(DA da,DADirection dir,PetscInt gp,MPI_Comm *comm) 38*47c6ae99SBarry Smith { 39*47c6ae99SBarry Smith MPI_Group group,subgroup; 40*47c6ae99SBarry Smith PetscErrorCode ierr; 41*47c6ae99SBarry Smith PetscInt i,ict,flag,*owners,xs,xm,ys,ym,zs,zm; 42*47c6ae99SBarry Smith PetscMPIInt size,*ranks = PETSC_NULL; 43*47c6ae99SBarry Smith DM_DA *dd = (DM_DA*)da->data; 44*47c6ae99SBarry Smith 45*47c6ae99SBarry Smith PetscFunctionBegin; 46*47c6ae99SBarry Smith PetscValidHeaderSpecific(da,DM_CLASSID,1); 47*47c6ae99SBarry Smith flag = 0; 48*47c6ae99SBarry Smith ierr = DAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); 49*47c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)da)->comm,&size);CHKERRQ(ierr); 50*47c6ae99SBarry Smith if (dir == DA_Z) { 51*47c6ae99SBarry Smith if (dd->dim < 3) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"DA_Z invalid for DA dim < 3"); 52*47c6ae99SBarry Smith if (gp < 0 || gp > dd->P) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid grid point"); 53*47c6ae99SBarry Smith if (gp >= zs && gp < zs+zm) flag = 1; 54*47c6ae99SBarry Smith } else if (dir == DA_Y) { 55*47c6ae99SBarry Smith if (dd->dim == 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"DA_Y invalid for DA dim = 1"); 56*47c6ae99SBarry Smith if (gp < 0 || gp > dd->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid grid point"); 57*47c6ae99SBarry Smith if (gp >= ys && gp < ys+ym) flag = 1; 58*47c6ae99SBarry Smith } else if (dir == DA_X) { 59*47c6ae99SBarry Smith if (gp < 0 || gp > dd->M) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid grid point"); 60*47c6ae99SBarry Smith if (gp >= xs && gp < xs+xm) flag = 1; 61*47c6ae99SBarry Smith } else SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid direction"); 62*47c6ae99SBarry Smith 63*47c6ae99SBarry Smith ierr = PetscMalloc2(size,PetscInt,&owners,size,PetscMPIInt,&ranks);CHKERRQ(ierr); 64*47c6ae99SBarry Smith ierr = MPI_Allgather(&flag,1,MPIU_INT,owners,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr); 65*47c6ae99SBarry Smith ict = 0; 66*47c6ae99SBarry Smith ierr = PetscInfo2(da,"DAGetProcessorSubset: dim=%D, direction=%d, procs: ",dd->dim,(int)dir);CHKERRQ(ierr); 67*47c6ae99SBarry Smith for (i=0; i<size; i++) { 68*47c6ae99SBarry Smith if (owners[i]) { 69*47c6ae99SBarry Smith ranks[ict] = i; ict++; 70*47c6ae99SBarry Smith ierr = PetscInfo1(da,"%D ",i);CHKERRQ(ierr); 71*47c6ae99SBarry Smith } 72*47c6ae99SBarry Smith } 73*47c6ae99SBarry Smith ierr = PetscInfo(da,"\n");CHKERRQ(ierr); 74*47c6ae99SBarry Smith ierr = MPI_Comm_group(((PetscObject)da)->comm,&group);CHKERRQ(ierr); 75*47c6ae99SBarry Smith ierr = MPI_Group_incl(group,ict,ranks,&subgroup);CHKERRQ(ierr); 76*47c6ae99SBarry Smith ierr = MPI_Comm_create(((PetscObject)da)->comm,subgroup,comm);CHKERRQ(ierr); 77*47c6ae99SBarry Smith ierr = MPI_Group_free(&subgroup);CHKERRQ(ierr); 78*47c6ae99SBarry Smith ierr = MPI_Group_free(&group);CHKERRQ(ierr); 79*47c6ae99SBarry Smith ierr = PetscFree2(owners,ranks);CHKERRQ(ierr); 80*47c6ae99SBarry Smith PetscFunctionReturn(0); 81*47c6ae99SBarry Smith } 82*47c6ae99SBarry Smith 83*47c6ae99SBarry Smith #undef __FUNCT__ 84*47c6ae99SBarry Smith #define __FUNCT__ "DAGetProcessorSubsets" 85*47c6ae99SBarry Smith /*@C 86*47c6ae99SBarry Smith DAGetProcessorSubsets - Returns communicators consisting only of the 87*47c6ae99SBarry Smith processors in a DA adjacent in a particular dimension, 88*47c6ae99SBarry Smith corresponding to a logical plane in a 3D grid or a line in a 2D grid. 89*47c6ae99SBarry Smith 90*47c6ae99SBarry Smith Collective on DA 91*47c6ae99SBarry Smith 92*47c6ae99SBarry Smith Input Parameters: 93*47c6ae99SBarry Smith + da - the distributed array 94*47c6ae99SBarry Smith - dir - Cartesian direction, either DA_X, DA_Y, or DA_Z 95*47c6ae99SBarry Smith 96*47c6ae99SBarry Smith Output Parameters: 97*47c6ae99SBarry Smith . subcomm - new communicator 98*47c6ae99SBarry Smith 99*47c6ae99SBarry Smith Level: advanced 100*47c6ae99SBarry Smith 101*47c6ae99SBarry Smith Notes: 102*47c6ae99SBarry Smith This routine is useful for distributing one-dimensional data in a tensor product grid. 103*47c6ae99SBarry Smith 104*47c6ae99SBarry Smith .keywords: distributed array, get, processor subset 105*47c6ae99SBarry Smith @*/ 106*47c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAGetProcessorSubsets(DA da, DADirection dir, MPI_Comm *subcomm) 107*47c6ae99SBarry Smith { 108*47c6ae99SBarry Smith MPI_Comm comm; 109*47c6ae99SBarry Smith MPI_Group group, subgroup; 110*47c6ae99SBarry Smith PetscInt subgroupSize = 0; 111*47c6ae99SBarry Smith PetscInt *firstPoints; 112*47c6ae99SBarry Smith PetscMPIInt size, *subgroupRanks = PETSC_NULL; 113*47c6ae99SBarry Smith PetscInt xs, xm, ys, ym, zs, zm, firstPoint, p; 114*47c6ae99SBarry Smith PetscErrorCode ierr; 115*47c6ae99SBarry Smith DM_DA *dd = (DM_DA*)da->data; 116*47c6ae99SBarry Smith 117*47c6ae99SBarry Smith PetscFunctionBegin; 118*47c6ae99SBarry Smith PetscValidHeaderSpecific(da, DM_CLASSID, 1); 119*47c6ae99SBarry Smith comm = ((PetscObject) da)->comm; 120*47c6ae99SBarry Smith ierr = DAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm);CHKERRQ(ierr); 121*47c6ae99SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 122*47c6ae99SBarry Smith if (dir == DA_Z) { 123*47c6ae99SBarry Smith if (dd->dim < 3) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"DA_Z invalid for DA dim < 3"); 124*47c6ae99SBarry Smith firstPoint = zs; 125*47c6ae99SBarry Smith } else if (dir == DA_Y) { 126*47c6ae99SBarry Smith if (dd->dim == 1) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"DA_Y invalid for DA dim = 1"); 127*47c6ae99SBarry Smith firstPoint = ys; 128*47c6ae99SBarry Smith } else if (dir == DA_X) { 129*47c6ae99SBarry Smith firstPoint = xs; 130*47c6ae99SBarry Smith } else SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid direction"); 131*47c6ae99SBarry Smith 132*47c6ae99SBarry Smith ierr = PetscMalloc2(size, PetscInt, &firstPoints, size, PetscMPIInt, &subgroupRanks);CHKERRQ(ierr); 133*47c6ae99SBarry Smith ierr = MPI_Allgather(&firstPoint, 1, MPIU_INT, firstPoints, 1, MPIU_INT, comm);CHKERRQ(ierr); 134*47c6ae99SBarry Smith ierr = PetscInfo2(da,"DAGetProcessorSubset: dim=%D, direction=%d, procs: ",dd->dim,(int)dir);CHKERRQ(ierr); 135*47c6ae99SBarry Smith for(p = 0; p < size; ++p) { 136*47c6ae99SBarry Smith if (firstPoints[p] == firstPoint) { 137*47c6ae99SBarry Smith subgroupRanks[subgroupSize++] = p; 138*47c6ae99SBarry Smith ierr = PetscInfo1(da, "%D ", p);CHKERRQ(ierr); 139*47c6ae99SBarry Smith } 140*47c6ae99SBarry Smith } 141*47c6ae99SBarry Smith ierr = PetscInfo(da, "\n");CHKERRQ(ierr); 142*47c6ae99SBarry Smith ierr = MPI_Comm_group(comm, &group);CHKERRQ(ierr); 143*47c6ae99SBarry Smith ierr = MPI_Group_incl(group, subgroupSize, subgroupRanks, &subgroup);CHKERRQ(ierr); 144*47c6ae99SBarry Smith ierr = MPI_Comm_create(comm, subgroup, subcomm);CHKERRQ(ierr); 145*47c6ae99SBarry Smith ierr = MPI_Group_free(&subgroup);CHKERRQ(ierr); 146*47c6ae99SBarry Smith ierr = MPI_Group_free(&group);CHKERRQ(ierr); 147*47c6ae99SBarry Smith ierr = PetscFree2(firstPoints, subgroupRanks);CHKERRQ(ierr); 148*47c6ae99SBarry Smith PetscFunctionReturn(0); 149*47c6ae99SBarry Smith } 150