xref: /petsc/src/dm/impls/da/dasub.c (revision 7087cfbefd1a42b179f217f9994fb6cb0d0c1824)
147c6ae99SBarry Smith #define PETSCDM_DLL
247c6ae99SBarry Smith 
347c6ae99SBarry Smith /*
447c6ae99SBarry Smith   Code for manipulating distributed regular arrays in parallel.
547c6ae99SBarry Smith */
647c6ae99SBarry Smith 
7e1589f56SBarry Smith #include "private/daimpl.h"    /*I   "petscdm.h"   I*/
847c6ae99SBarry Smith 
947c6ae99SBarry Smith #undef __FUNCT__
10aa219208SBarry Smith #define __FUNCT__ "DMDAGetProcessorSubset"
1147c6ae99SBarry Smith /*@C
12aa219208SBarry Smith    DMDAGetProcessorSubset - Returns a communicator consisting only of the
13aa219208SBarry Smith    processors in a DMDA that own a particular global x, y, or z grid point
1447c6ae99SBarry Smith    (corresponding to a logical plane in a 3D grid or a line in a 2D grid).
1547c6ae99SBarry Smith 
16aa219208SBarry Smith    Collective on DMDA
1747c6ae99SBarry Smith 
1847c6ae99SBarry Smith    Input Parameters:
1947c6ae99SBarry Smith +  da - the distributed array
20aa219208SBarry Smith .  dir - Cartesian direction, either DMDA_X, DMDA_Y, or DMDA_Z
2147c6ae99SBarry Smith -  gp - global grid point number in this direction
2247c6ae99SBarry Smith 
2347c6ae99SBarry Smith    Output Parameters:
2447c6ae99SBarry Smith .  comm - new communicator
2547c6ae99SBarry Smith 
2647c6ae99SBarry Smith    Level: advanced
2747c6ae99SBarry Smith 
2847c6ae99SBarry Smith    Notes:
29aa219208SBarry Smith    All processors that share the DMDA must call this with the same gp value
3047c6ae99SBarry Smith 
3147c6ae99SBarry Smith    This routine is particularly useful to compute boundary conditions
3247c6ae99SBarry Smith    or other application-specific calculations that require manipulating
3347c6ae99SBarry Smith    sets of data throughout a logical plane of grid points.
3447c6ae99SBarry Smith 
3547c6ae99SBarry Smith .keywords: distributed array, get, processor subset
3647c6ae99SBarry Smith @*/
37*7087cfbeSBarry Smith PetscErrorCode  DMDAGetProcessorSubset(DM da,DMDADirection dir,PetscInt gp,MPI_Comm *comm)
3847c6ae99SBarry Smith {
3947c6ae99SBarry Smith   MPI_Group      group,subgroup;
4047c6ae99SBarry Smith   PetscErrorCode ierr;
4147c6ae99SBarry Smith   PetscInt       i,ict,flag,*owners,xs,xm,ys,ym,zs,zm;
4247c6ae99SBarry Smith   PetscMPIInt    size,*ranks = PETSC_NULL;
4347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
4447c6ae99SBarry Smith 
4547c6ae99SBarry Smith   PetscFunctionBegin;
4647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
4747c6ae99SBarry Smith   flag = 0;
48aa219208SBarry Smith   ierr = DMDAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr);
4947c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)da)->comm,&size);CHKERRQ(ierr);
50aa219208SBarry Smith   if (dir == DMDA_Z) {
51aa219208SBarry Smith     if (dd->dim < 3) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"DMDA_Z invalid for DMDA dim < 3");
5247c6ae99SBarry Smith     if (gp < 0 || gp > dd->P) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid grid point");
5347c6ae99SBarry Smith     if (gp >= zs && gp < zs+zm) flag = 1;
54aa219208SBarry Smith   } else if (dir == DMDA_Y) {
55aa219208SBarry Smith     if (dd->dim == 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"DMDA_Y invalid for DMDA dim = 1");
5647c6ae99SBarry Smith     if (gp < 0 || gp > dd->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid grid point");
5747c6ae99SBarry Smith     if (gp >= ys && gp < ys+ym) flag = 1;
58aa219208SBarry Smith   } else if (dir == DMDA_X) {
5947c6ae99SBarry Smith     if (gp < 0 || gp > dd->M) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid grid point");
6047c6ae99SBarry Smith     if (gp >= xs && gp < xs+xm) flag = 1;
6147c6ae99SBarry Smith   } else SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid direction");
6247c6ae99SBarry Smith 
6347c6ae99SBarry Smith   ierr = PetscMalloc2(size,PetscInt,&owners,size,PetscMPIInt,&ranks);CHKERRQ(ierr);
6447c6ae99SBarry Smith   ierr = MPI_Allgather(&flag,1,MPIU_INT,owners,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
6547c6ae99SBarry Smith   ict  = 0;
66aa219208SBarry Smith   ierr = PetscInfo2(da,"DMDAGetProcessorSubset: dim=%D, direction=%d, procs: ",dd->dim,(int)dir);CHKERRQ(ierr);
6747c6ae99SBarry Smith   for (i=0; i<size; i++) {
6847c6ae99SBarry Smith     if (owners[i]) {
6947c6ae99SBarry Smith       ranks[ict] = i; ict++;
7047c6ae99SBarry Smith       ierr = PetscInfo1(da,"%D ",i);CHKERRQ(ierr);
7147c6ae99SBarry Smith     }
7247c6ae99SBarry Smith   }
7347c6ae99SBarry Smith   ierr = PetscInfo(da,"\n");CHKERRQ(ierr);
7447c6ae99SBarry Smith   ierr = MPI_Comm_group(((PetscObject)da)->comm,&group);CHKERRQ(ierr);
7547c6ae99SBarry Smith   ierr = MPI_Group_incl(group,ict,ranks,&subgroup);CHKERRQ(ierr);
7647c6ae99SBarry Smith   ierr = MPI_Comm_create(((PetscObject)da)->comm,subgroup,comm);CHKERRQ(ierr);
7747c6ae99SBarry Smith   ierr = MPI_Group_free(&subgroup);CHKERRQ(ierr);
7847c6ae99SBarry Smith   ierr = MPI_Group_free(&group);CHKERRQ(ierr);
7947c6ae99SBarry Smith   ierr = PetscFree2(owners,ranks);CHKERRQ(ierr);
8047c6ae99SBarry Smith   PetscFunctionReturn(0);
8147c6ae99SBarry Smith }
8247c6ae99SBarry Smith 
8347c6ae99SBarry Smith #undef __FUNCT__
84aa219208SBarry Smith #define __FUNCT__ "DMDAGetProcessorSubsets"
8547c6ae99SBarry Smith /*@C
86aa219208SBarry Smith    DMDAGetProcessorSubsets - Returns communicators consisting only of the
87aa219208SBarry Smith    processors in a DMDA adjacent in a particular dimension,
8847c6ae99SBarry Smith    corresponding to a logical plane in a 3D grid or a line in a 2D grid.
8947c6ae99SBarry Smith 
90aa219208SBarry Smith    Collective on DMDA
9147c6ae99SBarry Smith 
9247c6ae99SBarry Smith    Input Parameters:
9347c6ae99SBarry Smith +  da - the distributed array
94aa219208SBarry Smith -  dir - Cartesian direction, either DMDA_X, DMDA_Y, or DMDA_Z
9547c6ae99SBarry Smith 
9647c6ae99SBarry Smith    Output Parameters:
9747c6ae99SBarry Smith .  subcomm - new communicator
9847c6ae99SBarry Smith 
9947c6ae99SBarry Smith    Level: advanced
10047c6ae99SBarry Smith 
10147c6ae99SBarry Smith    Notes:
10247c6ae99SBarry Smith    This routine is useful for distributing one-dimensional data in a tensor product grid.
10347c6ae99SBarry Smith 
10447c6ae99SBarry Smith .keywords: distributed array, get, processor subset
10547c6ae99SBarry Smith @*/
106*7087cfbeSBarry Smith PetscErrorCode  DMDAGetProcessorSubsets(DM da, DMDADirection dir, MPI_Comm *subcomm)
10747c6ae99SBarry Smith {
10847c6ae99SBarry Smith   MPI_Comm       comm;
10947c6ae99SBarry Smith   MPI_Group      group, subgroup;
11047c6ae99SBarry Smith   PetscInt       subgroupSize = 0;
11147c6ae99SBarry Smith   PetscInt      *firstPoints;
11247c6ae99SBarry Smith   PetscMPIInt    size, *subgroupRanks = PETSC_NULL;
11347c6ae99SBarry Smith   PetscInt       xs, xm, ys, ym, zs, zm, firstPoint, p;
11447c6ae99SBarry Smith   PetscErrorCode ierr;
11547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
11647c6ae99SBarry Smith 
11747c6ae99SBarry Smith   PetscFunctionBegin;
11847c6ae99SBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
11947c6ae99SBarry Smith   comm = ((PetscObject) da)->comm;
120aa219208SBarry Smith   ierr = DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm);CHKERRQ(ierr);
12147c6ae99SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
122aa219208SBarry Smith   if (dir == DMDA_Z) {
123aa219208SBarry Smith     if (dd->dim < 3) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"DMDA_Z invalid for DMDA dim < 3");
12447c6ae99SBarry Smith     firstPoint = zs;
125aa219208SBarry Smith   } else if (dir == DMDA_Y) {
126aa219208SBarry Smith     if (dd->dim == 1) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"DMDA_Y invalid for DMDA dim = 1");
12747c6ae99SBarry Smith     firstPoint = ys;
128aa219208SBarry Smith   } else if (dir == DMDA_X) {
12947c6ae99SBarry Smith     firstPoint = xs;
13047c6ae99SBarry Smith   } else SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid direction");
13147c6ae99SBarry Smith 
13247c6ae99SBarry Smith   ierr = PetscMalloc2(size, PetscInt, &firstPoints, size, PetscMPIInt, &subgroupRanks);CHKERRQ(ierr);
13347c6ae99SBarry Smith   ierr = MPI_Allgather(&firstPoint, 1, MPIU_INT, firstPoints, 1, MPIU_INT, comm);CHKERRQ(ierr);
134aa219208SBarry Smith   ierr = PetscInfo2(da,"DMDAGetProcessorSubset: dim=%D, direction=%d, procs: ",dd->dim,(int)dir);CHKERRQ(ierr);
13547c6ae99SBarry Smith   for(p = 0; p < size; ++p) {
13647c6ae99SBarry Smith     if (firstPoints[p] == firstPoint) {
13747c6ae99SBarry Smith       subgroupRanks[subgroupSize++] = p;
13847c6ae99SBarry Smith       ierr = PetscInfo1(da, "%D ", p);CHKERRQ(ierr);
13947c6ae99SBarry Smith     }
14047c6ae99SBarry Smith   }
14147c6ae99SBarry Smith   ierr = PetscInfo(da, "\n");CHKERRQ(ierr);
14247c6ae99SBarry Smith   ierr = MPI_Comm_group(comm, &group);CHKERRQ(ierr);
14347c6ae99SBarry Smith   ierr = MPI_Group_incl(group, subgroupSize, subgroupRanks, &subgroup);CHKERRQ(ierr);
14447c6ae99SBarry Smith   ierr = MPI_Comm_create(comm, subgroup, subcomm);CHKERRQ(ierr);
14547c6ae99SBarry Smith   ierr = MPI_Group_free(&subgroup);CHKERRQ(ierr);
14647c6ae99SBarry Smith   ierr = MPI_Group_free(&group);CHKERRQ(ierr);
14747c6ae99SBarry Smith   ierr = PetscFree2(firstPoints, subgroupRanks);CHKERRQ(ierr);
14847c6ae99SBarry Smith   PetscFunctionReturn(0);
14947c6ae99SBarry Smith }
150