xref: /petsc/src/sys/objects/subcomm.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
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 /*@
14811af0c4SBarry Smith    PetscSubcommSetFromOptions - Allows setting options for a `PetscSubcomm`
15e5acf8a4SHong Zhang 
16c3339decSBarry Smith    Collective
17e5acf8a4SHong Zhang 
18e5acf8a4SHong Zhang    Input Parameter:
19811af0c4SBarry Smith .  psubcomm - `PetscSubcomm` context
20e5acf8a4SHong Zhang 
21e5acf8a4SHong Zhang    Level: beginner
22e5acf8a4SHong Zhang 
23811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`
24e5acf8a4SHong Zhang @*/
25d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetFromOptions(PetscSubcomm psubcomm)
26d71ae5a4SJacob Faibussowitsch {
2745487dadSJed Brown   PetscSubcommType type;
28f68be91cSHong Zhang   PetscBool        flg;
29f68be91cSHong Zhang 
30f68be91cSHong Zhang   PetscFunctionBegin;
3128b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Must call PetscSubcommCreate firt");
3260f5f21cSHong Zhang 
33d0609cedSBarry Smith   PetscOptionsBegin(psubcomm->parent, psubcomm->subcommprefix, "Options for PetscSubcomm", NULL);
349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-psubcomm_type", NULL, NULL, PetscSubcommTypes, (PetscEnum)psubcomm->type, (PetscEnum *)&type, &flg));
35f68be91cSHong Zhang   if (flg && psubcomm->type != type) {
36f68be91cSHong Zhang     /* free old structures */
379566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&(psubcomm)->dupparent));
389566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&(psubcomm)->child));
399566063dSJacob Faibussowitsch     PetscCall(PetscFree((psubcomm)->subsize));
40f68be91cSHong Zhang     switch (type) {
41d71ae5a4SJacob Faibussowitsch     case PETSC_SUBCOMM_GENERAL:
42d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
43d71ae5a4SJacob Faibussowitsch     case PETSC_SUBCOMM_CONTIGUOUS:
44d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSubcommCreate_contiguous(psubcomm));
45d71ae5a4SJacob Faibussowitsch       break;
46d71ae5a4SJacob Faibussowitsch     case PETSC_SUBCOMM_INTERLACED:
47d71ae5a4SJacob Faibussowitsch       PetscCall(PetscSubcommCreate_interlaced(psubcomm));
48d71ae5a4SJacob Faibussowitsch       break;
49d71ae5a4SJacob Faibussowitsch     default:
50d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscSubcommType %s is not supported yet", PetscSubcommTypes[type]);
51f68be91cSHong Zhang     }
52f68be91cSHong Zhang   }
5319171117SHong Zhang 
549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-psubcomm_view", "Triggers display of PetscSubcomm context", "PetscSubcommView", &flg));
551baa6e33SBarry Smith   if (flg) PetscCall(PetscSubcommView(psubcomm, PETSC_VIEWER_STDOUT_(psubcomm->parent)));
56d0609cedSBarry Smith   PetscOptionsEnd();
573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58f68be91cSHong Zhang }
59d8a68f86SHong Zhang 
60e5acf8a4SHong Zhang /*@C
61811af0c4SBarry Smith   PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for options in the options database for this object
62e5acf8a4SHong Zhang 
63*20f4b53cSBarry Smith   Logically Collective
64e5acf8a4SHong Zhang 
65e5acf8a4SHong Zhang   Level: Intermediate
66e5acf8a4SHong Zhang 
67e5acf8a4SHong Zhang   Input Parameters:
68811af0c4SBarry Smith +   psubcomm - `PetscSubcomm` context
69e5acf8a4SHong Zhang -   prefix - the prefix to prepend all PetscSubcomm item names with.
70e5acf8a4SHong Zhang 
71811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`
72e5acf8a4SHong Zhang @*/
73d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm, const char pre[])
74d71ae5a4SJacob Faibussowitsch {
75e5acf8a4SHong Zhang   PetscFunctionBegin;
76e5acf8a4SHong Zhang   if (!pre) {
779566063dSJacob Faibussowitsch     PetscCall(PetscFree(psubcomm->subcommprefix));
78e5acf8a4SHong Zhang   } else {
79cc73adaaSBarry Smith     PetscCheck(pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
809566063dSJacob Faibussowitsch     PetscCall(PetscFree(psubcomm->subcommprefix));
819566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(pre, &(psubcomm->subcommprefix)));
82e5acf8a4SHong Zhang   }
833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84e5acf8a4SHong Zhang }
85e5acf8a4SHong Zhang 
86e5acf8a4SHong Zhang /*@C
87811af0c4SBarry Smith    PetscSubcommView - Views a `PetscSubcomm`
88e5acf8a4SHong Zhang 
89c3339decSBarry Smith    Collective
90e5acf8a4SHong Zhang 
91d8d19677SJose E. Roman    Input Parameters:
92811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
93811af0c4SBarry Smith -  viewer - `PetscViewer` to display the information
94e5acf8a4SHong Zhang 
95e5acf8a4SHong Zhang    Level: beginner
96811af0c4SBarry Smith 
97811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`, `PetscViewer`
98e5acf8a4SHong Zhang @*/
99d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm, PetscViewer viewer)
100d71ae5a4SJacob Faibussowitsch {
101053d1c95SHong Zhang   PetscBool         iascii;
102053d1c95SHong Zhang   PetscViewerFormat format;
103053d1c95SHong Zhang 
104053d1c95SHong Zhang   PetscFunctionBegin;
1059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
106053d1c95SHong Zhang   if (iascii) {
1079566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
108053d1c95SHong Zhang     if (format == PETSC_VIEWER_DEFAULT) {
109053d1c95SHong Zhang       MPI_Comm    comm = psubcomm->parent;
110053d1c95SHong Zhang       PetscMPIInt rank, size, subsize, subrank, duprank;
111053d1c95SHong Zhang 
1129566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
1139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "PetscSubcomm type %s with total %d MPI processes:\n", PetscSubcommTypes[psubcomm->type], size));
1149566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
1159566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(psubcomm->child, &subsize));
1169566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(psubcomm->child, &subrank));
1179566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(psubcomm->dupparent, &duprank));
1189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n", rank, psubcomm->color, subsize, subrank, duprank));
1209566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
1219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
122053d1c95SHong Zhang     }
123053d1c95SHong Zhang   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not supported yet");
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125053d1c95SHong Zhang }
126053d1c95SHong Zhang 
127a530d236SBarry Smith /*@
128811af0c4SBarry Smith   PetscSubcommSetNumber - Set total number of subcommunicators desired in the given `PetscSubcomm`
129d8a68f86SHong Zhang 
130d083f849SBarry Smith    Collective
131d8a68f86SHong Zhang 
132d8d19677SJose E. Roman    Input Parameters:
133811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
134d8a68f86SHong Zhang -  nsubcomm - the total number of subcommunicators in psubcomm
135d8a68f86SHong Zhang 
136d8a68f86SHong Zhang    Level: advanced
137d8a68f86SHong Zhang 
138811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetType()`, `PetscSubcommSetTypeGeneral()`
139d8a68f86SHong Zhang @*/
140d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetNumber(PetscSubcomm psubcomm, PetscInt nsubcomm)
141d71ae5a4SJacob Faibussowitsch {
142d8a68f86SHong Zhang   MPI_Comm    comm = psubcomm->parent;
14345487dadSJed Brown   PetscMPIInt msub, size;
144d8a68f86SHong Zhang 
145d8a68f86SHong Zhang   PetscFunctionBegin;
14628b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate() first");
1479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1489566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(nsubcomm, &msub));
149cc73adaaSBarry 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);
150d8a68f86SHong Zhang 
15145487dadSJed Brown   psubcomm->n = msub;
1523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
153d8a68f86SHong Zhang }
154d8a68f86SHong Zhang 
155a530d236SBarry Smith /*@
156811af0c4SBarry Smith   PetscSubcommSetType - Set the way the original MPI communicator is divided up in the `PetscSubcomm`
157d8a68f86SHong Zhang 
158d083f849SBarry Smith    Collective
159d8a68f86SHong Zhang 
160d8d19677SJose E. Roman    Input Parameters:
161811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
162811af0c4SBarry Smith -  subcommtype - `PetscSubcommType` `PETSC_SUBCOMM_CONTIGUOUS` or `PETSC_SUBCOMM_INTERLACED`
163d8a68f86SHong Zhang 
164d8a68f86SHong Zhang    Level: advanced
165d8a68f86SHong Zhang 
166811af0c4SBarry Smith .seealso: `PetscSubcommType`, `PETSC_SUBCOMM_CONTIGUOUS`, `PETSC_SUBCOMM_INTERLACED`,
167811af0c4SBarry Smith           `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommType`
168d8a68f86SHong Zhang @*/
169d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetType(PetscSubcomm psubcomm, PetscSubcommType subcommtype)
170d71ae5a4SJacob Faibussowitsch {
171d8a68f86SHong Zhang   PetscFunctionBegin;
17228b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate()");
17308401ef6SPierre Jolivet   PetscCheck(psubcomm->n >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()", psubcomm->n);
174d8a68f86SHong Zhang 
175d8a68f86SHong Zhang   if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
1769566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate_contiguous(psubcomm));
177d8a68f86SHong Zhang   } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
1789566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate_interlaced(psubcomm));
17998921bdaSJacob Faibussowitsch   } else SETERRQ(psubcomm->parent, PETSC_ERR_SUP, "PetscSubcommType %s is not supported yet", PetscSubcommTypes[subcommtype]);
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
181d8a68f86SHong Zhang }
182d8a68f86SHong Zhang 
183a530d236SBarry Smith /*@
184811af0c4SBarry Smith   PetscSubcommSetTypeGeneral - Divides up a communicator based on a specific user's specification
1851ba920a7SHong Zhang 
186d083f849SBarry Smith    Collective
1871ba920a7SHong Zhang 
188d8d19677SJose E. Roman    Input Parameters:
189811af0c4SBarry Smith +  psubcomm - `PetscSubcomm` context
1901ba920a7SHong Zhang .  color   - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
19165d9b8f1SHong Zhang -  subrank - rank in the subcommunicator
1921ba920a7SHong Zhang 
1931ba920a7SHong Zhang    Level: advanced
1941ba920a7SHong Zhang 
195811af0c4SBarry Smith .seealso: `PetscSubcommType`, `PETSC_SUBCOMM_CONTIGUOUS`, `PETSC_SUBCOMM_INTERLACED`, `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetType()`
1961ba920a7SHong Zhang @*/
197d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm, PetscMPIInt color, PetscMPIInt subrank)
198d71ae5a4SJacob Faibussowitsch {
1991ba920a7SHong Zhang   MPI_Comm    subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
200c9e2ceb8SHong Zhang   PetscMPIInt size, icolor, duprank, *recvbuf, sendbuf[3], mysubsize, rank, *subsize;
20145487dadSJed Brown   PetscMPIInt i, nsubcomm = psubcomm->n;
2021ba920a7SHong Zhang 
203d8a68f86SHong Zhang   PetscFunctionBegin;
20428b400f6SJacob Faibussowitsch   PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate()");
20508401ef6SPierre Jolivet   PetscCheck(nsubcomm >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()", nsubcomm);
2061ba920a7SHong Zhang 
2079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
2081ba920a7SHong Zhang 
20965d9b8f1SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
2109abe469cSDmitry 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(). */
2119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2 * size, &recvbuf));
21365d9b8f1SHong Zhang 
2149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
2159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(subcomm, &mysubsize));
21665d9b8f1SHong Zhang 
21765d9b8f1SHong Zhang   sendbuf[0] = color;
218c9e2ceb8SHong Zhang   sendbuf[1] = mysubsize;
2199566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(sendbuf, 2, MPI_INT, recvbuf, 2, MPI_INT, comm));
22065d9b8f1SHong Zhang 
2219566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nsubcomm, &subsize));
222ad540459SPierre Jolivet   for (i = 0; i < 2 * size; i += 2) subsize[recvbuf[i]] = recvbuf[i + 1];
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(recvbuf));
22465d9b8f1SHong Zhang 
22565d9b8f1SHong Zhang   duprank = 0;
226c9e2ceb8SHong Zhang   for (icolor = 0; icolor < nsubcomm; icolor++) {
22765d9b8f1SHong Zhang     if (icolor != color) { /* not color of this process */
228c9e2ceb8SHong Zhang       duprank += subsize[icolor];
22965d9b8f1SHong Zhang     } else {
23065d9b8f1SHong Zhang       duprank += subrank;
23165d9b8f1SHong Zhang       break;
23265d9b8f1SHong Zhang     }
23365d9b8f1SHong Zhang   }
2349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
23565d9b8f1SHong Zhang 
2369566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
2379566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
2389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
2399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
240a297a907SKarl Rupp 
2411ba920a7SHong Zhang   psubcomm->color   = color;
242c9e2ceb8SHong Zhang   psubcomm->subsize = subsize;
243c9e2ceb8SHong Zhang   psubcomm->type    = PETSC_SUBCOMM_GENERAL;
2443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
245d8a68f86SHong Zhang }
246638faf0bSHong Zhang 
247a530d236SBarry Smith /*@
248811af0c4SBarry Smith   PetscSubcommDestroy - Destroys a `PetscSubcomm` object
24989587e68SDave May 
250c3339decSBarry Smith    Collective
25189587e68SDave May 
25289587e68SDave May    Input Parameter:
253811af0c4SBarry Smith    .  psubcomm - the `PetscSubcomm` context
25489587e68SDave May 
25589587e68SDave May    Level: advanced
25689587e68SDave May 
257c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommSetType()`
25889587e68SDave May @*/
259d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommDestroy(PetscSubcomm *psubcomm)
260d71ae5a4SJacob Faibussowitsch {
261cd05a4c0SHong Zhang   PetscFunctionBegin;
2623ba16761SJacob Faibussowitsch   if (!*psubcomm) PetscFunctionReturn(PETSC_SUCCESS);
2639566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&(*psubcomm)->dupparent));
2649566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&(*psubcomm)->child));
2659566063dSJacob Faibussowitsch   PetscCall(PetscFree((*psubcomm)->subsize));
2669566063dSJacob Faibussowitsch   if ((*psubcomm)->subcommprefix) PetscCall(PetscFree((*psubcomm)->subcommprefix));
2679566063dSJacob Faibussowitsch   PetscCall(PetscFree((*psubcomm)));
2683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
269cd05a4c0SHong Zhang }
270cd05a4c0SHong Zhang 
271a530d236SBarry Smith /*@
272811af0c4SBarry Smith   PetscSubcommCreate - Create a `PetscSubcomm` context. This object is used to manage the division of a `MPI_Comm` into subcommunicators
273cd05a4c0SHong Zhang 
274d083f849SBarry Smith    Collective
275cd05a4c0SHong Zhang 
276cd05a4c0SHong Zhang    Input Parameter:
2779873d53eSJed Brown .  comm - MPI communicator
278cd05a4c0SHong Zhang 
279cd05a4c0SHong Zhang    Output Parameter:
280811af0c4SBarry Smith .  psubcomm - location to store the `PetscSubcomm` context
281cd05a4c0SHong Zhang 
282638faf0bSHong Zhang    Level: advanced
283cd05a4c0SHong Zhang 
284811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
285db781477SPatrick Sanan           `PetscSubcommSetNumber()`
286638faf0bSHong Zhang @*/
287d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommCreate(MPI_Comm comm, PetscSubcomm *psubcomm)
288d71ae5a4SJacob Faibussowitsch {
289d3b23db5SHong Zhang   PetscMPIInt rank, size;
290638faf0bSHong Zhang 
291638faf0bSHong Zhang   PetscFunctionBegin;
2929566063dSJacob Faibussowitsch   PetscCall(PetscNew(psubcomm));
293a297a907SKarl Rupp 
294d3b23db5SHong Zhang   /* set defaults */
2959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
2969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
297f68be91cSHong Zhang 
298d8a68f86SHong Zhang   (*psubcomm)->parent    = comm;
299d3b23db5SHong Zhang   (*psubcomm)->dupparent = comm;
300306c2d5bSBarry Smith   (*psubcomm)->child     = PETSC_COMM_SELF;
301d3b23db5SHong Zhang   (*psubcomm)->n         = size;
302d3b23db5SHong Zhang   (*psubcomm)->color     = rank;
303e37c6257SHong Zhang   (*psubcomm)->subsize   = NULL;
304d3b23db5SHong Zhang   (*psubcomm)->type      = PETSC_SUBCOMM_INTERLACED;
3053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
306638faf0bSHong Zhang }
307638faf0bSHong Zhang 
308a530d236SBarry Smith /*@C
309811af0c4SBarry Smith   PetscSubcommGetParent - Gets the communicator that was used to create the `PetscSubcomm`
310a530d236SBarry Smith 
311a530d236SBarry Smith    Collective
312a530d236SBarry Smith 
313a530d236SBarry Smith    Input Parameter:
314811af0c4SBarry Smith .  scomm - the `PetscSubcomm`
315a530d236SBarry Smith 
316a530d236SBarry Smith    Output Parameter:
317a530d236SBarry Smith .  pcomm - location to store the parent communicator
318a530d236SBarry Smith 
319a530d236SBarry Smith    Level: intermediate
320a530d236SBarry Smith 
321db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
322db781477SPatrick Sanan           `PetscSubcommSetNumber()`, `PetscSubcommGetChild()`, `PetscSubcommContiguousParent()`
323a530d236SBarry Smith @*/
324d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommGetParent(PetscSubcomm scomm, MPI_Comm *pcomm)
325d71ae5a4SJacob Faibussowitsch {
326a530d236SBarry Smith   *pcomm = PetscSubcommParent(scomm);
3273ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
328a530d236SBarry Smith }
329a530d236SBarry Smith 
330a530d236SBarry Smith /*@C
331a530d236SBarry Smith   PetscSubcommGetContiguousParent - Gets a communicator that that is a duplicate of the parent but has the ranks
332a530d236SBarry Smith                                     reordered by the order they are in the children
333a530d236SBarry Smith 
334a530d236SBarry Smith    Collective
335a530d236SBarry Smith 
336a530d236SBarry Smith    Input Parameter:
337811af0c4SBarry Smith .  scomm - the `PetscSubcomm`
338a530d236SBarry Smith 
339a530d236SBarry Smith    Output Parameter:
340a530d236SBarry Smith .  pcomm - location to store the parent communicator
341a530d236SBarry Smith 
342a530d236SBarry Smith    Level: intermediate
343a530d236SBarry Smith 
344db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
345db781477SPatrick Sanan           `PetscSubcommSetNumber()`, `PetscSubcommGetChild()`, `PetscSubcommContiguousParent()`
346a530d236SBarry Smith @*/
347d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommGetContiguousParent(PetscSubcomm scomm, MPI_Comm *pcomm)
348d71ae5a4SJacob Faibussowitsch {
349a530d236SBarry Smith   *pcomm = PetscSubcommContiguousParent(scomm);
3503ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
351a530d236SBarry Smith }
352a530d236SBarry Smith 
353a530d236SBarry Smith /*@C
354811af0c4SBarry Smith   PetscSubcommGetChild - Gets the communicator created by the `PetscSubcomm`. This is part of one of the subcommunicators created by the `PetscSubcomm`
355a530d236SBarry Smith 
356a530d236SBarry Smith    Collective
357a530d236SBarry Smith 
358a530d236SBarry Smith    Input Parameter:
359811af0c4SBarry Smith .  scomm - the `PetscSubcomm`
360a530d236SBarry Smith 
361a530d236SBarry Smith    Output Parameter:
362a530d236SBarry Smith .  ccomm - location to store the child communicator
363a530d236SBarry Smith 
364a530d236SBarry Smith    Level: intermediate
365a530d236SBarry Smith 
366db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
367db781477SPatrick Sanan           `PetscSubcommSetNumber()`, `PetscSubcommGetParent()`, `PetscSubcommContiguousParent()`
368a530d236SBarry Smith @*/
369d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommGetChild(PetscSubcomm scomm, MPI_Comm *ccomm)
370d71ae5a4SJacob Faibussowitsch {
371a530d236SBarry Smith   *ccomm = PetscSubcommChild(scomm);
3723ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
373a530d236SBarry Smith }
374a530d236SBarry Smith 
375d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)
376d71ae5a4SJacob Faibussowitsch {
377d6037b41SHong Zhang   PetscMPIInt rank, size, *subsize, duprank = -1, subrank = -1;
37845487dadSJed Brown   PetscMPIInt np_subcomm, nleftover, i, color = -1, rankstart, nsubcomm = psubcomm->n;
379d8a68f86SHong Zhang   MPI_Comm    subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
380638faf0bSHong Zhang 
381638faf0bSHong Zhang   PetscFunctionBegin;
3829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
3839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
38455e3b8d2SHong Zhang 
385638faf0bSHong Zhang   /* get size of each subcommunicator */
3869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1 + nsubcomm, &subsize));
387a297a907SKarl Rupp 
388638faf0bSHong Zhang   np_subcomm = size / nsubcomm;
389638faf0bSHong Zhang   nleftover  = size - nsubcomm * np_subcomm;
390638faf0bSHong Zhang   for (i = 0; i < nsubcomm; i++) {
391638faf0bSHong Zhang     subsize[i] = np_subcomm;
392638faf0bSHong Zhang     if (i < nleftover) subsize[i]++;
393638faf0bSHong Zhang   }
394638faf0bSHong Zhang 
395638faf0bSHong Zhang   /* get color and subrank of this proc */
396638faf0bSHong Zhang   rankstart = 0;
397638faf0bSHong Zhang   for (i = 0; i < nsubcomm; i++) {
398638faf0bSHong Zhang     if (rank >= rankstart && rank < rankstart + subsize[i]) {
399638faf0bSHong Zhang       color   = i;
400638faf0bSHong Zhang       subrank = rank - rankstart;
401638faf0bSHong Zhang       duprank = rank;
402638faf0bSHong Zhang       break;
403a297a907SKarl Rupp     } else rankstart += subsize[i];
404638faf0bSHong Zhang   }
405638faf0bSHong Zhang 
4069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
407638faf0bSHong Zhang 
408638faf0bSHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
4099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
4109566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
4119566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
4129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
4139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
414a297a907SKarl Rupp 
415d8a68f86SHong Zhang   psubcomm->color   = color;
416e37c6257SHong Zhang   psubcomm->subsize = subsize;
417f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_CONTIGUOUS;
4183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
419638faf0bSHong Zhang }
420638faf0bSHong Zhang 
421638faf0bSHong Zhang /*
422638faf0bSHong Zhang    Note:
423638faf0bSHong Zhang    In PCREDUNDANT, to avoid data scattering from subcomm back to original comm, we create subcommunicators
42445fc02eaSBarry Smith    by iteratively taking a process into a subcommunicator.
425cd05a4c0SHong Zhang    Example: size=4, nsubcomm=(*psubcomm)->n=3
426cd05a4c0SHong Zhang      comm=(*psubcomm)->parent:
427cd05a4c0SHong Zhang       rank:     [0]  [1]  [2]  [3]
428cd05a4c0SHong Zhang       color:     0    1    2    0
429cd05a4c0SHong Zhang 
430cd05a4c0SHong Zhang      subcomm=(*psubcomm)->comm:
431cd05a4c0SHong Zhang       subrank:  [0]  [0]  [0]  [1]
432cd05a4c0SHong Zhang 
433cd05a4c0SHong Zhang      dupcomm=(*psubcomm)->dupparent:
434cd05a4c0SHong Zhang       duprank:  [0]  [2]  [3]  [1]
435cd05a4c0SHong Zhang 
436cd05a4c0SHong Zhang      Here, subcomm[color = 0] has subsize=2, owns process [0] and [3]
437cd05a4c0SHong Zhang            subcomm[color = 1] has subsize=1, owns process [1]
438cd05a4c0SHong Zhang            subcomm[color = 2] has subsize=1, owns process [2]
439cd05a4c0SHong Zhang            dupcomm has same number of processes as comm, and its duprank maps
440cd05a4c0SHong Zhang            processes in subcomm contiguously into a 1d array:
441cd05a4c0SHong Zhang             duprank: [0] [1]      [2]         [3]
442cd05a4c0SHong Zhang             rank:    [0] [3]      [1]         [2]
443cd05a4c0SHong Zhang                     subcomm[0] subcomm[1]  subcomm[2]
444638faf0bSHong Zhang */
445cd05a4c0SHong Zhang 
446d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)
447d71ae5a4SJacob Faibussowitsch {
448cd05a4c0SHong Zhang   PetscMPIInt rank, size, *subsize, duprank, subrank;
44945487dadSJed Brown   PetscMPIInt np_subcomm, nleftover, i, j, color, nsubcomm = psubcomm->n;
450d8a68f86SHong Zhang   MPI_Comm    subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
451cd05a4c0SHong Zhang 
452cd05a4c0SHong Zhang   PetscFunctionBegin;
4539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
4549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
45555e3b8d2SHong Zhang 
456cd05a4c0SHong Zhang   /* get size of each subcommunicator */
4579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1 + nsubcomm, &subsize));
458a297a907SKarl Rupp 
459cd05a4c0SHong Zhang   np_subcomm = size / nsubcomm;
460cd05a4c0SHong Zhang   nleftover  = size - nsubcomm * np_subcomm;
461cd05a4c0SHong Zhang   for (i = 0; i < nsubcomm; i++) {
462cd05a4c0SHong Zhang     subsize[i] = np_subcomm;
463cd05a4c0SHong Zhang     if (i < nleftover) subsize[i]++;
464cd05a4c0SHong Zhang   }
465cd05a4c0SHong Zhang 
466cd05a4c0SHong Zhang   /* find color for this proc */
467cd05a4c0SHong Zhang   color   = rank % nsubcomm;
468cd05a4c0SHong Zhang   subrank = rank / nsubcomm;
469cd05a4c0SHong Zhang 
4709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
471cd05a4c0SHong Zhang 
4729371c9d4SSatish Balay   j       = 0;
4739371c9d4SSatish Balay   duprank = 0;
474cd05a4c0SHong Zhang   for (i = 0; i < nsubcomm; i++) {
475cd05a4c0SHong Zhang     if (j == color) {
476cd05a4c0SHong Zhang       duprank += subrank;
477cd05a4c0SHong Zhang       break;
478cd05a4c0SHong Zhang     }
4799371c9d4SSatish Balay     duprank += subsize[i];
4809371c9d4SSatish Balay     j++;
481cd05a4c0SHong Zhang   }
482cd05a4c0SHong Zhang 
483cd05a4c0SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
4849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
4859566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
4869566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
4879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
4889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
489a297a907SKarl Rupp 
490d8a68f86SHong Zhang   psubcomm->color   = color;
491e37c6257SHong Zhang   psubcomm->subsize = subsize;
492f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_INTERLACED;
4933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494cd05a4c0SHong Zhang }
495