xref: /petsc/src/sys/objects/subcomm.c (revision 98921bda46e76d7aaed9e0138c5ff9d0ce93f355)
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 
802c9f0b5SLisandro Dalcin const char *const PetscSubcommTypes[] = {"GENERAL","CONTIGUOUS","INTERLACED","PetscSubcommType","PETSC_SUBCOMM_",NULL};
96a6fc655SJed Brown 
1095c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm);
1195c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm);
12e5acf8a4SHong Zhang 
13a530d236SBarry Smith /*@
14e5acf8a4SHong Zhang    PetscSubcommSetFromOptions - Allows setting options from a PetscSubcomm
15e5acf8a4SHong Zhang 
16e5acf8a4SHong Zhang    Collective on PetscSubcomm
17e5acf8a4SHong Zhang 
18e5acf8a4SHong Zhang    Input Parameter:
19e5acf8a4SHong Zhang .  psubcomm - PetscSubcomm context
20e5acf8a4SHong Zhang 
21e5acf8a4SHong Zhang    Level: beginner
22e5acf8a4SHong Zhang 
23e5acf8a4SHong Zhang @*/
24f68be91cSHong Zhang PetscErrorCode PetscSubcommSetFromOptions(PetscSubcomm psubcomm)
25f68be91cSHong Zhang {
26f68be91cSHong Zhang   PetscErrorCode   ierr;
2745487dadSJed Brown   PetscSubcommType type;
28f68be91cSHong Zhang   PetscBool        flg;
29f68be91cSHong Zhang 
30f68be91cSHong Zhang   PetscFunctionBegin;
31f68be91cSHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Must call PetscSubcommCreate firt");
3260f5f21cSHong Zhang 
33e5acf8a4SHong Zhang   ierr = PetscOptionsBegin(psubcomm->parent,psubcomm->subcommprefix,"Options for PetscSubcomm",NULL);CHKERRQ(ierr);
3460f5f21cSHong Zhang   ierr = PetscOptionsEnum("-psubcomm_type",NULL,NULL,PetscSubcommTypes,(PetscEnum)psubcomm->type,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
35f68be91cSHong Zhang   if (flg && psubcomm->type != type) {
36f68be91cSHong Zhang     /* free old structures */
37f68be91cSHong Zhang     ierr = PetscCommDestroy(&(psubcomm)->dupparent);CHKERRQ(ierr);
38306c2d5bSBarry Smith     ierr = PetscCommDestroy(&(psubcomm)->child);CHKERRQ(ierr);
39f68be91cSHong Zhang     ierr = PetscFree((psubcomm)->subsize);CHKERRQ(ierr);
40f68be91cSHong Zhang     switch (type) {
4145487dadSJed Brown     case PETSC_SUBCOMM_GENERAL:
42b3a4ddeeSHong Zhang       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
4345487dadSJed Brown     case PETSC_SUBCOMM_CONTIGUOUS:
44f68be91cSHong Zhang       ierr = PetscSubcommCreate_contiguous(psubcomm);CHKERRQ(ierr);
45f68be91cSHong Zhang       break;
4645487dadSJed Brown     case PETSC_SUBCOMM_INTERLACED:
47f68be91cSHong Zhang       ierr = PetscSubcommCreate_interlaced(psubcomm);CHKERRQ(ierr);
48f68be91cSHong Zhang       break;
49f68be91cSHong Zhang     default:
50*98921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[type]);
51f68be91cSHong Zhang     }
52f68be91cSHong Zhang   }
5319171117SHong Zhang 
5460f5f21cSHong Zhang   ierr = PetscOptionsName("-psubcomm_view","Triggers display of PetscSubcomm context","PetscSubcommView",&flg);CHKERRQ(ierr);
5519171117SHong Zhang   if (flg) {
560c9e03a2SStefano Zampini     ierr = PetscSubcommView(psubcomm,PETSC_VIEWER_STDOUT_(psubcomm->parent));CHKERRQ(ierr);
5719171117SHong Zhang   }
5860f5f21cSHong Zhang   ierr = PetscOptionsEnd();CHKERRQ(ierr);
59f68be91cSHong Zhang   PetscFunctionReturn(0);
60f68be91cSHong Zhang }
61d8a68f86SHong Zhang 
62e5acf8a4SHong Zhang /*@C
63e5acf8a4SHong Zhang   PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for all
64e5acf8a4SHong Zhang   PetscSubcomm items in the options database.
65e5acf8a4SHong Zhang 
66e5acf8a4SHong Zhang   Logically collective on PetscSubcomm.
67e5acf8a4SHong Zhang 
68e5acf8a4SHong Zhang   Level: Intermediate
69e5acf8a4SHong Zhang 
70e5acf8a4SHong Zhang   Input Parameters:
71e5acf8a4SHong Zhang +   psubcomm - PetscSubcomm context
72e5acf8a4SHong Zhang -   prefix - the prefix to prepend all PetscSubcomm item names with.
73e5acf8a4SHong Zhang 
74e5acf8a4SHong Zhang @*/
75e5acf8a4SHong Zhang PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm,const char pre[])
76e5acf8a4SHong Zhang {
77e5acf8a4SHong Zhang   PetscErrorCode   ierr;
78e5acf8a4SHong Zhang 
79e5acf8a4SHong Zhang   PetscFunctionBegin;
80e5acf8a4SHong Zhang    if (!pre) {
81e5acf8a4SHong Zhang     ierr = PetscFree(psubcomm->subcommprefix);CHKERRQ(ierr);
82e5acf8a4SHong Zhang   } else {
83a5b23f4aSJose E. Roman     if (pre[0] == '-') SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hyphen");
84e5acf8a4SHong Zhang     ierr = PetscFree(psubcomm->subcommprefix);CHKERRQ(ierr);
85e5acf8a4SHong Zhang     ierr = PetscStrallocpy(pre,&(psubcomm->subcommprefix));CHKERRQ(ierr);
86e5acf8a4SHong Zhang   }
87e5acf8a4SHong Zhang   PetscFunctionReturn(0);
88e5acf8a4SHong Zhang }
89e5acf8a4SHong Zhang 
90e5acf8a4SHong Zhang /*@C
9123072422SBarry Smith    PetscSubcommView - Views a PetscSubcomm of values as either ASCII text or a binary file
92e5acf8a4SHong Zhang 
93e5acf8a4SHong Zhang    Collective on PetscSubcomm
94e5acf8a4SHong Zhang 
95d8d19677SJose E. Roman    Input Parameters:
96e5acf8a4SHong Zhang +  psubcomm - PetscSubcomm context
97e5acf8a4SHong Zhang -  viewer - location to view the values
98e5acf8a4SHong Zhang 
99e5acf8a4SHong Zhang    Level: beginner
100e5acf8a4SHong Zhang @*/
101053d1c95SHong Zhang PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm,PetscViewer viewer)
102053d1c95SHong Zhang {
103053d1c95SHong Zhang   PetscErrorCode    ierr;
104053d1c95SHong Zhang   PetscBool         iascii;
105053d1c95SHong Zhang   PetscViewerFormat format;
106053d1c95SHong Zhang 
107053d1c95SHong Zhang   PetscFunctionBegin;
108053d1c95SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
109053d1c95SHong Zhang   if (iascii) {
110053d1c95SHong Zhang     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
111053d1c95SHong Zhang     if (format == PETSC_VIEWER_DEFAULT) {
112053d1c95SHong Zhang       MPI_Comm    comm=psubcomm->parent;
113053d1c95SHong Zhang       PetscMPIInt rank,size,subsize,subrank,duprank;
114053d1c95SHong Zhang 
115ffc4695bSBarry Smith       ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
11645487dadSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"PetscSubcomm type %s with total %d MPI processes:\n",PetscSubcommTypes[psubcomm->type],size);CHKERRQ(ierr);
117ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
118ffc4695bSBarry Smith       ierr = MPI_Comm_size(psubcomm->child,&subsize);CHKERRMPI(ierr);
119ffc4695bSBarry Smith       ierr = MPI_Comm_rank(psubcomm->child,&subrank);CHKERRMPI(ierr);
120ffc4695bSBarry Smith       ierr = MPI_Comm_rank(psubcomm->dupparent,&duprank);CHKERRMPI(ierr);
1210c9e03a2SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
1220c9e03a2SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"  [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n",rank,psubcomm->color,subsize,subrank,duprank);CHKERRQ(ierr);
1230c9e03a2SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
124a530d236SBarry Smith       ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
125053d1c95SHong Zhang     }
126053d1c95SHong Zhang   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported yet");
127053d1c95SHong Zhang   PetscFunctionReturn(0);
128053d1c95SHong Zhang }
129053d1c95SHong Zhang 
130a530d236SBarry Smith /*@
131d8a68f86SHong Zhang   PetscSubcommSetNumber - Set total number of subcommunicators.
132d8a68f86SHong Zhang 
133d083f849SBarry Smith    Collective
134d8a68f86SHong Zhang 
135d8d19677SJose E. Roman    Input Parameters:
136d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
137d8a68f86SHong Zhang -  nsubcomm - the total number of subcommunicators in psubcomm
138d8a68f86SHong Zhang 
139d8a68f86SHong Zhang    Level: advanced
140d8a68f86SHong Zhang 
141d8a68f86SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetType(),PetscSubcommSetTypeGeneral()
142d8a68f86SHong Zhang @*/
1437087cfbeSBarry Smith PetscErrorCode  PetscSubcommSetNumber(PetscSubcomm psubcomm,PetscInt nsubcomm)
144d8a68f86SHong Zhang {
145d8a68f86SHong Zhang   PetscErrorCode ierr;
146d8a68f86SHong Zhang   MPI_Comm       comm=psubcomm->parent;
14745487dadSJed Brown   PetscMPIInt    msub,size;
148d8a68f86SHong Zhang 
149d8a68f86SHong Zhang   PetscFunctionBegin;
150d8a68f86SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate() first");
151ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
15245487dadSJed Brown   ierr = PetscMPIIntCast(nsubcomm,&msub);CHKERRQ(ierr);
153*98921bdaSJacob Faibussowitsch   if (msub < 1 || msub > size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Num of subcommunicators %d cannot be < 1 or > input comm size %d",msub,size);
154d8a68f86SHong Zhang 
15545487dadSJed Brown   psubcomm->n = msub;
156d8a68f86SHong Zhang   PetscFunctionReturn(0);
157d8a68f86SHong Zhang }
158d8a68f86SHong Zhang 
159a530d236SBarry Smith /*@
160d8a68f86SHong Zhang   PetscSubcommSetType - Set type of subcommunicators.
161d8a68f86SHong Zhang 
162d083f849SBarry Smith    Collective
163d8a68f86SHong Zhang 
164d8d19677SJose E. Roman    Input Parameters:
165d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
1661ba920a7SHong Zhang -  subcommtype - subcommunicator type, PETSC_SUBCOMM_CONTIGUOUS,PETSC_SUBCOMM_INTERLACED
167d8a68f86SHong Zhang 
168d8a68f86SHong Zhang    Level: advanced
169d8a68f86SHong Zhang 
170a530d236SBarry Smith .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetNumber(),PetscSubcommSetTypeGeneral(), PetscSubcommType
171d8a68f86SHong Zhang @*/
1727c764164SBarry Smith PetscErrorCode  PetscSubcommSetType(PetscSubcomm psubcomm,PetscSubcommType subcommtype)
173d8a68f86SHong Zhang {
174d8a68f86SHong Zhang   PetscErrorCode ierr;
175d8a68f86SHong Zhang 
176d8a68f86SHong Zhang   PetscFunctionBegin;
177d8a68f86SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
178*98921bdaSJacob Faibussowitsch   if (psubcomm->n < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",psubcomm->n);
179d8a68f86SHong Zhang 
180d8a68f86SHong Zhang   if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
181d8a68f86SHong Zhang     ierr = PetscSubcommCreate_contiguous(psubcomm);CHKERRQ(ierr);
182d8a68f86SHong Zhang   } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
183d8a68f86SHong Zhang     ierr = PetscSubcommCreate_interlaced(psubcomm);CHKERRQ(ierr);
184*98921bdaSJacob Faibussowitsch   } else SETERRQ(psubcomm->parent,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[subcommtype]);
185d8a68f86SHong Zhang   PetscFunctionReturn(0);
186d8a68f86SHong Zhang }
187d8a68f86SHong Zhang 
188a530d236SBarry Smith /*@
18965d9b8f1SHong Zhang   PetscSubcommSetTypeGeneral - Set a PetscSubcomm from user's specifications
1901ba920a7SHong Zhang 
191d083f849SBarry Smith    Collective
1921ba920a7SHong Zhang 
193d8d19677SJose E. Roman    Input Parameters:
1941ba920a7SHong Zhang +  psubcomm - PetscSubcomm context
1951ba920a7SHong Zhang .  color   - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
19665d9b8f1SHong Zhang -  subrank - rank in the subcommunicator
1971ba920a7SHong Zhang 
1981ba920a7SHong Zhang    Level: advanced
1991ba920a7SHong Zhang 
2001ba920a7SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetNumber(),PetscSubcommSetType()
2011ba920a7SHong Zhang @*/
20265d9b8f1SHong Zhang PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm,PetscMPIInt color,PetscMPIInt subrank)
203d8a68f86SHong Zhang {
2041ba920a7SHong Zhang   PetscErrorCode ierr;
2051ba920a7SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
206c9e2ceb8SHong Zhang   PetscMPIInt    size,icolor,duprank,*recvbuf,sendbuf[3],mysubsize,rank,*subsize;
20745487dadSJed Brown   PetscMPIInt    i,nsubcomm=psubcomm->n;
2081ba920a7SHong Zhang 
209d8a68f86SHong Zhang   PetscFunctionBegin;
2101ba920a7SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
211*98921bdaSJacob Faibussowitsch   if (nsubcomm < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",nsubcomm);
2121ba920a7SHong Zhang 
213ffc4695bSBarry Smith   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRMPI(ierr);
2141ba920a7SHong Zhang 
21565d9b8f1SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
2169abe469cSDmitry 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(). */
217ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
218785e854fSJed Brown   ierr = PetscMalloc1(2*size,&recvbuf);CHKERRQ(ierr);
21965d9b8f1SHong Zhang 
220ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
221ffc4695bSBarry Smith   ierr = MPI_Comm_size(subcomm,&mysubsize);CHKERRMPI(ierr);
22265d9b8f1SHong Zhang 
22365d9b8f1SHong Zhang   sendbuf[0] = color;
224c9e2ceb8SHong Zhang   sendbuf[1] = mysubsize;
225ffc4695bSBarry Smith   ierr = MPI_Allgather(sendbuf,2,MPI_INT,recvbuf,2,MPI_INT,comm);CHKERRMPI(ierr);
22665d9b8f1SHong Zhang 
227eca4a452SHong Zhang   ierr = PetscCalloc1(nsubcomm,&subsize);CHKERRQ(ierr);
2289972d2ceSHong Zhang   for (i=0; i<2*size; i+=2) {
229c9e2ceb8SHong Zhang     subsize[recvbuf[i]] = recvbuf[i+1];
2301ba920a7SHong Zhang   }
23165d9b8f1SHong Zhang   ierr = PetscFree(recvbuf);CHKERRQ(ierr);
23265d9b8f1SHong Zhang 
23365d9b8f1SHong Zhang   duprank = 0;
234c9e2ceb8SHong Zhang   for (icolor=0; icolor<nsubcomm; icolor++) {
23565d9b8f1SHong Zhang     if (icolor != color) { /* not color of this process */
236c9e2ceb8SHong Zhang       duprank += subsize[icolor];
23765d9b8f1SHong Zhang     } else {
23865d9b8f1SHong Zhang       duprank += subrank;
23965d9b8f1SHong Zhang       break;
24065d9b8f1SHong Zhang     }
24165d9b8f1SHong Zhang   }
242ffc4695bSBarry Smith   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRMPI(ierr);
24365d9b8f1SHong Zhang 
2440298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
245306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
246ffc4695bSBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRMPI(ierr);
247ffc4695bSBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRMPI(ierr);
248a297a907SKarl Rupp 
2491ba920a7SHong Zhang   psubcomm->color   = color;
250c9e2ceb8SHong Zhang   psubcomm->subsize = subsize;
251c9e2ceb8SHong Zhang   psubcomm->type    = PETSC_SUBCOMM_GENERAL;
252d8a68f86SHong Zhang   PetscFunctionReturn(0);
253d8a68f86SHong Zhang }
254638faf0bSHong Zhang 
255a530d236SBarry Smith /*@
25689587e68SDave May   PetscSubcommDestroy - Destroys a PetscSubcomm object
25789587e68SDave May 
25889587e68SDave May    Collective on PetscSubcomm
25989587e68SDave May 
26089587e68SDave May    Input Parameter:
26189587e68SDave May    .  psubcomm - the PetscSubcomm context
26289587e68SDave May 
26389587e68SDave May    Level: advanced
26489587e68SDave May 
26589587e68SDave May .seealso: PetscSubcommCreate(),PetscSubcommSetType()
26689587e68SDave May @*/
2676bf464f9SBarry Smith PetscErrorCode  PetscSubcommDestroy(PetscSubcomm *psubcomm)
268cd05a4c0SHong Zhang {
269cd05a4c0SHong Zhang   PetscErrorCode ierr;
270cd05a4c0SHong Zhang 
271cd05a4c0SHong Zhang   PetscFunctionBegin;
2726bf464f9SBarry Smith   if (!*psubcomm) PetscFunctionReturn(0);
273aa9c1079SBarry Smith   ierr = PetscCommDestroy(&(*psubcomm)->dupparent);CHKERRQ(ierr);
274306c2d5bSBarry Smith   ierr = PetscCommDestroy(&(*psubcomm)->child);CHKERRQ(ierr);
275e37c6257SHong Zhang   ierr = PetscFree((*psubcomm)->subsize);CHKERRQ(ierr);
276e5acf8a4SHong Zhang   if ((*psubcomm)->subcommprefix) { ierr = PetscFree((*psubcomm)->subcommprefix);CHKERRQ(ierr); }
2776bf464f9SBarry Smith   ierr = PetscFree((*psubcomm));CHKERRQ(ierr);
278cd05a4c0SHong Zhang   PetscFunctionReturn(0);
279cd05a4c0SHong Zhang }
280cd05a4c0SHong Zhang 
281a530d236SBarry Smith /*@
282cd05a4c0SHong Zhang   PetscSubcommCreate - Create a PetscSubcomm context.
283cd05a4c0SHong Zhang 
284d083f849SBarry Smith    Collective
285cd05a4c0SHong Zhang 
286cd05a4c0SHong Zhang    Input Parameter:
2879873d53eSJed Brown .  comm - MPI communicator
288cd05a4c0SHong Zhang 
289cd05a4c0SHong Zhang    Output Parameter:
290cd05a4c0SHong Zhang .  psubcomm - location to store the PetscSubcomm context
291cd05a4c0SHong Zhang 
292638faf0bSHong Zhang    Level: advanced
293cd05a4c0SHong Zhang 
294a530d236SBarry Smith .seealso: PetscSubcommDestroy(), PetscSubcommSetTypeGeneral(), PetscSubcommSetFromOptions(), PetscSubcommSetType(),
295a530d236SBarry Smith           PetscSubcommSetNumber()
296638faf0bSHong Zhang @*/
2977087cfbeSBarry Smith PetscErrorCode  PetscSubcommCreate(MPI_Comm comm,PetscSubcomm *psubcomm)
298638faf0bSHong Zhang {
299638faf0bSHong Zhang   PetscErrorCode ierr;
300d3b23db5SHong Zhang   PetscMPIInt    rank,size;
301638faf0bSHong Zhang 
302638faf0bSHong Zhang   PetscFunctionBegin;
303b00a9115SJed Brown   ierr = PetscNew(psubcomm);CHKERRQ(ierr);
304a297a907SKarl Rupp 
305d3b23db5SHong Zhang   /* set defaults */
306ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
307ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
308f68be91cSHong Zhang 
309d8a68f86SHong Zhang   (*psubcomm)->parent    = comm;
310d3b23db5SHong Zhang   (*psubcomm)->dupparent = comm;
311306c2d5bSBarry Smith   (*psubcomm)->child     = PETSC_COMM_SELF;
312d3b23db5SHong Zhang   (*psubcomm)->n         = size;
313d3b23db5SHong Zhang   (*psubcomm)->color     = rank;
314e37c6257SHong Zhang   (*psubcomm)->subsize   = NULL;
315d3b23db5SHong Zhang   (*psubcomm)->type      = PETSC_SUBCOMM_INTERLACED;
316638faf0bSHong Zhang   PetscFunctionReturn(0);
317638faf0bSHong Zhang }
318638faf0bSHong Zhang 
319a530d236SBarry Smith /*@C
320a530d236SBarry Smith   PetscSubcommGetParent - Gets the communicator that was used to create the PetscSubcomm
321a530d236SBarry Smith 
322a530d236SBarry Smith    Collective
323a530d236SBarry Smith 
324a530d236SBarry Smith    Input Parameter:
325a530d236SBarry Smith .  scomm - the PetscSubcomm
326a530d236SBarry Smith 
327a530d236SBarry Smith    Output Parameter:
328a530d236SBarry Smith .  pcomm - location to store the parent communicator
329a530d236SBarry Smith 
330a530d236SBarry Smith    Level: intermediate
331a530d236SBarry Smith 
332a530d236SBarry Smith .seealso: PetscSubcommDestroy(), PetscSubcommSetTypeGeneral(), PetscSubcommSetFromOptions(), PetscSubcommSetType(),
333a530d236SBarry Smith           PetscSubcommSetNumber(), PetscSubcommGetChild(), PetscSubcommContiguousParent()
334a530d236SBarry Smith @*/
335a530d236SBarry Smith PetscErrorCode  PetscSubcommGetParent(PetscSubcomm scomm,MPI_Comm *pcomm)
336a530d236SBarry Smith {
337a530d236SBarry Smith   *pcomm = PetscSubcommParent(scomm);
338a530d236SBarry Smith   return 0;
339a530d236SBarry Smith }
340a530d236SBarry Smith 
341a530d236SBarry Smith /*@C
342a530d236SBarry Smith   PetscSubcommGetContiguousParent - Gets a communicator that that is a duplicate of the parent but has the ranks
343a530d236SBarry Smith                                     reordered by the order they are in the children
344a530d236SBarry Smith 
345a530d236SBarry Smith    Collective
346a530d236SBarry Smith 
347a530d236SBarry Smith    Input Parameter:
348a530d236SBarry Smith .  scomm - the PetscSubcomm
349a530d236SBarry Smith 
350a530d236SBarry Smith    Output Parameter:
351a530d236SBarry Smith .  pcomm - location to store the parent communicator
352a530d236SBarry Smith 
353a530d236SBarry Smith    Level: intermediate
354a530d236SBarry Smith 
355a530d236SBarry Smith .seealso: PetscSubcommDestroy(), PetscSubcommSetTypeGeneral(), PetscSubcommSetFromOptions(), PetscSubcommSetType(),
356a530d236SBarry Smith           PetscSubcommSetNumber(), PetscSubcommGetChild(), PetscSubcommContiguousParent()
357a530d236SBarry Smith @*/
358a530d236SBarry Smith PetscErrorCode  PetscSubcommGetContiguousParent(PetscSubcomm scomm,MPI_Comm *pcomm)
359a530d236SBarry Smith {
360a530d236SBarry Smith   *pcomm = PetscSubcommContiguousParent(scomm);
361a530d236SBarry Smith   return 0;
362a530d236SBarry Smith }
363a530d236SBarry Smith 
364a530d236SBarry Smith /*@C
365a530d236SBarry Smith   PetscSubcommGetChild - Gets the communicator created by the PetscSubcomm
366a530d236SBarry Smith 
367a530d236SBarry Smith    Collective
368a530d236SBarry Smith 
369a530d236SBarry Smith    Input Parameter:
370a530d236SBarry Smith .  scomm - the PetscSubcomm
371a530d236SBarry Smith 
372a530d236SBarry Smith    Output Parameter:
373a530d236SBarry Smith .  ccomm - location to store the child communicator
374a530d236SBarry Smith 
375a530d236SBarry Smith    Level: intermediate
376a530d236SBarry Smith 
377a530d236SBarry Smith .seealso: PetscSubcommDestroy(), PetscSubcommSetTypeGeneral(), PetscSubcommSetFromOptions(), PetscSubcommSetType(),
378a530d236SBarry Smith           PetscSubcommSetNumber(), PetscSubcommGetParent(), PetscSubcommContiguousParent()
379a530d236SBarry Smith @*/
380a530d236SBarry Smith PetscErrorCode  PetscSubcommGetChild(PetscSubcomm scomm,MPI_Comm *ccomm)
381a530d236SBarry Smith {
382a530d236SBarry Smith   *ccomm = PetscSubcommChild(scomm);
383a530d236SBarry Smith   return 0;
384a530d236SBarry Smith }
385a530d236SBarry Smith 
38695c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)
387638faf0bSHong Zhang {
388638faf0bSHong Zhang   PetscErrorCode ierr;
389d6037b41SHong Zhang   PetscMPIInt    rank,size,*subsize,duprank=-1,subrank=-1;
39045487dadSJed Brown   PetscMPIInt    np_subcomm,nleftover,i,color=-1,rankstart,nsubcomm=psubcomm->n;
391d8a68f86SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
392638faf0bSHong Zhang 
393638faf0bSHong Zhang   PetscFunctionBegin;
394ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
395ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
39655e3b8d2SHong Zhang 
397638faf0bSHong Zhang   /* get size of each subcommunicator */
398854ce69bSBarry Smith   ierr = PetscMalloc1(1+nsubcomm,&subsize);CHKERRQ(ierr);
399a297a907SKarl Rupp 
400638faf0bSHong Zhang   np_subcomm = size/nsubcomm;
401638faf0bSHong Zhang   nleftover  = size - nsubcomm*np_subcomm;
402638faf0bSHong Zhang   for (i=0; i<nsubcomm; i++) {
403638faf0bSHong Zhang     subsize[i] = np_subcomm;
404638faf0bSHong Zhang     if (i<nleftover) subsize[i]++;
405638faf0bSHong Zhang   }
406638faf0bSHong Zhang 
407638faf0bSHong Zhang   /* get color and subrank of this proc */
408638faf0bSHong Zhang   rankstart = 0;
409638faf0bSHong Zhang   for (i=0; i<nsubcomm; i++) {
410638faf0bSHong Zhang     if (rank >= rankstart && rank < rankstart+subsize[i]) {
411638faf0bSHong Zhang       color   = i;
412638faf0bSHong Zhang       subrank = rank - rankstart;
413638faf0bSHong Zhang       duprank = rank;
414638faf0bSHong Zhang       break;
415a297a907SKarl Rupp     } else rankstart += subsize[i];
416638faf0bSHong Zhang   }
417638faf0bSHong Zhang 
418ffc4695bSBarry Smith   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRMPI(ierr);
419638faf0bSHong Zhang 
420638faf0bSHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
421ffc4695bSBarry Smith   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRMPI(ierr);
4220298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
423306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
424ffc4695bSBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRMPI(ierr);
425ffc4695bSBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRMPI(ierr);
426a297a907SKarl Rupp 
427d8a68f86SHong Zhang   psubcomm->color   = color;
428e37c6257SHong Zhang   psubcomm->subsize = subsize;
429f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_CONTIGUOUS;
430638faf0bSHong Zhang   PetscFunctionReturn(0);
431638faf0bSHong Zhang }
432638faf0bSHong Zhang 
433638faf0bSHong Zhang /*
434638faf0bSHong Zhang    Note:
435638faf0bSHong Zhang    In PCREDUNDANT, to avoid data scattering from subcomm back to original comm, we create subcommunicators
43645fc02eaSBarry Smith    by iteratively taking a process into a subcommunicator.
437cd05a4c0SHong Zhang    Example: size=4, nsubcomm=(*psubcomm)->n=3
438cd05a4c0SHong Zhang      comm=(*psubcomm)->parent:
439cd05a4c0SHong Zhang       rank:     [0]  [1]  [2]  [3]
440cd05a4c0SHong Zhang       color:     0    1    2    0
441cd05a4c0SHong Zhang 
442cd05a4c0SHong Zhang      subcomm=(*psubcomm)->comm:
443cd05a4c0SHong Zhang       subrank:  [0]  [0]  [0]  [1]
444cd05a4c0SHong Zhang 
445cd05a4c0SHong Zhang      dupcomm=(*psubcomm)->dupparent:
446cd05a4c0SHong Zhang       duprank:  [0]  [2]  [3]  [1]
447cd05a4c0SHong Zhang 
448cd05a4c0SHong Zhang      Here, subcomm[color = 0] has subsize=2, owns process [0] and [3]
449cd05a4c0SHong Zhang            subcomm[color = 1] has subsize=1, owns process [1]
450cd05a4c0SHong Zhang            subcomm[color = 2] has subsize=1, owns process [2]
451cd05a4c0SHong Zhang            dupcomm has same number of processes as comm, and its duprank maps
452cd05a4c0SHong Zhang            processes in subcomm contiguously into a 1d array:
453cd05a4c0SHong Zhang             duprank: [0] [1]      [2]         [3]
454cd05a4c0SHong Zhang             rank:    [0] [3]      [1]         [2]
455cd05a4c0SHong Zhang                     subcomm[0] subcomm[1]  subcomm[2]
456638faf0bSHong Zhang */
457cd05a4c0SHong Zhang 
45895c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)
459cd05a4c0SHong Zhang {
460cd05a4c0SHong Zhang   PetscErrorCode ierr;
461cd05a4c0SHong Zhang   PetscMPIInt    rank,size,*subsize,duprank,subrank;
46245487dadSJed Brown   PetscMPIInt    np_subcomm,nleftover,i,j,color,nsubcomm=psubcomm->n;
463d8a68f86SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
464cd05a4c0SHong Zhang 
465cd05a4c0SHong Zhang   PetscFunctionBegin;
466ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
467ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
46855e3b8d2SHong Zhang 
469cd05a4c0SHong Zhang   /* get size of each subcommunicator */
470854ce69bSBarry Smith   ierr = PetscMalloc1(1+nsubcomm,&subsize);CHKERRQ(ierr);
471a297a907SKarl Rupp 
472cd05a4c0SHong Zhang   np_subcomm = size/nsubcomm;
473cd05a4c0SHong Zhang   nleftover  = size - nsubcomm*np_subcomm;
474cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
475cd05a4c0SHong Zhang     subsize[i] = np_subcomm;
476cd05a4c0SHong Zhang     if (i<nleftover) subsize[i]++;
477cd05a4c0SHong Zhang   }
478cd05a4c0SHong Zhang 
479cd05a4c0SHong Zhang   /* find color for this proc */
480cd05a4c0SHong Zhang   color   = rank%nsubcomm;
481cd05a4c0SHong Zhang   subrank = rank/nsubcomm;
482cd05a4c0SHong Zhang 
483ffc4695bSBarry Smith   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRMPI(ierr);
484cd05a4c0SHong Zhang 
485cd05a4c0SHong Zhang   j = 0; duprank = 0;
486cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
487cd05a4c0SHong Zhang     if (j == color) {
488cd05a4c0SHong Zhang       duprank += subrank;
489cd05a4c0SHong Zhang       break;
490cd05a4c0SHong Zhang     }
491cd05a4c0SHong Zhang     duprank += subsize[i]; j++;
492cd05a4c0SHong Zhang   }
493cd05a4c0SHong Zhang 
494cd05a4c0SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
495ffc4695bSBarry Smith   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRMPI(ierr);
4960298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
497306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
498ffc4695bSBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRMPI(ierr);
499ffc4695bSBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRMPI(ierr);
500a297a907SKarl Rupp 
501d8a68f86SHong Zhang   psubcomm->color   = color;
502e37c6257SHong Zhang   psubcomm->subsize = subsize;
503f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_INTERLACED;
504cd05a4c0SHong Zhang   PetscFunctionReturn(0);
505cd05a4c0SHong Zhang }
506638faf0bSHong Zhang 
507