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