1cd05a4c0SHong Zhang /*
2cd05a4c0SHong Zhang Provides utility routines for split MPI communicator.
3cd05a4c0SHong Zhang */
4c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/
5053d1c95SHong Zhang #include <petscviewer.h>
6cd05a4c0SHong Zhang
702c9f0b5SLisandro Dalcin const char *const PetscSubcommTypes[] = {"GENERAL", "CONTIGUOUS", "INTERLACED", "PetscSubcommType", "PETSC_SUBCOMM_", NULL};
86a6fc655SJed Brown
995c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm);
1095c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm);
11e5acf8a4SHong Zhang
12a530d236SBarry Smith /*@
13811af0c4SBarry Smith PetscSubcommSetFromOptions - Allows setting options for a `PetscSubcomm`
14e5acf8a4SHong Zhang
15c3339decSBarry Smith Collective
16e5acf8a4SHong Zhang
17e5acf8a4SHong Zhang Input Parameter:
18811af0c4SBarry Smith . psubcomm - `PetscSubcomm` context
19e5acf8a4SHong Zhang
20e5acf8a4SHong Zhang Level: beginner
21e5acf8a4SHong Zhang
22811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`
23e5acf8a4SHong Zhang @*/
PetscSubcommSetFromOptions(PetscSubcomm psubcomm)24d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetFromOptions(PetscSubcomm psubcomm)
25d71ae5a4SJacob Faibussowitsch {
2645487dadSJed Brown PetscSubcommType type;
27f68be91cSHong Zhang PetscBool flg;
28f68be91cSHong Zhang
29f68be91cSHong Zhang PetscFunctionBegin;
30aaa8cc7dSPierre Jolivet PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Must call PetscSubcommCreate first");
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) {
40d71ae5a4SJacob Faibussowitsch case PETSC_SUBCOMM_GENERAL:
41d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
42d71ae5a4SJacob Faibussowitsch case PETSC_SUBCOMM_CONTIGUOUS:
43d71ae5a4SJacob Faibussowitsch PetscCall(PetscSubcommCreate_contiguous(psubcomm));
44d71ae5a4SJacob Faibussowitsch break;
45d71ae5a4SJacob Faibussowitsch case PETSC_SUBCOMM_INTERLACED:
46d71ae5a4SJacob Faibussowitsch PetscCall(PetscSubcommCreate_interlaced(psubcomm));
47d71ae5a4SJacob Faibussowitsch break;
48d71ae5a4SJacob Faibussowitsch default:
49d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscSubcommType %s is not supported yet", PetscSubcommTypes[type]);
50f68be91cSHong Zhang }
51f68be91cSHong Zhang }
5219171117SHong Zhang
539566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-psubcomm_view", "Triggers display of PetscSubcomm context", "PetscSubcommView", &flg));
541baa6e33SBarry Smith if (flg) PetscCall(PetscSubcommView(psubcomm, PETSC_VIEWER_STDOUT_(psubcomm->parent)));
55d0609cedSBarry Smith PetscOptionsEnd();
563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
57f68be91cSHong Zhang }
58d8a68f86SHong Zhang
59cc4c1da9SBarry Smith /*@
60811af0c4SBarry Smith PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for options in the options database for this object
61e5acf8a4SHong Zhang
6220f4b53cSBarry Smith Logically Collective
63e5acf8a4SHong Zhang
64aec76313SJacob Faibussowitsch Level: intermediate
65e5acf8a4SHong Zhang
66e5acf8a4SHong Zhang Input Parameters:
67811af0c4SBarry Smith + psubcomm - `PetscSubcomm` context
68aec76313SJacob Faibussowitsch - pre - the prefix to prepend all `PetscSubcomm` item names with.
69e5acf8a4SHong Zhang
70811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`
71e5acf8a4SHong Zhang @*/
PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm,const char pre[])72d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm, const char pre[])
73d71ae5a4SJacob Faibussowitsch {
74e5acf8a4SHong Zhang PetscFunctionBegin;
75e5acf8a4SHong Zhang if (!pre) {
769566063dSJacob Faibussowitsch PetscCall(PetscFree(psubcomm->subcommprefix));
77e5acf8a4SHong Zhang } else {
78cc73adaaSBarry Smith PetscCheck(pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
799566063dSJacob Faibussowitsch PetscCall(PetscFree(psubcomm->subcommprefix));
80f4f49eeaSPierre Jolivet PetscCall(PetscStrallocpy(pre, &psubcomm->subcommprefix));
81e5acf8a4SHong Zhang }
823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
83e5acf8a4SHong Zhang }
84e5acf8a4SHong Zhang
85ffeef943SBarry Smith /*@
86811af0c4SBarry Smith PetscSubcommView - Views a `PetscSubcomm`
87e5acf8a4SHong Zhang
88c3339decSBarry Smith Collective
89e5acf8a4SHong Zhang
90d8d19677SJose E. Roman Input Parameters:
91811af0c4SBarry Smith + psubcomm - `PetscSubcomm` context
92811af0c4SBarry Smith - viewer - `PetscViewer` to display the information
93e5acf8a4SHong Zhang
94e5acf8a4SHong Zhang Level: beginner
95811af0c4SBarry Smith
96811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`, `PetscViewer`
97e5acf8a4SHong Zhang @*/
PetscSubcommView(PetscSubcomm psubcomm,PetscViewer viewer)98d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm, PetscViewer viewer)
99d71ae5a4SJacob Faibussowitsch {
1009f196a02SMartin Diehl PetscBool isascii;
101053d1c95SHong Zhang PetscViewerFormat format;
102053d1c95SHong Zhang
103053d1c95SHong Zhang PetscFunctionBegin;
1049f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
105*966bd95aSPierre Jolivet PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not supported yet");
1069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format));
107053d1c95SHong Zhang if (format == PETSC_VIEWER_DEFAULT) {
108053d1c95SHong Zhang MPI_Comm comm = psubcomm->parent;
109053d1c95SHong Zhang PetscMPIInt rank, size, subsize, subrank, duprank;
110053d1c95SHong Zhang
1119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
1129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PetscSubcomm type %s with total %d MPI processes:\n", PetscSubcommTypes[psubcomm->type], size));
1139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
1149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(psubcomm->child, &subsize));
1159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(psubcomm->child, &subrank));
1169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(psubcomm->dupparent, &duprank));
1179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n", rank, psubcomm->color, subsize, subrank, duprank));
1199566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer));
1209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer));
121053d1c95SHong Zhang }
1223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
123053d1c95SHong Zhang }
124053d1c95SHong Zhang
125a530d236SBarry Smith /*@
126811af0c4SBarry Smith PetscSubcommSetNumber - Set total number of subcommunicators desired in the given `PetscSubcomm`
127d8a68f86SHong Zhang
128d083f849SBarry Smith Collective
129d8a68f86SHong Zhang
130d8d19677SJose E. Roman Input Parameters:
131811af0c4SBarry Smith + psubcomm - `PetscSubcomm` context
132d8a68f86SHong Zhang - nsubcomm - the total number of subcommunicators in psubcomm
133d8a68f86SHong Zhang
134d8a68f86SHong Zhang Level: advanced
135d8a68f86SHong Zhang
136811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetType()`, `PetscSubcommSetTypeGeneral()`
137d8a68f86SHong Zhang @*/
PetscSubcommSetNumber(PetscSubcomm psubcomm,PetscInt nsubcomm)138d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetNumber(PetscSubcomm psubcomm, PetscInt nsubcomm)
139d71ae5a4SJacob Faibussowitsch {
140d8a68f86SHong Zhang MPI_Comm comm = psubcomm->parent;
14145487dadSJed Brown PetscMPIInt msub, size;
142d8a68f86SHong Zhang
143d8a68f86SHong Zhang PetscFunctionBegin;
14428b400f6SJacob Faibussowitsch PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate() first");
1459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
1469566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(nsubcomm, &msub));
147cc73adaaSBarry 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);
148d8a68f86SHong Zhang
14945487dadSJed Brown psubcomm->n = msub;
1503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
151d8a68f86SHong Zhang }
152d8a68f86SHong Zhang
153a530d236SBarry Smith /*@
154811af0c4SBarry Smith PetscSubcommSetType - Set the way the original MPI communicator is divided up in the `PetscSubcomm`
155d8a68f86SHong Zhang
156d083f849SBarry Smith Collective
157d8a68f86SHong Zhang
158d8d19677SJose E. Roman Input Parameters:
159811af0c4SBarry Smith + psubcomm - `PetscSubcomm` context
160811af0c4SBarry Smith - subcommtype - `PetscSubcommType` `PETSC_SUBCOMM_CONTIGUOUS` or `PETSC_SUBCOMM_INTERLACED`
161d8a68f86SHong Zhang
162d8a68f86SHong Zhang Level: advanced
163d8a68f86SHong Zhang
164811af0c4SBarry Smith .seealso: `PetscSubcommType`, `PETSC_SUBCOMM_CONTIGUOUS`, `PETSC_SUBCOMM_INTERLACED`,
165aec76313SJacob Faibussowitsch `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetTypeGeneral()`
166d8a68f86SHong Zhang @*/
PetscSubcommSetType(PetscSubcomm psubcomm,PetscSubcommType subcommtype)167d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetType(PetscSubcomm psubcomm, PetscSubcommType subcommtype)
168d71ae5a4SJacob Faibussowitsch {
169d8a68f86SHong Zhang PetscFunctionBegin;
17028b400f6SJacob Faibussowitsch PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate()");
17108401ef6SPierre Jolivet PetscCheck(psubcomm->n >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()", psubcomm->n);
172d8a68f86SHong Zhang
173d8a68f86SHong Zhang if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
1749566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate_contiguous(psubcomm));
175d8a68f86SHong Zhang } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
1769566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate_interlaced(psubcomm));
17798921bdaSJacob Faibussowitsch } else SETERRQ(psubcomm->parent, PETSC_ERR_SUP, "PetscSubcommType %s is not supported yet", PetscSubcommTypes[subcommtype]);
1783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
179d8a68f86SHong Zhang }
180d8a68f86SHong Zhang
181a530d236SBarry Smith /*@
182811af0c4SBarry Smith PetscSubcommSetTypeGeneral - Divides up a communicator based on a specific user's specification
1831ba920a7SHong Zhang
184d083f849SBarry Smith Collective
1851ba920a7SHong Zhang
186d8d19677SJose E. Roman Input Parameters:
187811af0c4SBarry Smith + psubcomm - `PetscSubcomm` context
1881ba920a7SHong Zhang . color - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
18965d9b8f1SHong Zhang - subrank - rank in the subcommunicator
1901ba920a7SHong Zhang
1911ba920a7SHong Zhang Level: advanced
1921ba920a7SHong Zhang
193811af0c4SBarry Smith .seealso: `PetscSubcommType`, `PETSC_SUBCOMM_CONTIGUOUS`, `PETSC_SUBCOMM_INTERLACED`, `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetType()`
1941ba920a7SHong Zhang @*/
PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm,PetscMPIInt color,PetscMPIInt subrank)195d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm, PetscMPIInt color, PetscMPIInt subrank)
196d71ae5a4SJacob Faibussowitsch {
1971ba920a7SHong Zhang MPI_Comm subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
198c9e2ceb8SHong Zhang PetscMPIInt size, icolor, duprank, *recvbuf, sendbuf[3], mysubsize, rank, *subsize;
19945487dadSJed Brown PetscMPIInt i, nsubcomm = psubcomm->n;
2001ba920a7SHong Zhang
201d8a68f86SHong Zhang PetscFunctionBegin;
20228b400f6SJacob Faibussowitsch PetscCheck(psubcomm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "PetscSubcomm is not created. Call PetscSubcommCreate()");
20308401ef6SPierre Jolivet PetscCheck(nsubcomm >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()", nsubcomm);
2041ba920a7SHong Zhang
2059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
2061ba920a7SHong Zhang
20765d9b8f1SHong Zhang /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
2089abe469cSDmitry 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(). */
2099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
2109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * size, &recvbuf));
21165d9b8f1SHong Zhang
2129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
2139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(subcomm, &mysubsize));
21465d9b8f1SHong Zhang
21565d9b8f1SHong Zhang sendbuf[0] = color;
216c9e2ceb8SHong Zhang sendbuf[1] = mysubsize;
2179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(sendbuf, 2, MPI_INT, recvbuf, 2, MPI_INT, comm));
21865d9b8f1SHong Zhang
2199566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nsubcomm, &subsize));
220ad540459SPierre Jolivet for (i = 0; i < 2 * size; i += 2) subsize[recvbuf[i]] = recvbuf[i + 1];
2219566063dSJacob Faibussowitsch PetscCall(PetscFree(recvbuf));
22265d9b8f1SHong Zhang
22365d9b8f1SHong Zhang duprank = 0;
224c9e2ceb8SHong Zhang for (icolor = 0; icolor < nsubcomm; icolor++) {
22565d9b8f1SHong Zhang if (icolor != color) { /* not color of this process */
226c9e2ceb8SHong Zhang duprank += subsize[icolor];
22765d9b8f1SHong Zhang } else {
22865d9b8f1SHong Zhang duprank += subrank;
22965d9b8f1SHong Zhang break;
23065d9b8f1SHong Zhang }
23165d9b8f1SHong Zhang }
2329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
23365d9b8f1SHong Zhang
2349566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
2359566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
2369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&dupcomm));
2379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&subcomm));
238a297a907SKarl Rupp
2391ba920a7SHong Zhang psubcomm->color = color;
240c9e2ceb8SHong Zhang psubcomm->subsize = subsize;
241c9e2ceb8SHong Zhang psubcomm->type = PETSC_SUBCOMM_GENERAL;
2423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
243d8a68f86SHong Zhang }
244638faf0bSHong Zhang
245a530d236SBarry Smith /*@
246811af0c4SBarry Smith PetscSubcommDestroy - Destroys a `PetscSubcomm` object
24789587e68SDave May
248c3339decSBarry Smith Collective
24989587e68SDave May
25089587e68SDave May Input Parameter:
251811af0c4SBarry Smith . psubcomm - the `PetscSubcomm` context
25289587e68SDave May
25389587e68SDave May Level: advanced
25489587e68SDave May
255c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommSetType()`
25689587e68SDave May @*/
PetscSubcommDestroy(PetscSubcomm * psubcomm)257d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommDestroy(PetscSubcomm *psubcomm)
258d71ae5a4SJacob Faibussowitsch {
259cd05a4c0SHong Zhang PetscFunctionBegin;
2603ba16761SJacob Faibussowitsch if (!*psubcomm) PetscFunctionReturn(PETSC_SUCCESS);
2619566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&(*psubcomm)->dupparent));
2629566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&(*psubcomm)->child));
2639566063dSJacob Faibussowitsch PetscCall(PetscFree((*psubcomm)->subsize));
2649566063dSJacob Faibussowitsch if ((*psubcomm)->subcommprefix) PetscCall(PetscFree((*psubcomm)->subcommprefix));
265f4f49eeaSPierre Jolivet PetscCall(PetscFree(*psubcomm));
2663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
267cd05a4c0SHong Zhang }
268cd05a4c0SHong Zhang
269a530d236SBarry Smith /*@
270811af0c4SBarry Smith PetscSubcommCreate - Create a `PetscSubcomm` context. This object is used to manage the division of a `MPI_Comm` into subcommunicators
271cd05a4c0SHong Zhang
272d083f849SBarry Smith Collective
273cd05a4c0SHong Zhang
274cd05a4c0SHong Zhang Input Parameter:
2759873d53eSJed Brown . comm - MPI communicator
276cd05a4c0SHong Zhang
277cd05a4c0SHong Zhang Output Parameter:
278811af0c4SBarry Smith . psubcomm - location to store the `PetscSubcomm` context
279cd05a4c0SHong Zhang
280638faf0bSHong Zhang Level: advanced
281cd05a4c0SHong Zhang
282811af0c4SBarry Smith .seealso: `PetscSubcomm`, `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
283db781477SPatrick Sanan `PetscSubcommSetNumber()`
284638faf0bSHong Zhang @*/
PetscSubcommCreate(MPI_Comm comm,PetscSubcomm * psubcomm)285d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommCreate(MPI_Comm comm, PetscSubcomm *psubcomm)
286d71ae5a4SJacob Faibussowitsch {
287d3b23db5SHong Zhang PetscMPIInt rank, size;
288638faf0bSHong Zhang
289638faf0bSHong Zhang PetscFunctionBegin;
2909566063dSJacob Faibussowitsch PetscCall(PetscNew(psubcomm));
291a297a907SKarl Rupp
292d3b23db5SHong Zhang /* set defaults */
2939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
2949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
295f68be91cSHong Zhang
296d8a68f86SHong Zhang (*psubcomm)->parent = comm;
297d3b23db5SHong Zhang (*psubcomm)->dupparent = comm;
298306c2d5bSBarry Smith (*psubcomm)->child = PETSC_COMM_SELF;
299d3b23db5SHong Zhang (*psubcomm)->n = size;
300d3b23db5SHong Zhang (*psubcomm)->color = rank;
301e37c6257SHong Zhang (*psubcomm)->subsize = NULL;
302d3b23db5SHong Zhang (*psubcomm)->type = PETSC_SUBCOMM_INTERLACED;
3033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
304638faf0bSHong Zhang }
305638faf0bSHong Zhang
306a530d236SBarry Smith /*@C
307811af0c4SBarry Smith PetscSubcommGetParent - Gets the communicator that was used to create the `PetscSubcomm`
308a530d236SBarry Smith
309a530d236SBarry Smith Collective
310a530d236SBarry Smith
311a530d236SBarry Smith Input Parameter:
312811af0c4SBarry Smith . scomm - the `PetscSubcomm`
313a530d236SBarry Smith
314a530d236SBarry Smith Output Parameter:
315a530d236SBarry Smith . pcomm - location to store the parent communicator
316a530d236SBarry Smith
317a530d236SBarry Smith Level: intermediate
318a530d236SBarry Smith
319db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
320db781477SPatrick Sanan `PetscSubcommSetNumber()`, `PetscSubcommGetChild()`, `PetscSubcommContiguousParent()`
321a530d236SBarry Smith @*/
PetscSubcommGetParent(PetscSubcomm scomm,MPI_Comm * pcomm)322d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommGetParent(PetscSubcomm scomm, MPI_Comm *pcomm)
323d71ae5a4SJacob Faibussowitsch {
324a530d236SBarry Smith *pcomm = PetscSubcommParent(scomm);
3253ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
326a530d236SBarry Smith }
327a530d236SBarry Smith
328a530d236SBarry Smith /*@C
32915229ffcSPierre Jolivet PetscSubcommGetContiguousParent - Gets a communicator that is a duplicate of the parent but has the ranks
330a530d236SBarry Smith reordered by the order they are in the children
331a530d236SBarry Smith
332a530d236SBarry Smith Collective
333a530d236SBarry Smith
334a530d236SBarry Smith Input Parameter:
335811af0c4SBarry Smith . scomm - the `PetscSubcomm`
336a530d236SBarry Smith
337a530d236SBarry Smith Output Parameter:
338a530d236SBarry Smith . pcomm - location to store the parent communicator
339a530d236SBarry Smith
340a530d236SBarry Smith Level: intermediate
341a530d236SBarry Smith
342db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
343db781477SPatrick Sanan `PetscSubcommSetNumber()`, `PetscSubcommGetChild()`, `PetscSubcommContiguousParent()`
344a530d236SBarry Smith @*/
PetscSubcommGetContiguousParent(PetscSubcomm scomm,MPI_Comm * pcomm)345d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommGetContiguousParent(PetscSubcomm scomm, MPI_Comm *pcomm)
346d71ae5a4SJacob Faibussowitsch {
347a530d236SBarry Smith *pcomm = PetscSubcommContiguousParent(scomm);
3483ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
349a530d236SBarry Smith }
350a530d236SBarry Smith
351a530d236SBarry Smith /*@C
352811af0c4SBarry Smith PetscSubcommGetChild - Gets the communicator created by the `PetscSubcomm`. This is part of one of the subcommunicators created by the `PetscSubcomm`
353a530d236SBarry Smith
354a530d236SBarry Smith Collective
355a530d236SBarry Smith
356a530d236SBarry Smith Input Parameter:
357811af0c4SBarry Smith . scomm - the `PetscSubcomm`
358a530d236SBarry Smith
359a530d236SBarry Smith Output Parameter:
360a530d236SBarry Smith . ccomm - location to store the child communicator
361a530d236SBarry Smith
362a530d236SBarry Smith Level: intermediate
363a530d236SBarry Smith
364db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
365db781477SPatrick Sanan `PetscSubcommSetNumber()`, `PetscSubcommGetParent()`, `PetscSubcommContiguousParent()`
366a530d236SBarry Smith @*/
PetscSubcommGetChild(PetscSubcomm scomm,MPI_Comm * ccomm)367d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSubcommGetChild(PetscSubcomm scomm, MPI_Comm *ccomm)
368d71ae5a4SJacob Faibussowitsch {
369a530d236SBarry Smith *ccomm = PetscSubcommChild(scomm);
3703ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
371a530d236SBarry Smith }
372a530d236SBarry Smith
PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)373d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)
374d71ae5a4SJacob Faibussowitsch {
375d6037b41SHong Zhang PetscMPIInt rank, size, *subsize, duprank = -1, subrank = -1;
37645487dadSJed Brown PetscMPIInt np_subcomm, nleftover, i, color = -1, rankstart, nsubcomm = psubcomm->n;
377d8a68f86SHong Zhang MPI_Comm subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
378638faf0bSHong Zhang
379638faf0bSHong Zhang PetscFunctionBegin;
3809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
3819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
38255e3b8d2SHong Zhang
383638faf0bSHong Zhang /* get size of each subcommunicator */
3849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1 + nsubcomm, &subsize));
385a297a907SKarl Rupp
386638faf0bSHong Zhang np_subcomm = size / nsubcomm;
387638faf0bSHong Zhang nleftover = size - nsubcomm * np_subcomm;
388638faf0bSHong Zhang for (i = 0; i < nsubcomm; i++) {
389638faf0bSHong Zhang subsize[i] = np_subcomm;
390638faf0bSHong Zhang if (i < nleftover) subsize[i]++;
391638faf0bSHong Zhang }
392638faf0bSHong Zhang
393638faf0bSHong Zhang /* get color and subrank of this proc */
394638faf0bSHong Zhang rankstart = 0;
395638faf0bSHong Zhang for (i = 0; i < nsubcomm; i++) {
396638faf0bSHong Zhang if (rank >= rankstart && rank < rankstart + subsize[i]) {
397638faf0bSHong Zhang color = i;
398638faf0bSHong Zhang subrank = rank - rankstart;
399638faf0bSHong Zhang duprank = rank;
400638faf0bSHong Zhang break;
401a297a907SKarl Rupp } else rankstart += subsize[i];
402638faf0bSHong Zhang }
403638faf0bSHong Zhang
4049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
405638faf0bSHong Zhang
406638faf0bSHong Zhang /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
4079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
4089566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
4099566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
4109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&dupcomm));
4119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&subcomm));
412a297a907SKarl Rupp
413d8a68f86SHong Zhang psubcomm->color = color;
414e37c6257SHong Zhang psubcomm->subsize = subsize;
415f38d543fSHong Zhang psubcomm->type = PETSC_SUBCOMM_CONTIGUOUS;
4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
417638faf0bSHong Zhang }
418638faf0bSHong Zhang
419638faf0bSHong Zhang /*
420638faf0bSHong Zhang Note:
421638faf0bSHong Zhang In PCREDUNDANT, to avoid data scattering from subcomm back to original comm, we create subcommunicators
42245fc02eaSBarry Smith by iteratively taking a process into a subcommunicator.
423cd05a4c0SHong Zhang Example: size=4, nsubcomm=(*psubcomm)->n=3
424cd05a4c0SHong Zhang comm=(*psubcomm)->parent:
425cd05a4c0SHong Zhang rank: [0] [1] [2] [3]
426cd05a4c0SHong Zhang color: 0 1 2 0
427cd05a4c0SHong Zhang
428cd05a4c0SHong Zhang subcomm=(*psubcomm)->comm:
429cd05a4c0SHong Zhang subrank: [0] [0] [0] [1]
430cd05a4c0SHong Zhang
431cd05a4c0SHong Zhang dupcomm=(*psubcomm)->dupparent:
432cd05a4c0SHong Zhang duprank: [0] [2] [3] [1]
433cd05a4c0SHong Zhang
434cd05a4c0SHong Zhang Here, subcomm[color = 0] has subsize=2, owns process [0] and [3]
435cd05a4c0SHong Zhang subcomm[color = 1] has subsize=1, owns process [1]
436cd05a4c0SHong Zhang subcomm[color = 2] has subsize=1, owns process [2]
437cd05a4c0SHong Zhang dupcomm has same number of processes as comm, and its duprank maps
438cd05a4c0SHong Zhang processes in subcomm contiguously into a 1d array:
439cd05a4c0SHong Zhang duprank: [0] [1] [2] [3]
440cd05a4c0SHong Zhang rank: [0] [3] [1] [2]
441cd05a4c0SHong Zhang subcomm[0] subcomm[1] subcomm[2]
442638faf0bSHong Zhang */
443cd05a4c0SHong Zhang
PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)444d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)
445d71ae5a4SJacob Faibussowitsch {
446cd05a4c0SHong Zhang PetscMPIInt rank, size, *subsize, duprank, subrank;
44745487dadSJed Brown PetscMPIInt np_subcomm, nleftover, i, j, color, nsubcomm = psubcomm->n;
448d8a68f86SHong Zhang MPI_Comm subcomm = 0, dupcomm = 0, comm = psubcomm->parent;
449cd05a4c0SHong Zhang
450cd05a4c0SHong Zhang PetscFunctionBegin;
4519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
4529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
45355e3b8d2SHong Zhang
454cd05a4c0SHong Zhang /* get size of each subcommunicator */
4559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1 + nsubcomm, &subsize));
456a297a907SKarl Rupp
457cd05a4c0SHong Zhang np_subcomm = size / nsubcomm;
458cd05a4c0SHong Zhang nleftover = size - nsubcomm * np_subcomm;
459cd05a4c0SHong Zhang for (i = 0; i < nsubcomm; i++) {
460cd05a4c0SHong Zhang subsize[i] = np_subcomm;
461cd05a4c0SHong Zhang if (i < nleftover) subsize[i]++;
462cd05a4c0SHong Zhang }
463cd05a4c0SHong Zhang
464cd05a4c0SHong Zhang /* find color for this proc */
465cd05a4c0SHong Zhang color = rank % nsubcomm;
466cd05a4c0SHong Zhang subrank = rank / nsubcomm;
467cd05a4c0SHong Zhang
4689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split(comm, color, subrank, &subcomm));
469cd05a4c0SHong Zhang
4709371c9d4SSatish Balay j = 0;
4719371c9d4SSatish Balay duprank = 0;
472cd05a4c0SHong Zhang for (i = 0; i < nsubcomm; i++) {
473cd05a4c0SHong Zhang if (j == color) {
474cd05a4c0SHong Zhang duprank += subrank;
475cd05a4c0SHong Zhang break;
476cd05a4c0SHong Zhang }
4779371c9d4SSatish Balay duprank += subsize[i];
4789371c9d4SSatish Balay j++;
479cd05a4c0SHong Zhang }
480cd05a4c0SHong Zhang
481cd05a4c0SHong Zhang /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
4829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split(comm, 0, duprank, &dupcomm));
4839566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(dupcomm, &psubcomm->dupparent, NULL));
4849566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(subcomm, &psubcomm->child, NULL));
4859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&dupcomm));
4869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&subcomm));
487a297a907SKarl Rupp
488d8a68f86SHong Zhang psubcomm->color = color;
489e37c6257SHong Zhang psubcomm->subsize = subsize;
490f38d543fSHong Zhang psubcomm->type = PETSC_SUBCOMM_INTERLACED;
4913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
492cd05a4c0SHong Zhang }
493