xref: /petsc/src/sys/objects/subcomm.c (revision e5acf8a457bbca6d488ec50ccac76a0142f931f5)
17d0a6c19SBarry Smith 
2cd05a4c0SHong Zhang /*
3cd05a4c0SHong Zhang      Provides utility routines for split MPI communicator.
4cd05a4c0SHong Zhang */
5c6db04a5SJed Brown #include <petscsys.h>    /*I   "petscsys.h"    I*/
6053d1c95SHong Zhang #include <petscviewer.h>
7cd05a4c0SHong Zhang 
86a6fc655SJed Brown const char *const PetscSubcommTypes[] = {"GENERAL","CONTIGUOUS","INTERLACED","PetscSubcommType","PETSC_SUBCOMM_",0};
96a6fc655SJed Brown 
10d8a68f86SHong Zhang extern PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm);
11d8a68f86SHong Zhang extern PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm);
12*e5acf8a4SHong Zhang 
13f68be91cSHong Zhang #undef __FUNCT__
14f68be91cSHong Zhang #define __FUNCT__ "PetscSubcommSetFromOptions"
15*e5acf8a4SHong Zhang /*@C
16*e5acf8a4SHong Zhang    PetscSubcommSetFromOptions - Allows setting options from a PetscSubcomm
17*e5acf8a4SHong Zhang 
18*e5acf8a4SHong Zhang    Collective on PetscSubcomm
19*e5acf8a4SHong Zhang 
20*e5acf8a4SHong Zhang    Input Parameter:
21*e5acf8a4SHong Zhang .  psubcomm - PetscSubcomm context
22*e5acf8a4SHong Zhang 
23*e5acf8a4SHong Zhang    Level: beginner
24*e5acf8a4SHong Zhang 
25*e5acf8a4SHong Zhang @*/
26f68be91cSHong Zhang PetscErrorCode PetscSubcommSetFromOptions(PetscSubcomm psubcomm)
27f68be91cSHong Zhang {
28f68be91cSHong Zhang   PetscErrorCode   ierr;
2945487dadSJed Brown   PetscSubcommType type;
30f68be91cSHong Zhang   PetscBool        flg;
31f68be91cSHong Zhang 
32f68be91cSHong Zhang   PetscFunctionBegin;
33f68be91cSHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Must call PetscSubcommCreate firt");
3460f5f21cSHong Zhang 
35*e5acf8a4SHong Zhang   ierr = PetscOptionsBegin(psubcomm->parent,psubcomm->subcommprefix,"Options for PetscSubcomm",NULL);CHKERRQ(ierr);
3660f5f21cSHong Zhang   ierr = PetscOptionsEnum("-psubcomm_type",NULL,NULL,PetscSubcommTypes,(PetscEnum)psubcomm->type,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
37f68be91cSHong Zhang   if (flg && psubcomm->type != type) {
38f68be91cSHong Zhang     /* free old structures */
39f68be91cSHong Zhang     ierr = PetscCommDestroy(&(psubcomm)->dupparent);CHKERRQ(ierr);
40306c2d5bSBarry Smith     ierr = PetscCommDestroy(&(psubcomm)->child);CHKERRQ(ierr);
41f68be91cSHong Zhang     ierr = PetscFree((psubcomm)->subsize);CHKERRQ(ierr);
42f68be91cSHong Zhang     switch (type) {
4345487dadSJed Brown     case PETSC_SUBCOMM_GENERAL:
44b3a4ddeeSHong Zhang       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
4545487dadSJed Brown     case PETSC_SUBCOMM_CONTIGUOUS:
46f68be91cSHong Zhang       ierr = PetscSubcommCreate_contiguous(psubcomm);CHKERRQ(ierr);
47f68be91cSHong Zhang       break;
4845487dadSJed Brown     case PETSC_SUBCOMM_INTERLACED:
49f68be91cSHong Zhang       ierr = PetscSubcommCreate_interlaced(psubcomm);CHKERRQ(ierr);
50f68be91cSHong Zhang       break;
51f68be91cSHong Zhang     default:
5245487dadSJed Brown       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[type]);
53f68be91cSHong Zhang     }
54f68be91cSHong Zhang   }
5519171117SHong Zhang 
5660f5f21cSHong Zhang   ierr = PetscOptionsName("-psubcomm_view","Triggers display of PetscSubcomm context","PetscSubcommView",&flg);CHKERRQ(ierr);
5719171117SHong Zhang   if (flg) {
5819171117SHong Zhang     ierr = PetscSubcommView(psubcomm,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
5919171117SHong Zhang   }
6060f5f21cSHong Zhang   ierr = PetscOptionsEnd();CHKERRQ(ierr);
61f68be91cSHong Zhang   PetscFunctionReturn(0);
62f68be91cSHong Zhang }
63d8a68f86SHong Zhang 
64d8a68f86SHong Zhang #undef __FUNCT__
65*e5acf8a4SHong Zhang #define __FUNCT__ "PetscSubcommSetOptionsPrefix"
66*e5acf8a4SHong Zhang /*@C
67*e5acf8a4SHong Zhang   PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for all
68*e5acf8a4SHong Zhang   PetscSubcomm items in the options database.
69*e5acf8a4SHong Zhang 
70*e5acf8a4SHong Zhang   Logically collective on PetscSubcomm.
71*e5acf8a4SHong Zhang 
72*e5acf8a4SHong Zhang   Level: Intermediate
73*e5acf8a4SHong Zhang 
74*e5acf8a4SHong Zhang   Input Parameters:
75*e5acf8a4SHong Zhang +   psubcomm - PetscSubcomm context
76*e5acf8a4SHong Zhang -   prefix - the prefix to prepend all PetscSubcomm item names with.
77*e5acf8a4SHong Zhang 
78*e5acf8a4SHong Zhang @*/
79*e5acf8a4SHong Zhang PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm,const char pre[])
80*e5acf8a4SHong Zhang {
81*e5acf8a4SHong Zhang   PetscErrorCode   ierr;
82*e5acf8a4SHong Zhang 
83*e5acf8a4SHong Zhang   PetscFunctionBegin;
84*e5acf8a4SHong Zhang    if (!pre) {
85*e5acf8a4SHong Zhang     ierr = PetscFree(psubcomm->subcommprefix);CHKERRQ(ierr);
86*e5acf8a4SHong Zhang   } else {
87*e5acf8a4SHong Zhang     if (pre[0] == '-') SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hypen");
88*e5acf8a4SHong Zhang     ierr = PetscFree(psubcomm->subcommprefix);CHKERRQ(ierr);
89*e5acf8a4SHong Zhang     ierr = PetscStrallocpy(pre,&(psubcomm->subcommprefix));CHKERRQ(ierr);
90*e5acf8a4SHong Zhang   }
91*e5acf8a4SHong Zhang   PetscFunctionReturn(0);
92*e5acf8a4SHong Zhang }
93*e5acf8a4SHong Zhang 
94*e5acf8a4SHong Zhang #undef __FUNCT__
95053d1c95SHong Zhang #define __FUNCT__ "PetscSubcommView"
96*e5acf8a4SHong Zhang /*@C
97*e5acf8a4SHong Zhang    PetsSubcommcView - Views a PetscSubcomm of values as either ASCII text or a binary file
98*e5acf8a4SHong Zhang 
99*e5acf8a4SHong Zhang    Collective on PetscSubcomm
100*e5acf8a4SHong Zhang 
101*e5acf8a4SHong Zhang    Input Parameter:
102*e5acf8a4SHong Zhang +  psubcomm - PetscSubcomm context
103*e5acf8a4SHong Zhang -  viewer - location to view the values
104*e5acf8a4SHong Zhang 
105*e5acf8a4SHong Zhang    Level: beginner
106*e5acf8a4SHong Zhang @*/
107053d1c95SHong Zhang PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm,PetscViewer viewer)
108053d1c95SHong Zhang {
109053d1c95SHong Zhang   PetscErrorCode    ierr;
110053d1c95SHong Zhang   PetscBool         iascii;
111053d1c95SHong Zhang   PetscViewerFormat format;
112053d1c95SHong Zhang 
113053d1c95SHong Zhang   PetscFunctionBegin;
114053d1c95SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
115053d1c95SHong Zhang   if (iascii) {
116053d1c95SHong Zhang     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
117053d1c95SHong Zhang     if (format == PETSC_VIEWER_DEFAULT) {
118053d1c95SHong Zhang       MPI_Comm    comm=psubcomm->parent;
119053d1c95SHong Zhang       PetscMPIInt rank,size,subsize,subrank,duprank;
120053d1c95SHong Zhang 
121053d1c95SHong Zhang       ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
12245487dadSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"PetscSubcomm type %s with total %d MPI processes:\n",PetscSubcommTypes[psubcomm->type],size);CHKERRQ(ierr);
123053d1c95SHong Zhang       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
124306c2d5bSBarry Smith       ierr = MPI_Comm_size(psubcomm->child,&subsize);CHKERRQ(ierr);
125306c2d5bSBarry Smith       ierr = MPI_Comm_rank(psubcomm->child,&subrank);CHKERRQ(ierr);
126053d1c95SHong Zhang       ierr = MPI_Comm_rank(psubcomm->dupparent,&duprank);CHKERRQ(ierr);
127302440fdSBarry Smith       ierr = PetscSynchronizedPrintf(comm,"  [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n",rank,psubcomm->color,subsize,subrank,duprank);CHKERRQ(ierr);
1280ec8b6e3SBarry Smith       ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
129053d1c95SHong Zhang     }
130053d1c95SHong Zhang   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported yet");
131053d1c95SHong Zhang   PetscFunctionReturn(0);
132053d1c95SHong Zhang }
133053d1c95SHong Zhang 
134053d1c95SHong Zhang #undef __FUNCT__
135d8a68f86SHong Zhang #define __FUNCT__ "PetscSubcommSetNumber"
136d8a68f86SHong Zhang /*@C
137d8a68f86SHong Zhang   PetscSubcommSetNumber - Set total number of subcommunicators.
138d8a68f86SHong Zhang 
139d8a68f86SHong Zhang    Collective on MPI_Comm
140d8a68f86SHong Zhang 
141d8a68f86SHong Zhang    Input Parameter:
142d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
143d8a68f86SHong Zhang -  nsubcomm - the total number of subcommunicators in psubcomm
144d8a68f86SHong Zhang 
145d8a68f86SHong Zhang    Level: advanced
146d8a68f86SHong Zhang 
147d8a68f86SHong Zhang .keywords: communicator
148d8a68f86SHong Zhang 
149d8a68f86SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetType(),PetscSubcommSetTypeGeneral()
150d8a68f86SHong Zhang @*/
1517087cfbeSBarry Smith PetscErrorCode  PetscSubcommSetNumber(PetscSubcomm psubcomm,PetscInt nsubcomm)
152d8a68f86SHong Zhang {
153d8a68f86SHong Zhang   PetscErrorCode ierr;
154d8a68f86SHong Zhang   MPI_Comm       comm=psubcomm->parent;
15545487dadSJed Brown   PetscMPIInt    msub,size;
156d8a68f86SHong Zhang 
157d8a68f86SHong Zhang   PetscFunctionBegin;
158d8a68f86SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate() first");
159d8a68f86SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
16045487dadSJed Brown   ierr = PetscMPIIntCast(nsubcomm,&msub);CHKERRQ(ierr);
16145487dadSJed Brown   if (msub < 1 || msub > size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Num of subcommunicators %d cannot be < 1 or > input comm size %d",msub,size);
162d8a68f86SHong Zhang 
16345487dadSJed Brown   psubcomm->n = msub;
164d8a68f86SHong Zhang   PetscFunctionReturn(0);
165d8a68f86SHong Zhang }
166d8a68f86SHong Zhang 
167d8a68f86SHong Zhang #undef __FUNCT__
168d8a68f86SHong Zhang #define __FUNCT__ "PetscSubcommSetType"
169d8a68f86SHong Zhang /*@C
170d8a68f86SHong Zhang   PetscSubcommSetType - Set type of subcommunicators.
171d8a68f86SHong Zhang 
172d8a68f86SHong Zhang    Collective on MPI_Comm
173d8a68f86SHong Zhang 
174d8a68f86SHong Zhang    Input Parameter:
175d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
1761ba920a7SHong Zhang -  subcommtype - subcommunicator type, PETSC_SUBCOMM_CONTIGUOUS,PETSC_SUBCOMM_INTERLACED
177d8a68f86SHong Zhang 
178d8a68f86SHong Zhang    Level: advanced
179d8a68f86SHong Zhang 
180d8a68f86SHong Zhang .keywords: communicator
181d8a68f86SHong Zhang 
182d8a68f86SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetNumber(),PetscSubcommSetTypeGeneral()
183d8a68f86SHong Zhang @*/
1847c764164SBarry Smith PetscErrorCode  PetscSubcommSetType(PetscSubcomm psubcomm,PetscSubcommType subcommtype)
185d8a68f86SHong Zhang {
186d8a68f86SHong Zhang   PetscErrorCode ierr;
187d8a68f86SHong Zhang 
188d8a68f86SHong Zhang   PetscFunctionBegin;
189d8a68f86SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
19045487dadSJed Brown   if (psubcomm->n < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",psubcomm->n);
191d8a68f86SHong Zhang 
192d8a68f86SHong Zhang   if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
193d8a68f86SHong Zhang     ierr = PetscSubcommCreate_contiguous(psubcomm);CHKERRQ(ierr);
194d8a68f86SHong Zhang   } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
195d8a68f86SHong Zhang     ierr = PetscSubcommCreate_interlaced(psubcomm);CHKERRQ(ierr);
19645487dadSJed Brown   } else SETERRQ1(psubcomm->parent,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[subcommtype]);
197d8a68f86SHong Zhang   PetscFunctionReturn(0);
198d8a68f86SHong Zhang }
199d8a68f86SHong Zhang 
200d8a68f86SHong Zhang #undef __FUNCT__
201d8a68f86SHong Zhang #define __FUNCT__ "PetscSubcommSetTypeGeneral"
2021ba920a7SHong Zhang /*@C
20365d9b8f1SHong Zhang   PetscSubcommSetTypeGeneral - Set a PetscSubcomm from user's specifications
2041ba920a7SHong Zhang 
2051ba920a7SHong Zhang    Collective on MPI_Comm
2061ba920a7SHong Zhang 
2071ba920a7SHong Zhang    Input Parameter:
2081ba920a7SHong Zhang +  psubcomm - PetscSubcomm context
2091ba920a7SHong Zhang .  color   - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
21065d9b8f1SHong Zhang -  subrank - rank in the subcommunicator
2111ba920a7SHong Zhang 
2121ba920a7SHong Zhang    Level: advanced
2131ba920a7SHong Zhang 
2141ba920a7SHong Zhang .keywords: communicator, create
2151ba920a7SHong Zhang 
2161ba920a7SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetNumber(),PetscSubcommSetType()
2171ba920a7SHong Zhang @*/
21865d9b8f1SHong Zhang PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm,PetscMPIInt color,PetscMPIInt subrank)
219d8a68f86SHong Zhang {
2201ba920a7SHong Zhang   PetscErrorCode ierr;
2211ba920a7SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
222c9e2ceb8SHong Zhang   PetscMPIInt    size,icolor,duprank,*recvbuf,sendbuf[3],mysubsize,rank,*subsize;
22345487dadSJed Brown   PetscMPIInt    i,nsubcomm=psubcomm->n;
2241ba920a7SHong Zhang 
225d8a68f86SHong Zhang   PetscFunctionBegin;
2261ba920a7SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
22745487dadSJed Brown   if (nsubcomm < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",nsubcomm);
2281ba920a7SHong Zhang 
2291ba920a7SHong Zhang   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr);
2301ba920a7SHong Zhang 
23165d9b8f1SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
2329abe469cSDmitry Karpeev   /* TODO: this can be done in an ostensibly scalale way (i.e., without allocating an array of size 'size') as is done in PetscObjectsCreateGlobalOrdering(). */
2331ba920a7SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
234785e854fSJed Brown   ierr = PetscMalloc1(2*size,&recvbuf);CHKERRQ(ierr);
23565d9b8f1SHong Zhang 
23665d9b8f1SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
237c9e2ceb8SHong Zhang   ierr = MPI_Comm_size(subcomm,&mysubsize);CHKERRQ(ierr);
23865d9b8f1SHong Zhang 
23965d9b8f1SHong Zhang   sendbuf[0] = color;
240c9e2ceb8SHong Zhang   sendbuf[1] = mysubsize;
241c9e2ceb8SHong Zhang   ierr = MPI_Allgather(sendbuf,2,MPI_INT,recvbuf,2,MPI_INT,comm);CHKERRQ(ierr);
24265d9b8f1SHong Zhang 
243eca4a452SHong Zhang   ierr = PetscCalloc1(nsubcomm,&subsize);CHKERRQ(ierr);
2449972d2ceSHong Zhang   for (i=0; i<2*size; i+=2) {
245c9e2ceb8SHong Zhang     subsize[recvbuf[i]] = recvbuf[i+1];
2461ba920a7SHong Zhang   }
24765d9b8f1SHong Zhang   ierr = PetscFree(recvbuf);CHKERRQ(ierr);
24865d9b8f1SHong Zhang 
24965d9b8f1SHong Zhang   duprank = 0;
250c9e2ceb8SHong Zhang   for (icolor=0; icolor<nsubcomm; icolor++) {
25165d9b8f1SHong Zhang     if (icolor != color) { /* not color of this process */
252c9e2ceb8SHong Zhang       duprank += subsize[icolor];
25365d9b8f1SHong Zhang     } else {
25465d9b8f1SHong Zhang       duprank += subrank;
25565d9b8f1SHong Zhang       break;
25665d9b8f1SHong Zhang     }
25765d9b8f1SHong Zhang   }
25865d9b8f1SHong Zhang   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr);
25965d9b8f1SHong Zhang 
2600298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
261306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
262b89831e5SBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRQ(ierr);
263b89831e5SBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
264a297a907SKarl Rupp 
2651ba920a7SHong Zhang   psubcomm->color   = color;
266c9e2ceb8SHong Zhang   psubcomm->subsize = subsize;
267c9e2ceb8SHong Zhang   psubcomm->type    = PETSC_SUBCOMM_GENERAL;
268d8a68f86SHong Zhang   PetscFunctionReturn(0);
269d8a68f86SHong Zhang }
270638faf0bSHong Zhang 
271cd05a4c0SHong Zhang #undef __FUNCT__
272cd05a4c0SHong Zhang #define __FUNCT__ "PetscSubcommDestroy"
2736bf464f9SBarry Smith PetscErrorCode  PetscSubcommDestroy(PetscSubcomm *psubcomm)
274cd05a4c0SHong Zhang {
275cd05a4c0SHong Zhang   PetscErrorCode ierr;
276cd05a4c0SHong Zhang 
277cd05a4c0SHong Zhang   PetscFunctionBegin;
2786bf464f9SBarry Smith   if (!*psubcomm) PetscFunctionReturn(0);
279aa9c1079SBarry Smith   ierr = PetscCommDestroy(&(*psubcomm)->dupparent);CHKERRQ(ierr);
280306c2d5bSBarry Smith   ierr = PetscCommDestroy(&(*psubcomm)->child);CHKERRQ(ierr);
281e37c6257SHong Zhang   ierr = PetscFree((*psubcomm)->subsize);CHKERRQ(ierr);
282*e5acf8a4SHong Zhang   if ((*psubcomm)->subcommprefix) { ierr = PetscFree((*psubcomm)->subcommprefix);CHKERRQ(ierr); }
2836bf464f9SBarry Smith   ierr = PetscFree((*psubcomm));CHKERRQ(ierr);
284cd05a4c0SHong Zhang   PetscFunctionReturn(0);
285cd05a4c0SHong Zhang }
286cd05a4c0SHong Zhang 
287cd05a4c0SHong Zhang #undef __FUNCT__
288cd05a4c0SHong Zhang #define __FUNCT__ "PetscSubcommCreate"
289ab8c242fSMatthew Knepley /*@C
290cd05a4c0SHong Zhang   PetscSubcommCreate - Create a PetscSubcomm context.
291cd05a4c0SHong Zhang 
292cd05a4c0SHong Zhang    Collective on MPI_Comm
293cd05a4c0SHong Zhang 
294cd05a4c0SHong Zhang    Input Parameter:
2959873d53eSJed Brown .  comm - MPI communicator
296cd05a4c0SHong Zhang 
297cd05a4c0SHong Zhang    Output Parameter:
298cd05a4c0SHong Zhang .  psubcomm - location to store the PetscSubcomm context
299cd05a4c0SHong Zhang 
300638faf0bSHong Zhang    Level: advanced
301cd05a4c0SHong Zhang 
302638faf0bSHong Zhang .keywords: communicator, create
303638faf0bSHong Zhang 
304638faf0bSHong Zhang .seealso: PetscSubcommDestroy()
305638faf0bSHong Zhang @*/
3067087cfbeSBarry Smith PetscErrorCode  PetscSubcommCreate(MPI_Comm comm,PetscSubcomm *psubcomm)
307638faf0bSHong Zhang {
308638faf0bSHong Zhang   PetscErrorCode ierr;
309d3b23db5SHong Zhang   PetscMPIInt    rank,size;
310638faf0bSHong Zhang 
311638faf0bSHong Zhang   PetscFunctionBegin;
312b00a9115SJed Brown   ierr = PetscNew(psubcomm);CHKERRQ(ierr);
313a297a907SKarl Rupp 
314d3b23db5SHong Zhang   /* set defaults */
315d3b23db5SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
316d3b23db5SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
317f68be91cSHong Zhang 
318d8a68f86SHong Zhang   (*psubcomm)->parent    = comm;
319d3b23db5SHong Zhang   (*psubcomm)->dupparent = comm;
320306c2d5bSBarry Smith   (*psubcomm)->child     = PETSC_COMM_SELF;
321d3b23db5SHong Zhang   (*psubcomm)->n         = size;
322d3b23db5SHong Zhang   (*psubcomm)->color     = rank;
323e37c6257SHong Zhang   (*psubcomm)->subsize   = NULL;
324d3b23db5SHong Zhang   (*psubcomm)->type      = PETSC_SUBCOMM_INTERLACED;
325638faf0bSHong Zhang   PetscFunctionReturn(0);
326638faf0bSHong Zhang }
327638faf0bSHong Zhang 
328638faf0bSHong Zhang #undef __FUNCT__
32953c77d0aSJed Brown #define __FUNCT__ "PetscSubcommCreate_contiguous"
330d8a68f86SHong Zhang PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)
331638faf0bSHong Zhang {
332638faf0bSHong Zhang   PetscErrorCode ierr;
333d6037b41SHong Zhang   PetscMPIInt    rank,size,*subsize,duprank=-1,subrank=-1;
33445487dadSJed Brown   PetscMPIInt    np_subcomm,nleftover,i,color=-1,rankstart,nsubcomm=psubcomm->n;
335d8a68f86SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
336638faf0bSHong Zhang 
337638faf0bSHong Zhang   PetscFunctionBegin;
33855e3b8d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
33955e3b8d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
34055e3b8d2SHong Zhang 
341638faf0bSHong Zhang   /* get size of each subcommunicator */
342854ce69bSBarry Smith   ierr = PetscMalloc1(1+nsubcomm,&subsize);CHKERRQ(ierr);
343a297a907SKarl Rupp 
344638faf0bSHong Zhang   np_subcomm = size/nsubcomm;
345638faf0bSHong Zhang   nleftover  = size - nsubcomm*np_subcomm;
346638faf0bSHong Zhang   for (i=0; i<nsubcomm; i++) {
347638faf0bSHong Zhang     subsize[i] = np_subcomm;
348638faf0bSHong Zhang     if (i<nleftover) subsize[i]++;
349638faf0bSHong Zhang   }
350638faf0bSHong Zhang 
351638faf0bSHong Zhang   /* get color and subrank of this proc */
352638faf0bSHong Zhang   rankstart = 0;
353638faf0bSHong Zhang   for (i=0; i<nsubcomm; i++) {
354638faf0bSHong Zhang     if (rank >= rankstart && rank < rankstart+subsize[i]) {
355638faf0bSHong Zhang       color   = i;
356638faf0bSHong Zhang       subrank = rank - rankstart;
357638faf0bSHong Zhang       duprank = rank;
358638faf0bSHong Zhang       break;
359a297a907SKarl Rupp     } else rankstart += subsize[i];
360638faf0bSHong Zhang   }
361638faf0bSHong Zhang 
362638faf0bSHong Zhang   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr);
363638faf0bSHong Zhang 
364638faf0bSHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
365638faf0bSHong Zhang   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr);
3660298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
367306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
368b89831e5SBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRQ(ierr);
369b89831e5SBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
370a297a907SKarl Rupp 
371d8a68f86SHong Zhang   psubcomm->color   = color;
372e37c6257SHong Zhang   psubcomm->subsize = subsize;
373f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_CONTIGUOUS;
374638faf0bSHong Zhang   PetscFunctionReturn(0);
375638faf0bSHong Zhang }
376638faf0bSHong Zhang 
377638faf0bSHong Zhang #undef __FUNCT__
378638faf0bSHong Zhang #define __FUNCT__ "PetscSubcommCreate_interlaced"
379638faf0bSHong Zhang /*
380638faf0bSHong Zhang    Note:
381638faf0bSHong Zhang    In PCREDUNDANT, to avoid data scattering from subcomm back to original comm, we create subcommunicators
38245fc02eaSBarry Smith    by iteratively taking a process into a subcommunicator.
383cd05a4c0SHong Zhang    Example: size=4, nsubcomm=(*psubcomm)->n=3
384cd05a4c0SHong Zhang      comm=(*psubcomm)->parent:
385cd05a4c0SHong Zhang       rank:     [0]  [1]  [2]  [3]
386cd05a4c0SHong Zhang       color:     0    1    2    0
387cd05a4c0SHong Zhang 
388cd05a4c0SHong Zhang      subcomm=(*psubcomm)->comm:
389cd05a4c0SHong Zhang       subrank:  [0]  [0]  [0]  [1]
390cd05a4c0SHong Zhang 
391cd05a4c0SHong Zhang      dupcomm=(*psubcomm)->dupparent:
392cd05a4c0SHong Zhang       duprank:  [0]  [2]  [3]  [1]
393cd05a4c0SHong Zhang 
394cd05a4c0SHong Zhang      Here, subcomm[color = 0] has subsize=2, owns process [0] and [3]
395cd05a4c0SHong Zhang            subcomm[color = 1] has subsize=1, owns process [1]
396cd05a4c0SHong Zhang            subcomm[color = 2] has subsize=1, owns process [2]
397cd05a4c0SHong Zhang            dupcomm has same number of processes as comm, and its duprank maps
398cd05a4c0SHong Zhang            processes in subcomm contiguously into a 1d array:
399cd05a4c0SHong Zhang             duprank: [0] [1]      [2]         [3]
400cd05a4c0SHong Zhang             rank:    [0] [3]      [1]         [2]
401cd05a4c0SHong Zhang                     subcomm[0] subcomm[1]  subcomm[2]
402638faf0bSHong Zhang */
403cd05a4c0SHong Zhang 
404d8a68f86SHong Zhang PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)
405cd05a4c0SHong Zhang {
406cd05a4c0SHong Zhang   PetscErrorCode ierr;
407cd05a4c0SHong Zhang   PetscMPIInt    rank,size,*subsize,duprank,subrank;
40845487dadSJed Brown   PetscMPIInt    np_subcomm,nleftover,i,j,color,nsubcomm=psubcomm->n;
409d8a68f86SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
410cd05a4c0SHong Zhang 
411cd05a4c0SHong Zhang   PetscFunctionBegin;
41255e3b8d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
41355e3b8d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
41455e3b8d2SHong Zhang 
415cd05a4c0SHong Zhang   /* get size of each subcommunicator */
416854ce69bSBarry Smith   ierr = PetscMalloc1(1+nsubcomm,&subsize);CHKERRQ(ierr);
417a297a907SKarl Rupp 
418cd05a4c0SHong Zhang   np_subcomm = size/nsubcomm;
419cd05a4c0SHong Zhang   nleftover  = size - nsubcomm*np_subcomm;
420cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
421cd05a4c0SHong Zhang     subsize[i] = np_subcomm;
422cd05a4c0SHong Zhang     if (i<nleftover) subsize[i]++;
423cd05a4c0SHong Zhang   }
424cd05a4c0SHong Zhang 
425cd05a4c0SHong Zhang   /* find color for this proc */
426cd05a4c0SHong Zhang   color   = rank%nsubcomm;
427cd05a4c0SHong Zhang   subrank = rank/nsubcomm;
428cd05a4c0SHong Zhang 
429cd05a4c0SHong Zhang   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr);
430cd05a4c0SHong Zhang 
431cd05a4c0SHong Zhang   j = 0; duprank = 0;
432cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
433cd05a4c0SHong Zhang     if (j == color) {
434cd05a4c0SHong Zhang       duprank += subrank;
435cd05a4c0SHong Zhang       break;
436cd05a4c0SHong Zhang     }
437cd05a4c0SHong Zhang     duprank += subsize[i]; j++;
438cd05a4c0SHong Zhang   }
439cd05a4c0SHong Zhang 
440cd05a4c0SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
441cd05a4c0SHong Zhang   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr);
4420298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
443306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
444b89831e5SBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRQ(ierr);
445b89831e5SBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
446a297a907SKarl Rupp 
447d8a68f86SHong Zhang   psubcomm->color   = color;
448e37c6257SHong Zhang   psubcomm->subsize = subsize;
449f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_INTERLACED;
450cd05a4c0SHong Zhang   PetscFunctionReturn(0);
451cd05a4c0SHong Zhang }
452638faf0bSHong Zhang 
453638faf0bSHong Zhang 
454