xref: /petsc/src/sys/objects/subcomm.c (revision 1baa6e3354bfe224b33a0c158f482508792a8a6e)
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 {
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) {
4045487dadSJed Brown     case PETSC_SUBCOMM_GENERAL:
41b3a4ddeeSHong Zhang       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
4245487dadSJed Brown     case PETSC_SUBCOMM_CONTIGUOUS:
439566063dSJacob Faibussowitsch       PetscCall(PetscSubcommCreate_contiguous(psubcomm));
44f68be91cSHong Zhang       break;
4545487dadSJed Brown     case PETSC_SUBCOMM_INTERLACED:
469566063dSJacob Faibussowitsch       PetscCall(PetscSubcommCreate_interlaced(psubcomm));
47f68be91cSHong Zhang       break;
48f68be91cSHong Zhang     default:
4998921bdaSJacob 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));
54*1baa6e33SBarry Smith   if (flg) PetscCall(PetscSubcommView(psubcomm,PETSC_VIEWER_STDOUT_(psubcomm->parent)));
55d0609cedSBarry Smith   PetscOptionsEnd();
56f68be91cSHong Zhang   PetscFunctionReturn(0);
57f68be91cSHong Zhang }
58d8a68f86SHong Zhang 
59e5acf8a4SHong Zhang /*@C
60e5acf8a4SHong Zhang   PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for all
61e5acf8a4SHong Zhang   PetscSubcomm items in the options database.
62e5acf8a4SHong Zhang 
63e5acf8a4SHong Zhang   Logically collective on PetscSubcomm.
64e5acf8a4SHong Zhang 
65e5acf8a4SHong Zhang   Level: Intermediate
66e5acf8a4SHong Zhang 
67e5acf8a4SHong Zhang   Input Parameters:
68e5acf8a4SHong Zhang +   psubcomm - PetscSubcomm context
69e5acf8a4SHong Zhang -   prefix - the prefix to prepend all PetscSubcomm item names with.
70e5acf8a4SHong Zhang 
71e5acf8a4SHong Zhang @*/
72e5acf8a4SHong Zhang PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm,const char pre[])
73e5acf8a4SHong Zhang {
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));
809566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(pre,&(psubcomm->subcommprefix)));
81e5acf8a4SHong Zhang   }
82e5acf8a4SHong Zhang   PetscFunctionReturn(0);
83e5acf8a4SHong Zhang }
84e5acf8a4SHong Zhang 
85e5acf8a4SHong Zhang /*@C
8623072422SBarry Smith    PetscSubcommView - Views a PetscSubcomm of values as either ASCII text or a binary file
87e5acf8a4SHong Zhang 
88e5acf8a4SHong Zhang    Collective on PetscSubcomm
89e5acf8a4SHong Zhang 
90d8d19677SJose E. Roman    Input Parameters:
91e5acf8a4SHong Zhang +  psubcomm - PetscSubcomm context
92e5acf8a4SHong Zhang -  viewer - location to view the values
93e5acf8a4SHong Zhang 
94e5acf8a4SHong Zhang    Level: beginner
95e5acf8a4SHong Zhang @*/
96053d1c95SHong Zhang PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm,PetscViewer viewer)
97053d1c95SHong Zhang {
98053d1c95SHong Zhang   PetscBool         iascii;
99053d1c95SHong Zhang   PetscViewerFormat format;
100053d1c95SHong Zhang 
101053d1c95SHong Zhang   PetscFunctionBegin;
1029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
103053d1c95SHong Zhang   if (iascii) {
1049566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
105053d1c95SHong Zhang     if (format == PETSC_VIEWER_DEFAULT) {
106053d1c95SHong Zhang       MPI_Comm    comm=psubcomm->parent;
107053d1c95SHong Zhang       PetscMPIInt rank,size,subsize,subrank,duprank;
108053d1c95SHong Zhang 
1099566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm,&size));
1109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"PetscSubcomm type %s with total %d MPI processes:\n",PetscSubcommTypes[psubcomm->type],size));
1119566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm,&rank));
1129566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(psubcomm->child,&subsize));
1139566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(psubcomm->child,&subrank));
1149566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(psubcomm->dupparent,&duprank));
1159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer,"  [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n",rank,psubcomm->color,subsize,subrank,duprank));
1179566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
1189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
119053d1c95SHong Zhang     }
120053d1c95SHong Zhang   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported yet");
121053d1c95SHong Zhang   PetscFunctionReturn(0);
122053d1c95SHong Zhang }
123053d1c95SHong Zhang 
124a530d236SBarry Smith /*@
125d8a68f86SHong Zhang   PetscSubcommSetNumber - Set total number of subcommunicators.
126d8a68f86SHong Zhang 
127d083f849SBarry Smith    Collective
128d8a68f86SHong Zhang 
129d8d19677SJose E. Roman    Input Parameters:
130d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
131d8a68f86SHong Zhang -  nsubcomm - the total number of subcommunicators in psubcomm
132d8a68f86SHong Zhang 
133d8a68f86SHong Zhang    Level: advanced
134d8a68f86SHong Zhang 
135c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetType()`, `PetscSubcommSetTypeGeneral()`
136d8a68f86SHong Zhang @*/
1377087cfbeSBarry Smith PetscErrorCode  PetscSubcommSetNumber(PetscSubcomm psubcomm,PetscInt nsubcomm)
138d8a68f86SHong Zhang {
139d8a68f86SHong Zhang   MPI_Comm       comm=psubcomm->parent;
14045487dadSJed Brown   PetscMPIInt    msub,size;
141d8a68f86SHong Zhang 
142d8a68f86SHong Zhang   PetscFunctionBegin;
14328b400f6SJacob Faibussowitsch   PetscCheck(psubcomm,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate() first");
1449566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
1459566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(nsubcomm,&msub));
146cc73adaaSBarry 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);
147d8a68f86SHong Zhang 
14845487dadSJed Brown   psubcomm->n = msub;
149d8a68f86SHong Zhang   PetscFunctionReturn(0);
150d8a68f86SHong Zhang }
151d8a68f86SHong Zhang 
152a530d236SBarry Smith /*@
153d8a68f86SHong Zhang   PetscSubcommSetType - Set type of subcommunicators.
154d8a68f86SHong Zhang 
155d083f849SBarry Smith    Collective
156d8a68f86SHong Zhang 
157d8d19677SJose E. Roman    Input Parameters:
158d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
1591ba920a7SHong Zhang -  subcommtype - subcommunicator type, PETSC_SUBCOMM_CONTIGUOUS,PETSC_SUBCOMM_INTERLACED
160d8a68f86SHong Zhang 
161d8a68f86SHong Zhang    Level: advanced
162d8a68f86SHong Zhang 
163c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommType`
164d8a68f86SHong Zhang @*/
1657c764164SBarry Smith PetscErrorCode  PetscSubcommSetType(PetscSubcomm psubcomm,PetscSubcommType subcommtype)
166d8a68f86SHong Zhang {
167d8a68f86SHong Zhang   PetscFunctionBegin;
16828b400f6SJacob Faibussowitsch   PetscCheck(psubcomm,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
16908401ef6SPierre Jolivet   PetscCheck(psubcomm->n >= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",psubcomm->n);
170d8a68f86SHong Zhang 
171d8a68f86SHong Zhang   if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
1729566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate_contiguous(psubcomm));
173d8a68f86SHong Zhang   } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
1749566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate_interlaced(psubcomm));
17598921bdaSJacob Faibussowitsch   } else SETERRQ(psubcomm->parent,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[subcommtype]);
176d8a68f86SHong Zhang   PetscFunctionReturn(0);
177d8a68f86SHong Zhang }
178d8a68f86SHong Zhang 
179a530d236SBarry Smith /*@
18065d9b8f1SHong Zhang   PetscSubcommSetTypeGeneral - Set a PetscSubcomm from user's specifications
1811ba920a7SHong Zhang 
182d083f849SBarry Smith    Collective
1831ba920a7SHong Zhang 
184d8d19677SJose E. Roman    Input Parameters:
1851ba920a7SHong Zhang +  psubcomm - PetscSubcomm context
1861ba920a7SHong Zhang .  color   - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
18765d9b8f1SHong Zhang -  subrank - rank in the subcommunicator
1881ba920a7SHong Zhang 
1891ba920a7SHong Zhang    Level: advanced
1901ba920a7SHong Zhang 
191c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommDestroy()`, `PetscSubcommSetNumber()`, `PetscSubcommSetType()`
1921ba920a7SHong Zhang @*/
19365d9b8f1SHong Zhang PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm,PetscMPIInt color,PetscMPIInt subrank)
194d8a68f86SHong Zhang {
1951ba920a7SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
196c9e2ceb8SHong Zhang   PetscMPIInt    size,icolor,duprank,*recvbuf,sendbuf[3],mysubsize,rank,*subsize;
19745487dadSJed Brown   PetscMPIInt    i,nsubcomm=psubcomm->n;
1981ba920a7SHong Zhang 
199d8a68f86SHong Zhang   PetscFunctionBegin;
20028b400f6SJacob Faibussowitsch   PetscCheck(psubcomm,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
20108401ef6SPierre Jolivet   PetscCheck(nsubcomm >= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",nsubcomm);
2021ba920a7SHong Zhang 
2039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm,color,subrank,&subcomm));
2041ba920a7SHong Zhang 
20565d9b8f1SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
2069abe469cSDmitry 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(). */
2079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
2089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2*size,&recvbuf));
20965d9b8f1SHong Zhang 
2109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm,&rank));
2119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(subcomm,&mysubsize));
21265d9b8f1SHong Zhang 
21365d9b8f1SHong Zhang   sendbuf[0] = color;
214c9e2ceb8SHong Zhang   sendbuf[1] = mysubsize;
2159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(sendbuf,2,MPI_INT,recvbuf,2,MPI_INT,comm));
21665d9b8f1SHong Zhang 
2179566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nsubcomm,&subsize));
2189972d2ceSHong Zhang   for (i=0; i<2*size; i+=2) {
219c9e2ceb8SHong Zhang     subsize[recvbuf[i]] = recvbuf[i+1];
2201ba920a7SHong Zhang   }
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;
242d8a68f86SHong Zhang   PetscFunctionReturn(0);
243d8a68f86SHong Zhang }
244638faf0bSHong Zhang 
245a530d236SBarry Smith /*@
24689587e68SDave May   PetscSubcommDestroy - Destroys a PetscSubcomm object
24789587e68SDave May 
24889587e68SDave May    Collective on PetscSubcomm
24989587e68SDave May 
25089587e68SDave May    Input Parameter:
25189587e68SDave May    .  psubcomm - the PetscSubcomm context
25289587e68SDave May 
25389587e68SDave May    Level: advanced
25489587e68SDave May 
255c2e3fba1SPatrick Sanan .seealso: `PetscSubcommCreate()`, `PetscSubcommSetType()`
25689587e68SDave May @*/
2576bf464f9SBarry Smith PetscErrorCode  PetscSubcommDestroy(PetscSubcomm *psubcomm)
258cd05a4c0SHong Zhang {
259cd05a4c0SHong Zhang   PetscFunctionBegin;
2606bf464f9SBarry Smith   if (!*psubcomm) PetscFunctionReturn(0);
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));
2659566063dSJacob Faibussowitsch   PetscCall(PetscFree((*psubcomm)));
266cd05a4c0SHong Zhang   PetscFunctionReturn(0);
267cd05a4c0SHong Zhang }
268cd05a4c0SHong Zhang 
269a530d236SBarry Smith /*@
270cd05a4c0SHong Zhang   PetscSubcommCreate - Create a PetscSubcomm context.
271cd05a4c0SHong Zhang 
272d083f849SBarry Smith    Collective
273cd05a4c0SHong Zhang 
274cd05a4c0SHong Zhang    Input Parameter:
2759873d53eSJed Brown .  comm - MPI communicator
276cd05a4c0SHong Zhang 
277cd05a4c0SHong Zhang    Output Parameter:
278cd05a4c0SHong Zhang .  psubcomm - location to store the PetscSubcomm context
279cd05a4c0SHong Zhang 
280638faf0bSHong Zhang    Level: advanced
281cd05a4c0SHong Zhang 
282db781477SPatrick Sanan .seealso: `PetscSubcommDestroy()`, `PetscSubcommSetTypeGeneral()`, `PetscSubcommSetFromOptions()`, `PetscSubcommSetType()`,
283db781477SPatrick Sanan           `PetscSubcommSetNumber()`
284638faf0bSHong Zhang @*/
2857087cfbeSBarry Smith PetscErrorCode  PetscSubcommCreate(MPI_Comm comm,PetscSubcomm *psubcomm)
286638faf0bSHong Zhang {
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;
303638faf0bSHong Zhang   PetscFunctionReturn(0);
304638faf0bSHong Zhang }
305638faf0bSHong Zhang 
306a530d236SBarry Smith /*@C
307a530d236SBarry Smith   PetscSubcommGetParent - Gets the communicator that was used to create the PetscSubcomm
308a530d236SBarry Smith 
309a530d236SBarry Smith    Collective
310a530d236SBarry Smith 
311a530d236SBarry Smith    Input Parameter:
312a530d236SBarry 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 @*/
322a530d236SBarry Smith PetscErrorCode  PetscSubcommGetParent(PetscSubcomm scomm,MPI_Comm *pcomm)
323a530d236SBarry Smith {
324a530d236SBarry Smith   *pcomm = PetscSubcommParent(scomm);
325a530d236SBarry Smith   return 0;
326a530d236SBarry Smith }
327a530d236SBarry Smith 
328a530d236SBarry Smith /*@C
329a530d236SBarry Smith   PetscSubcommGetContiguousParent - Gets a communicator that 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:
335a530d236SBarry 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 @*/
345a530d236SBarry Smith PetscErrorCode  PetscSubcommGetContiguousParent(PetscSubcomm scomm,MPI_Comm *pcomm)
346a530d236SBarry Smith {
347a530d236SBarry Smith   *pcomm = PetscSubcommContiguousParent(scomm);
348a530d236SBarry Smith   return 0;
349a530d236SBarry Smith }
350a530d236SBarry Smith 
351a530d236SBarry Smith /*@C
352a530d236SBarry Smith   PetscSubcommGetChild - Gets the communicator created by the PetscSubcomm
353a530d236SBarry Smith 
354a530d236SBarry Smith    Collective
355a530d236SBarry Smith 
356a530d236SBarry Smith    Input Parameter:
357a530d236SBarry 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 @*/
367a530d236SBarry Smith PetscErrorCode  PetscSubcommGetChild(PetscSubcomm scomm,MPI_Comm *ccomm)
368a530d236SBarry Smith {
369a530d236SBarry Smith   *ccomm = PetscSubcommChild(scomm);
370a530d236SBarry Smith   return 0;
371a530d236SBarry Smith }
372a530d236SBarry Smith 
37395c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)
374638faf0bSHong Zhang {
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;
416638faf0bSHong Zhang   PetscFunctionReturn(0);
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 
44495c0884eSLisandro Dalcin static PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)
445cd05a4c0SHong Zhang {
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 
470cd05a4c0SHong Zhang   j = 0; duprank = 0;
471cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
472cd05a4c0SHong Zhang     if (j == color) {
473cd05a4c0SHong Zhang       duprank += subrank;
474cd05a4c0SHong Zhang       break;
475cd05a4c0SHong Zhang     }
476cd05a4c0SHong Zhang     duprank += subsize[i]; j++;
477cd05a4c0SHong Zhang   }
478cd05a4c0SHong Zhang 
479cd05a4c0SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
4809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_split(comm,0,duprank,&dupcomm));
4819566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL));
4829566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(subcomm,&psubcomm->child,NULL));
4839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&dupcomm));
4849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&subcomm));
485a297a907SKarl Rupp 
486d8a68f86SHong Zhang   psubcomm->color   = color;
487e37c6257SHong Zhang   psubcomm->subsize = subsize;
488f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_INTERLACED;
489cd05a4c0SHong Zhang   PetscFunctionReturn(0);
490cd05a4c0SHong Zhang }
491