xref: /petsc/src/sys/objects/subcomm.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
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 /*@
14*811af0c4SBarry Smith    PetscSubcommSetFromOptions - Allows setting options for a `PetscSubcomm`
15e5acf8a4SHong Zhang 
16*811af0c4SBarry Smith    Collective on psubcomm
17e5acf8a4SHong Zhang 
18e5acf8a4SHong Zhang    Input Parameter:
19*811af0c4SBarry Smith .  psubcomm - `PetscSubcomm` context
20e5acf8a4SHong Zhang 
21e5acf8a4SHong Zhang    Level: beginner
22e5acf8a4SHong Zhang 
23*811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`
24e5acf8a4SHong Zhang @*/
259371c9d4SSatish Balay PetscErrorCode PetscSubcommSetFromOptions(PetscSubcomm psubcomm) {
2645487dadSJed Brown   PetscSubcommType type;
27f68be91cSHong Zhang   PetscBool        flg;
28f68be91cSHong Zhang 
29f68be91cSHong Zhang   PetscFunctionBegin;
3028b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Must call PetscSubcommCreate firt");
3160f5f21cSHong Zhang 
32d0609cedSBarry Smith   PetscOptionsBegin(psubcomm->parent, psubcomm->subcommprefix, "Options for PetscSubcomm", NULL);
339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-psubcomm_type", NULL, NULL, PetscSubcommTypes, (PetscEnum)psubcomm->type, (PetscEnum *)&type, &flg));
34f68be91cSHong Zhang   if (flg && psubcomm->type != type) {
35f68be91cSHong Zhang     /* free old structures */
369566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&(psubcomm)->dupparent));
379566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&(psubcomm)->child));
389566063dSJacob Faibussowitsch     PetscCall(PetscFree((psubcomm)->subsize));
39f68be91cSHong Zhang     switch (type) {
409371c9d4SSatish Balay     case PETSC_SUBCOMM_GENERAL: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
419371c9d4SSatish Balay     case PETSC_SUBCOMM_CONTIGUOUS: PetscCall(PetscSubcommCreate_contiguous(psubcomm)); break;
429371c9d4SSatish Balay     case PETSC_SUBCOMM_INTERLACED: PetscCall(PetscSubcommCreate_interlaced(psubcomm)); break;
439371c9d4SSatish Balay     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscSubcommType %s is not supported yet", PetscSubcommTypes[type]);
44f68be91cSHong Zhang     }
45f68be91cSHong Zhang   }
4619171117SHong Zhang 
479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-psubcomm_view", "Triggers display of PetscSubcomm context", "PetscSubcommView", &flg));
481baa6e33SBarry Smith   if (flg) PetscCall(PetscSubcommView(psubcomm, PETSC_VIEWER_STDOUT_(psubcomm->parent)));
49d0609cedSBarry Smith   PetscOptionsEnd();
50f68be91cSHong Zhang   PetscFunctionReturn(0);
51f68be91cSHong Zhang }
52d8a68f86SHong Zhang 
53e5acf8a4SHong Zhang /*@C
54*811af0c4SBarry Smith   PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for options in the options database for this object
55e5acf8a4SHong Zhang 
56*811af0c4SBarry Smith   Logically collective on psubcomm
57e5acf8a4SHong Zhang 
58e5acf8a4SHong Zhang   Level: Intermediate
59e5acf8a4SHong Zhang 
60e5acf8a4SHong Zhang   Input Parameters:
61*811af0c4SBarry Smith +   psubcomm - `PetscSubcomm` context
62e5acf8a4SHong Zhang -   prefix - the prefix to prepend all PetscSubcomm item names with.
63e5acf8a4SHong Zhang 
64*811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`
65e5acf8a4SHong Zhang @*/
669371c9d4SSatish Balay PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm, const char pre[]) {
67e5acf8a4SHong Zhang   PetscFunctionBegin;
68e5acf8a4SHong Zhang   if (!pre) {
699566063dSJacob Faibussowitsch     PetscCall(PetscFree(psubcomm->subcommprefix));
70e5acf8a4SHong Zhang   } else {
71cc73adaaSBarry Smith     PetscCheck(pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
729566063dSJacob Faibussowitsch     PetscCall(PetscFree(psubcomm->subcommprefix));
739566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(pre, &(psubcomm->subcommprefix)));
74e5acf8a4SHong Zhang   }
75e5acf8a4SHong Zhang   PetscFunctionReturn(0);
76e5acf8a4SHong Zhang }
77e5acf8a4SHong Zhang 
78e5acf8a4SHong Zhang /*@C
79*811af0c4SBarry Smith    PetscSubcommView - Views a `PetscSubcomm`
80e5acf8a4SHong Zhang 
81*811af0c4SBarry Smith    Collective on psubcomm
82e5acf8a4SHong Zhang 
83d8d19677SJose E. Roman    Input Parameters:
84*811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
85*811af0c4SBarry Smith -  viewer - `PetscViewer` to display the information
86e5acf8a4SHong Zhang 
87e5acf8a4SHong Zhang    Level: beginner
88*811af0c4SBarry Smith 
89*811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`, `PetscViewer`
90e5acf8a4SHong Zhang @*/
919371c9d4SSatish Balay PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm, PetscViewer viewer) {
92053d1c95SHong Zhang   PetscBool         iascii;
93053d1c95SHong Zhang   PetscViewerFormat format;
94053d1c95SHong Zhang 
95053d1c95SHong Zhang   PetscFunctionBegin;
969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
97053d1c95SHong Zhang   if (iascii) {
989566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
99053d1c95SHong Zhang     if (format == PETSC_VIEWER_DEFAULT) {
100053d1c95SHong Zhang       MPI_Comm    comm = psubcomm->parent;
101053d1c95SHong Zhang       PetscMPIInt rank, size, subsize, subrank, duprank;
102053d1c95SHong Zhang 
1039566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
1049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "PetscSubcomm type %s with total %d MPI processes:\n", PetscSubcommTypes[psubcomm->type], size));
1059566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
1069566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(psubcomm->child, &subsize));
1079566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(psubcomm->child, &subrank));
1089566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(psubcomm->dupparent, &duprank));
1099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n", rank, psubcomm->color, subsize, subrank, duprank));
1119566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
1129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
113053d1c95SHong Zhang     }
114053d1c95SHong Zhang   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not supported yet");
115053d1c95SHong Zhang   PetscFunctionReturn(0);
116053d1c95SHong Zhang }
117053d1c95SHong Zhang 
118a530d236SBarry Smith /*@
119*811af0c4SBarry Smith   PetscSubcommSetNumber - Set total number of subcommunicators desired in the given `PetscSubcomm`
120d8a68f86SHong Zhang 
121d083f849SBarry Smith    Collective
122d8a68f86SHong Zhang 
123d8d19677SJose E. Roman    Input Parameters:
124*811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
125d8a68f86SHong Zhang -  nsubcomm - the total number of subcommunicators in psubcomm
126d8a68f86SHong Zhang 
127d8a68f86SHong Zhang    Level: advanced
128d8a68f86SHong Zhang 
129*811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetType()`, `PetscSubcommSetTypeGeneral()`
130d8a68f86SHong Zhang @*/
1319371c9d4SSatish Balay PetscErrorCode PetscSubcommSetNumber(PetscSubcomm psubcomm, PetscInt nsubcomm) {
132d8a68f86SHong Zhang   MPI_Comm    comm = psubcomm->parent;
13345487dadSJed Brown   PetscMPIInt msub, size;
134d8a68f86SHong Zhang 
135d8a68f86SHong Zhang   PetscFunctionBegin;
13628b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate() first");
1379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1389566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(nsubcomm, &msub));
139cc73adaaSBarry Smith   PetscCheck(msub >= 1 && msub <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Num of subcommunicators %d cannot be < 1 or > input comm size %d", msub, size);
140d8a68f86SHong Zhang 
14145487dadSJed Brown   psubcomm->n = msub;
142d8a68f86SHong Zhang   PetscFunctionReturn(0);
143d8a68f86SHong Zhang }
144d8a68f86SHong Zhang 
145a530d236SBarry Smith /*@
146*811af0c4SBarry Smith   PetscSubcommSetType - Set the way the original MPI communicator is divided up in the `PetscSubcomm`
147d8a68f86SHong Zhang 
148d083f849SBarry Smith    Collective
149d8a68f86SHong Zhang 
150d8d19677SJose E. Roman    Input Parameters:
151*811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
152*811af0c4SBarry Smith -  subcommtype - `PetscSubcommType` `PETSC_SUBCOMM_CONTIGUOUS` or `PETSC_SUBCOMM_INTERLACED`
153d8a68f86SHong Zhang 
154d8a68f86SHong Zhang    Level: advanced
155d8a68f86SHong Zhang 
156*811af0c4SBarry Smith .seealso: `PetscSubcommType`, `PETSC_SUBCOMM_CONTIGUOUS`, `PETSC_SUBCOMM_INTERLACED`,
157*811af0c4SBarry Smith           `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommType`
158d8a68f86SHong Zhang @*/
1599371c9d4SSatish Balay PetscErrorCode PetscSubcommSetType(PetscSubcomm psubcomm, PetscSubcommType subcommtype) {
160d8a68f86SHong Zhang   PetscFunctionBegin;
16128b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate()");
16208401ef6SPierre Jolivet   PetscCheck(psubcomm->n >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()", psubcomm->n);
163d8a68f86SHong Zhang 
164d8a68f86SHong Zhang   if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
1659566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate_contiguous(psubcomm));
166d8a68f86SHong Zhang   } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
1679566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate_interlaced(psubcomm));
16898921bdaSJacob Faibussowitsch   } else SETERRQ(psubcomm->parent, PETSC_ERR_SUP, "PetscSubcommType %s is not supported yet", PetscSubcommTypes[subcommtype]);
169d8a68f86SHong Zhang   PetscFunctionReturn(0);
170d8a68f86SHong Zhang }
171d8a68f86SHong Zhang 
172a530d236SBarry Smith /*@
173*811af0c4SBarry Smith   PetscSubcommSetTypeGeneral - Divides up a communicator based on a specific user's specification
1741ba920a7SHong Zhang 
175d083f849SBarry Smith    Collective
1761ba920a7SHong Zhang 
177d8d19677SJose E. Roman    Input Parameters:
178*811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
1791ba920a7SHong Zhang .  color   - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
18065d9b8f1SHong Zhang -  subrank - rank in the subcommunicator
1811ba920a7SHong Zhang 
1821ba920a7SHong Zhang    Level: advanced
1831ba920a7SHong Zhang 
184*811af0c4SBarry Smith .seealso: `PetscSubcommType`, `PETSC_SUBCOMM_CONTIGUOUS`, `PETSC_SUBCOMM_INTERLACED`, `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetType()`
1851ba920a7SHong Zhang @*/
1869371c9d4SSatish Balay PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm, PetscMPIInt color, PetscMPIInt subrank) {
1871ba920a7SHong Zhang   MPI_Comm    subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
188c9e2ceb8SHong Zhang   PetscMPIInt size, icolor, duprank, *recvbuf, sendbuf[3], mysubsize, rank, *subsize;
18945487dadSJed Brown   PetscMPIInt i, nsubcomm = psubcomm->n;
1901ba920a7SHong Zhang 
191d8a68f86SHong Zhang   PetscFunctionBegin;
19228b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate()");
19308401ef6SPierre Jolivet   PetscCheck(nsubcomm >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()", nsubcomm);
1941ba920a7SHong Zhang 
1959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
1961ba920a7SHong Zhang 
19765d9b8f1SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
1989abe469cSDmitry 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(). */
1999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2 * size, &recvbuf));
20165d9b8f1SHong Zhang 
2029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
2039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(subcomm, &mysubsize));
20465d9b8f1SHong Zhang 
20565d9b8f1SHong Zhang   sendbuf[0] = color;
206c9e2ceb8SHong Zhang   sendbuf[1] = mysubsize;
2079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(sendbuf, 2, MPI_INT, recvbuf, 2, MPI_INT, comm));
20865d9b8f1SHong Zhang 
2099566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nsubcomm, &subsize));
210ad540459SPierre Jolivet   for (i = 0; i < 2 * size; i += 2) subsize[recvbuf[i]] = recvbuf[i + 1];
2119566063dSJacob Faibussowitsch   PetscCall(PetscFree(recvbuf));
21265d9b8f1SHong Zhang 
21365d9b8f1SHong Zhang   duprank = 0;
214c9e2ceb8SHong Zhang   for (icolor = 0; icolor < nsubcomm; icolor++) {
21565d9b8f1SHong Zhang     if (icolor != color) { /* not color of this process */
216c9e2ceb8SHong Zhang       duprank += subsize[icolor];
21765d9b8f1SHong Zhang     } else {
21865d9b8f1SHong Zhang       duprank += subrank;
21965d9b8f1SHong Zhang       break;
22065d9b8f1SHong Zhang     }
22165d9b8f1SHong Zhang   }
2229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
22365d9b8f1SHong Zhang 
2249566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
2259566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
2269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
2279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
228a297a907SKarl Rupp 
2291ba920a7SHong Zhang   psubcomm->color   = color;
230c9e2ceb8SHong Zhang   psubcomm->subsize = subsize;
231c9e2ceb8SHong Zhang   psubcomm->type    = PETSC_SUBCOMM_GENERAL;
232d8a68f86SHong Zhang   PetscFunctionReturn(0);
233d8a68f86SHong Zhang }
234638faf0bSHong Zhang 
235a530d236SBarry Smith /*@
236*811af0c4SBarry Smith   PetscSubcommDestroy - Destroys a `PetscSubcomm` object
23789587e68SDave May 
238*811af0c4SBarry Smith    Collective on psubcomm
23989587e68SDave May 
24089587e68SDave May    Input Parameter:
241*811af0c4SBarry Smith    .  psubcomm - the `PetscSubcomm` context
24289587e68SDave May 
24389587e68SDave May    Level: advanced
24489587e68SDave May 
245c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommSetType()`
24689587e68SDave May @*/
2479371c9d4SSatish Balay PetscErrorCode PetscSubcommDestroy(PetscSubcomm *psubcomm) {
248cd05a4c0SHong Zhang   PetscFunctionBegin;
2496bf464f9SBarry Smith   if (!*psubcomm) PetscFunctionReturn(0);
2509566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&(*psubcomm)->dupparent));
2519566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&(*psubcomm)->child));
2529566063dSJacob Faibussowitsch   PetscCall(PetscFree((*psubcomm)->subsize));
2539566063dSJacob Faibussowitsch   if ((*psubcomm)->subcommprefix) PetscCall(PetscFree((*psubcomm)->subcommprefix));
2549566063dSJacob Faibussowitsch   PetscCall(PetscFree((*psubcomm)));
255cd05a4c0SHong Zhang   PetscFunctionReturn(0);
256cd05a4c0SHong Zhang }
257cd05a4c0SHong Zhang 
258a530d236SBarry Smith /*@
259*811af0c4SBarry Smith   PetscSubcommCreate - Create a `PetscSubcomm` context. This object is used to manage the division of a `MPI_Comm` into subcommunicators
260cd05a4c0SHong Zhang 
261d083f849SBarry Smith    Collective
262cd05a4c0SHong Zhang 
263cd05a4c0SHong Zhang    Input Parameter:
2649873d53eSJed Brown .  comm - MPI communicator
265cd05a4c0SHong Zhang 
266cd05a4c0SHong Zhang    Output Parameter:
267*811af0c4SBarry Smith .  psubcomm - location to store the `PetscSubcomm` context
268cd05a4c0SHong Zhang 
269638faf0bSHong Zhang    Level: advanced
270cd05a4c0SHong Zhang 
271*811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
272db781477SPatrick Sanan           `PetscSubcommSetNumber()`
273638faf0bSHong Zhang @*/
2749371c9d4SSatish Balay PetscErrorCode PetscSubcommCreate(MPI_Comm comm, PetscSubcomm *psubcomm) {
275d3b23db5SHong Zhang   PetscMPIInt rank, size;
276638faf0bSHong Zhang 
277638faf0bSHong Zhang   PetscFunctionBegin;
2789566063dSJacob Faibussowitsch   PetscCall(PetscNew(psubcomm));
279a297a907SKarl Rupp 
280d3b23db5SHong Zhang   /* set defaults */
2819566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
2829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
283f68be91cSHong Zhang 
284d8a68f86SHong Zhang   (*psubcomm)->parent    = comm;
285d3b23db5SHong Zhang   (*psubcomm)->dupparent = comm;
286306c2d5bSBarry Smith   (*psubcomm)->child     = PETSC_COMM_SELF;
287d3b23db5SHong Zhang   (*psubcomm)->n         = size;
288d3b23db5SHong Zhang   (*psubcomm)->color     = rank;
289e37c6257SHong Zhang   (*psubcomm)->subsize   = NULL;
290d3b23db5SHong Zhang   (*psubcomm)->type      = PETSC_SUBCOMM_INTERLACED;
291638faf0bSHong Zhang   PetscFunctionReturn(0);
292638faf0bSHong Zhang }
293638faf0bSHong Zhang 
294a530d236SBarry Smith /*@C
295*811af0c4SBarry Smith   PetscSubcommGetParent - Gets the communicator that was used to create the `PetscSubcomm`
296a530d236SBarry Smith 
297a530d236SBarry Smith    Collective
298a530d236SBarry Smith 
299a530d236SBarry Smith    Input Parameter:
300*811af0c4SBarry Smith .  scomm - the `PetscSubcomm`
301a530d236SBarry Smith 
302a530d236SBarry Smith    Output Parameter:
303a530d236SBarry Smith .  pcomm - location to store the parent communicator
304a530d236SBarry Smith 
305a530d236SBarry Smith    Level: intermediate
306a530d236SBarry Smith 
307db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
308db781477SPatrick Sanan           `PetscSubcommSetNumber()`, `PetscSubcommGetChild()`, `PetscSubcommContiguousParent()`
309a530d236SBarry Smith @*/
3109371c9d4SSatish Balay PetscErrorCode PetscSubcommGetParent(PetscSubcomm scomm, MPI_Comm *pcomm) {
311a530d236SBarry Smith   *pcomm = PetscSubcommParent(scomm);
312a530d236SBarry Smith   return 0;
313a530d236SBarry Smith }
314a530d236SBarry Smith 
315a530d236SBarry Smith /*@C
316a530d236SBarry Smith   PetscSubcommGetContiguousParent - Gets a communicator that that is a duplicate of the parent but has the ranks
317a530d236SBarry Smith                                     reordered by the order they are in the children
318a530d236SBarry Smith 
319a530d236SBarry Smith    Collective
320a530d236SBarry Smith 
321a530d236SBarry Smith    Input Parameter:
322*811af0c4SBarry Smith .  scomm - the `PetscSubcomm`
323a530d236SBarry Smith 
324a530d236SBarry Smith    Output Parameter:
325a530d236SBarry Smith .  pcomm - location to store the parent communicator
326a530d236SBarry Smith 
327a530d236SBarry Smith    Level: intermediate
328a530d236SBarry Smith 
329db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
330db781477SPatrick Sanan           `PetscSubcommSetNumber()`, `PetscSubcommGetChild()`, `PetscSubcommContiguousParent()`
331a530d236SBarry Smith @*/
3329371c9d4SSatish Balay PetscErrorCode PetscSubcommGetContiguousParent(PetscSubcomm scomm, MPI_Comm *pcomm) {
333a530d236SBarry Smith   *pcomm = PetscSubcommContiguousParent(scomm);
334a530d236SBarry Smith   return 0;
335a530d236SBarry Smith }
336a530d236SBarry Smith 
337a530d236SBarry Smith /*@C
338*811af0c4SBarry Smith   PetscSubcommGetChild - Gets the communicator created by the `PetscSubcomm`. This is part of one of the subcommunicators created by the `PetscSubcomm`
339a530d236SBarry Smith 
340a530d236SBarry Smith    Collective
341a530d236SBarry Smith 
342a530d236SBarry Smith    Input Parameter:
343*811af0c4SBarry Smith .  scomm - the `PetscSubcomm`
344a530d236SBarry Smith 
345a530d236SBarry Smith    Output Parameter:
346a530d236SBarry Smith .  ccomm - location to store the child communicator
347a530d236SBarry Smith 
348a530d236SBarry Smith    Level: intermediate
349a530d236SBarry Smith 
350db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
351db781477SPatrick Sanan           `PetscSubcommSetNumber()`, `PetscSubcommGetParent()`, `PetscSubcommContiguousParent()`
352a530d236SBarry Smith @*/
3539371c9d4SSatish Balay PetscErrorCode PetscSubcommGetChild(PetscSubcomm scomm, MPI_Comm *ccomm) {
354a530d236SBarry Smith   *ccomm = PetscSubcommChild(scomm);
355a530d236SBarry Smith   return 0;
356a530d236SBarry Smith }
357a530d236SBarry Smith 
3589371c9d4SSatish Balay static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm) {
359d6037b41SHong Zhang   PetscMPIInt rank, size, *subsize, duprank = -1, subrank = -1;
36045487dadSJed Brown   PetscMPIInt np_subcomm, nleftover, i, color = -1, rankstart, nsubcomm = psubcomm->n;
361d8a68f86SHong Zhang   MPI_Comm    subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
362638faf0bSHong Zhang 
363638faf0bSHong Zhang   PetscFunctionBegin;
3649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
3659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
36655e3b8d2SHong Zhang 
367638faf0bSHong Zhang   /* get size of each subcommunicator */
3689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1 + nsubcomm, &subsize));
369a297a907SKarl Rupp 
370638faf0bSHong Zhang   np_subcomm = size / nsubcomm;
371638faf0bSHong Zhang   nleftover  = size - nsubcomm * np_subcomm;
372638faf0bSHong Zhang   for (i = 0; i < nsubcomm; i++) {
373638faf0bSHong Zhang     subsize[i] = np_subcomm;
374638faf0bSHong Zhang     if (i < nleftover) subsize[i]++;
375638faf0bSHong Zhang   }
376638faf0bSHong Zhang 
377638faf0bSHong Zhang   /* get color and subrank of this proc */
378638faf0bSHong Zhang   rankstart = 0;
379638faf0bSHong Zhang   for (i = 0; i < nsubcomm; i++) {
380638faf0bSHong Zhang     if (rank >= rankstart && rank < rankstart + subsize[i]) {
381638faf0bSHong Zhang       color   = i;
382638faf0bSHong Zhang       subrank = rank - rankstart;
383638faf0bSHong Zhang       duprank = rank;
384638faf0bSHong Zhang       break;
385a297a907SKarl Rupp     } else rankstart += subsize[i];
386638faf0bSHong Zhang   }
387638faf0bSHong Zhang 
3889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
389638faf0bSHong Zhang 
390638faf0bSHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
3919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
3929566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
3939566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
3949566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
3959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
396a297a907SKarl Rupp 
397d8a68f86SHong Zhang   psubcomm->color   = color;
398e37c6257SHong Zhang   psubcomm->subsize = subsize;
399f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_CONTIGUOUS;
400638faf0bSHong Zhang   PetscFunctionReturn(0);
401638faf0bSHong Zhang }
402638faf0bSHong Zhang 
403638faf0bSHong Zhang /*
404638faf0bSHong Zhang    Note:
405638faf0bSHong Zhang    In PCREDUNDANT, to avoid data scattering from subcomm back to original comm, we create subcommunicators
40645fc02eaSBarry Smith    by iteratively taking a process into a subcommunicator.
407cd05a4c0SHong Zhang    Example: size=4, nsubcomm=(*psubcomm)->n=3
408cd05a4c0SHong Zhang      comm=(*psubcomm)->parent:
409cd05a4c0SHong Zhang       rank:     [0]  [1]  [2]  [3]
410cd05a4c0SHong Zhang       color:     0    1    2    0
411cd05a4c0SHong Zhang 
412cd05a4c0SHong Zhang      subcomm=(*psubcomm)->comm:
413cd05a4c0SHong Zhang       subrank:  [0]  [0]  [0]  [1]
414cd05a4c0SHong Zhang 
415cd05a4c0SHong Zhang      dupcomm=(*psubcomm)->dupparent:
416cd05a4c0SHong Zhang       duprank:  [0]  [2]  [3]  [1]
417cd05a4c0SHong Zhang 
418cd05a4c0SHong Zhang      Here, subcomm[color = 0] has subsize=2, owns process [0] and [3]
419cd05a4c0SHong Zhang            subcomm[color = 1] has subsize=1, owns process [1]
420cd05a4c0SHong Zhang            subcomm[color = 2] has subsize=1, owns process [2]
421cd05a4c0SHong Zhang            dupcomm has same number of processes as comm, and its duprank maps
422cd05a4c0SHong Zhang            processes in subcomm contiguously into a 1d array:
423cd05a4c0SHong Zhang             duprank: [0] [1]      [2]         [3]
424cd05a4c0SHong Zhang             rank:    [0] [3]      [1]         [2]
425cd05a4c0SHong Zhang                     subcomm[0] subcomm[1]  subcomm[2]
426638faf0bSHong Zhang */
427cd05a4c0SHong Zhang 
4289371c9d4SSatish Balay static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm) {
429cd05a4c0SHong Zhang   PetscMPIInt rank, size, *subsize, duprank, subrank;
43045487dadSJed Brown   PetscMPIInt np_subcomm, nleftover, i, j, color, nsubcomm = psubcomm->n;
431d8a68f86SHong Zhang   MPI_Comm    subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
432cd05a4c0SHong Zhang 
433cd05a4c0SHong Zhang   PetscFunctionBegin;
4349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
4359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
43655e3b8d2SHong Zhang 
437cd05a4c0SHong Zhang   /* get size of each subcommunicator */
4389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1 + nsubcomm, &subsize));
439a297a907SKarl Rupp 
440cd05a4c0SHong Zhang   np_subcomm = size / nsubcomm;
441cd05a4c0SHong Zhang   nleftover  = size - nsubcomm * np_subcomm;
442cd05a4c0SHong Zhang   for (i = 0; i < nsubcomm; i++) {
443cd05a4c0SHong Zhang     subsize[i] = np_subcomm;
444cd05a4c0SHong Zhang     if (i < nleftover) subsize[i]++;
445cd05a4c0SHong Zhang   }
446cd05a4c0SHong Zhang 
447cd05a4c0SHong Zhang   /* find color for this proc */
448cd05a4c0SHong Zhang   color   = rank % nsubcomm;
449cd05a4c0SHong Zhang   subrank = rank / nsubcomm;
450cd05a4c0SHong Zhang 
4519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
452cd05a4c0SHong Zhang 
4539371c9d4SSatish Balay   j       = 0;
4549371c9d4SSatish Balay   duprank = 0;
455cd05a4c0SHong Zhang   for (i = 0; i < nsubcomm; i++) {
456cd05a4c0SHong Zhang     if (j == color) {
457cd05a4c0SHong Zhang       duprank += subrank;
458cd05a4c0SHong Zhang       break;
459cd05a4c0SHong Zhang     }
4609371c9d4SSatish Balay     duprank += subsize[i];
4619371c9d4SSatish Balay     j++;
462cd05a4c0SHong Zhang   }
463cd05a4c0SHong Zhang 
464cd05a4c0SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
4659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
4669566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
4679566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
4689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
4699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
470a297a907SKarl Rupp 
471d8a68f86SHong Zhang   psubcomm->color   = color;
472e37c6257SHong Zhang   psubcomm->subsize = subsize;
473f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_INTERLACED;
474cd05a4c0SHong Zhang   PetscFunctionReturn(0);
475cd05a4c0SHong Zhang }
476