1cd05a4c0SHong Zhang #define PETSC_DLL 2cd05a4c0SHong Zhang /* 3cd05a4c0SHong Zhang Provides utility routines for split MPI communicator. 4cd05a4c0SHong Zhang */ 5*d382aafbSBarry Smith #include "petscsys.h" /*I "petscsys.h" I*/ 6cd05a4c0SHong Zhang 7cd05a4c0SHong Zhang #undef __FUNCT__ 8cd05a4c0SHong Zhang #define __FUNCT__ "PetscSubcommDestroy" 9c540e29cSHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT PetscSubcommDestroy(PetscSubcomm psubcomm) 10cd05a4c0SHong Zhang { 11cd05a4c0SHong Zhang PetscErrorCode ierr; 12cd05a4c0SHong Zhang 13cd05a4c0SHong Zhang PetscFunctionBegin; 14cd05a4c0SHong Zhang ierr = PetscFree(psubcomm);CHKERRQ(ierr); 15cd05a4c0SHong Zhang PetscFunctionReturn(0); 16cd05a4c0SHong Zhang } 17cd05a4c0SHong Zhang 18cd05a4c0SHong Zhang #undef __FUNCT__ 19cd05a4c0SHong Zhang #define __FUNCT__ "PetscSubcommCreate" 20ab8c242fSMatthew Knepley /*@C 21cd05a4c0SHong Zhang PetscSubcommCreate - Create a PetscSubcomm context. 22cd05a4c0SHong Zhang 23cd05a4c0SHong Zhang Collective on MPI_Comm 24cd05a4c0SHong Zhang 25cd05a4c0SHong Zhang Input Parameter: 26cd05a4c0SHong Zhang + comm - MPI communicator 27cd05a4c0SHong Zhang - nsubcomm - the number of subcommunicators to be created 28cd05a4c0SHong Zhang 29cd05a4c0SHong Zhang Output Parameter: 30cd05a4c0SHong Zhang . psubcomm - location to store the PetscSubcomm context 31cd05a4c0SHong Zhang 32cd05a4c0SHong Zhang 33cd05a4c0SHong Zhang Notes: 34cd05a4c0SHong Zhang To avoid data scattering from subcomm back to original comm, we create subcommunicators 3545fc02eaSBarry Smith by iteratively taking a process into a subcommunicator. 36cd05a4c0SHong Zhang Example: size=4, nsubcomm=(*psubcomm)->n=3 37cd05a4c0SHong Zhang comm=(*psubcomm)->parent: 38cd05a4c0SHong Zhang rank: [0] [1] [2] [3] 39cd05a4c0SHong Zhang color: 0 1 2 0 40cd05a4c0SHong Zhang 41cd05a4c0SHong Zhang subcomm=(*psubcomm)->comm: 42cd05a4c0SHong Zhang subrank: [0] [0] [0] [1] 43cd05a4c0SHong Zhang 44cd05a4c0SHong Zhang dupcomm=(*psubcomm)->dupparent: 45cd05a4c0SHong Zhang duprank: [0] [2] [3] [1] 46cd05a4c0SHong Zhang 47cd05a4c0SHong Zhang Here, subcomm[color = 0] has subsize=2, owns process [0] and [3] 48cd05a4c0SHong Zhang subcomm[color = 1] has subsize=1, owns process [1] 49cd05a4c0SHong Zhang subcomm[color = 2] has subsize=1, owns process [2] 50cd05a4c0SHong Zhang dupcomm has same number of processes as comm, and its duprank maps 51cd05a4c0SHong Zhang processes in subcomm contiguously into a 1d array: 52cd05a4c0SHong Zhang duprank: [0] [1] [2] [3] 53cd05a4c0SHong Zhang rank: [0] [3] [1] [2] 54cd05a4c0SHong Zhang subcomm[0] subcomm[1] subcomm[2] 55cd05a4c0SHong Zhang 56cd05a4c0SHong Zhang Level: advanced 57cd05a4c0SHong Zhang 58cd05a4c0SHong Zhang .keywords: communicator, create 59cd05a4c0SHong Zhang 60cd05a4c0SHong Zhang .seealso: PetscSubcommDestroy() 61cd05a4c0SHong Zhang @*/ 62c540e29cSHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT PetscSubcommCreate(MPI_Comm comm,PetscInt nsubcomm,PetscSubcomm *psubcomm) 63cd05a4c0SHong Zhang { 64cd05a4c0SHong Zhang PetscErrorCode ierr; 65cd05a4c0SHong Zhang PetscMPIInt rank,size,*subsize,duprank,subrank; 66cd05a4c0SHong Zhang PetscInt np_subcomm,nleftover,i,j,color; 67cd05a4c0SHong Zhang MPI_Comm subcomm=0,dupcomm=0; 68c540e29cSHong Zhang PetscSubcomm psubcomm_tmp; 69cd05a4c0SHong Zhang 70cd05a4c0SHong Zhang PetscFunctionBegin; 71cd05a4c0SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 72cd05a4c0SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 73cd05a4c0SHong Zhang if (nsubcomm < 1 || nsubcomm > size) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Num of subcommunicators %D cannot be < 1 or > input comm size %D",nsubcomm,size); 74cd05a4c0SHong Zhang 75cd05a4c0SHong Zhang /* get size of each subcommunicator */ 76cd05a4c0SHong Zhang ierr = PetscMalloc((1+nsubcomm)*sizeof(PetscMPIInt),&subsize);CHKERRQ(ierr); 77cd05a4c0SHong Zhang np_subcomm = size/nsubcomm; 78cd05a4c0SHong Zhang nleftover = size - nsubcomm*np_subcomm; 79cd05a4c0SHong Zhang for (i=0; i<nsubcomm; i++){ 80cd05a4c0SHong Zhang subsize[i] = np_subcomm; 81cd05a4c0SHong Zhang if (i<nleftover) subsize[i]++; 82cd05a4c0SHong Zhang } 83cd05a4c0SHong Zhang 84cd05a4c0SHong Zhang /* find color for this proc */ 85cd05a4c0SHong Zhang color = rank%nsubcomm; 86cd05a4c0SHong Zhang subrank = rank/nsubcomm; 87cd05a4c0SHong Zhang 88cd05a4c0SHong Zhang ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr); 89cd05a4c0SHong Zhang 90cd05a4c0SHong Zhang j = 0; duprank = 0; 91cd05a4c0SHong Zhang for (i=0; i<nsubcomm; i++){ 92cd05a4c0SHong Zhang if (j == color){ 93cd05a4c0SHong Zhang duprank += subrank; 94cd05a4c0SHong Zhang break; 95cd05a4c0SHong Zhang } 96cd05a4c0SHong Zhang duprank += subsize[i]; j++; 97cd05a4c0SHong Zhang } 9845fc02eaSBarry Smith ierr = PetscFree(subsize);CHKERRQ(ierr); 99cd05a4c0SHong Zhang 100cd05a4c0SHong Zhang /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */ 101cd05a4c0SHong Zhang ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr); 102cd05a4c0SHong Zhang 10304033c30SSatish Balay ierr = PetscNew(struct _n_PetscSubcomm,&psubcomm_tmp);CHKERRQ(ierr); 104cd05a4c0SHong Zhang psubcomm_tmp->parent = comm; 105cd05a4c0SHong Zhang psubcomm_tmp->dupparent = dupcomm; 106cd05a4c0SHong Zhang psubcomm_tmp->comm = subcomm; 107cd05a4c0SHong Zhang psubcomm_tmp->n = nsubcomm; 108cd05a4c0SHong Zhang psubcomm_tmp->color = color; 109cd05a4c0SHong Zhang *psubcomm = psubcomm_tmp; 110cd05a4c0SHong Zhang PetscFunctionReturn(0); 111cd05a4c0SHong Zhang } 112