xref: /petsc/src/sys/objects/subcomm.c (revision 89587e68d01593b4eae63e3441d5153dad64e45b)
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 
86a6fc655SJed Brown const char *const PetscSubcommTypes[] = {"GENERAL","CONTIGUOUS","INTERLACED","PetscSubcommType","PETSC_SUBCOMM_",0};
96a6fc655SJed Brown 
10d8a68f86SHong Zhang extern PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm);
11d8a68f86SHong Zhang extern PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm);
12e5acf8a4SHong Zhang 
13f68be91cSHong Zhang #undef __FUNCT__
14f68be91cSHong Zhang #define __FUNCT__ "PetscSubcommSetFromOptions"
15e5acf8a4SHong Zhang /*@C
16e5acf8a4SHong Zhang    PetscSubcommSetFromOptions - Allows setting options from a PetscSubcomm
17e5acf8a4SHong Zhang 
18e5acf8a4SHong Zhang    Collective on PetscSubcomm
19e5acf8a4SHong Zhang 
20e5acf8a4SHong Zhang    Input Parameter:
21e5acf8a4SHong Zhang .  psubcomm - PetscSubcomm context
22e5acf8a4SHong Zhang 
23e5acf8a4SHong Zhang    Level: beginner
24e5acf8a4SHong Zhang 
25e5acf8a4SHong Zhang @*/
26f68be91cSHong Zhang PetscErrorCode PetscSubcommSetFromOptions(PetscSubcomm psubcomm)
27f68be91cSHong Zhang {
28f68be91cSHong Zhang   PetscErrorCode   ierr;
2945487dadSJed Brown   PetscSubcommType type;
30f68be91cSHong Zhang   PetscBool        flg;
31f68be91cSHong Zhang 
32f68be91cSHong Zhang   PetscFunctionBegin;
33f68be91cSHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Must call PetscSubcommCreate firt");
3460f5f21cSHong Zhang 
35e5acf8a4SHong Zhang   ierr = PetscOptionsBegin(psubcomm->parent,psubcomm->subcommprefix,"Options for PetscSubcomm",NULL);CHKERRQ(ierr);
3660f5f21cSHong Zhang   ierr = PetscOptionsEnum("-psubcomm_type",NULL,NULL,PetscSubcommTypes,(PetscEnum)psubcomm->type,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
37f68be91cSHong Zhang   if (flg && psubcomm->type != type) {
38f68be91cSHong Zhang     /* free old structures */
39f68be91cSHong Zhang     ierr = PetscCommDestroy(&(psubcomm)->dupparent);CHKERRQ(ierr);
40306c2d5bSBarry Smith     ierr = PetscCommDestroy(&(psubcomm)->child);CHKERRQ(ierr);
41f68be91cSHong Zhang     ierr = PetscFree((psubcomm)->subsize);CHKERRQ(ierr);
42f68be91cSHong Zhang     switch (type) {
4345487dadSJed Brown     case PETSC_SUBCOMM_GENERAL:
44b3a4ddeeSHong Zhang       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Runtime option PETSC_SUBCOMM_GENERAL is not supported, use PetscSubcommSetTypeGeneral()");
4545487dadSJed Brown     case PETSC_SUBCOMM_CONTIGUOUS:
46f68be91cSHong Zhang       ierr = PetscSubcommCreate_contiguous(psubcomm);CHKERRQ(ierr);
47f68be91cSHong Zhang       break;
4845487dadSJed Brown     case PETSC_SUBCOMM_INTERLACED:
49f68be91cSHong Zhang       ierr = PetscSubcommCreate_interlaced(psubcomm);CHKERRQ(ierr);
50f68be91cSHong Zhang       break;
51f68be91cSHong Zhang     default:
5245487dadSJed Brown       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[type]);
53f68be91cSHong Zhang     }
54f68be91cSHong Zhang   }
5519171117SHong Zhang 
5660f5f21cSHong Zhang   ierr = PetscOptionsName("-psubcomm_view","Triggers display of PetscSubcomm context","PetscSubcommView",&flg);CHKERRQ(ierr);
5719171117SHong Zhang   if (flg) {
5819171117SHong Zhang     ierr = PetscSubcommView(psubcomm,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
5919171117SHong Zhang   }
6060f5f21cSHong Zhang   ierr = PetscOptionsEnd();CHKERRQ(ierr);
61f68be91cSHong Zhang   PetscFunctionReturn(0);
62f68be91cSHong Zhang }
63d8a68f86SHong Zhang 
64d8a68f86SHong Zhang #undef __FUNCT__
65e5acf8a4SHong Zhang #define __FUNCT__ "PetscSubcommSetOptionsPrefix"
66e5acf8a4SHong Zhang /*@C
67e5acf8a4SHong Zhang   PetscSubcommSetOptionsPrefix - Sets the prefix used for searching for all
68e5acf8a4SHong Zhang   PetscSubcomm items in the options database.
69e5acf8a4SHong Zhang 
70e5acf8a4SHong Zhang   Logically collective on PetscSubcomm.
71e5acf8a4SHong Zhang 
72e5acf8a4SHong Zhang   Level: Intermediate
73e5acf8a4SHong Zhang 
74e5acf8a4SHong Zhang   Input Parameters:
75e5acf8a4SHong Zhang +   psubcomm - PetscSubcomm context
76e5acf8a4SHong Zhang -   prefix - the prefix to prepend all PetscSubcomm item names with.
77e5acf8a4SHong Zhang 
78e5acf8a4SHong Zhang @*/
79e5acf8a4SHong Zhang PetscErrorCode PetscSubcommSetOptionsPrefix(PetscSubcomm psubcomm,const char pre[])
80e5acf8a4SHong Zhang {
81e5acf8a4SHong Zhang   PetscErrorCode   ierr;
82e5acf8a4SHong Zhang 
83e5acf8a4SHong Zhang   PetscFunctionBegin;
84e5acf8a4SHong Zhang    if (!pre) {
85e5acf8a4SHong Zhang     ierr = PetscFree(psubcomm->subcommprefix);CHKERRQ(ierr);
86e5acf8a4SHong Zhang   } else {
87e5acf8a4SHong Zhang     if (pre[0] == '-') SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hypen");
88e5acf8a4SHong Zhang     ierr = PetscFree(psubcomm->subcommprefix);CHKERRQ(ierr);
89e5acf8a4SHong Zhang     ierr = PetscStrallocpy(pre,&(psubcomm->subcommprefix));CHKERRQ(ierr);
90e5acf8a4SHong Zhang   }
91e5acf8a4SHong Zhang   PetscFunctionReturn(0);
92e5acf8a4SHong Zhang }
93e5acf8a4SHong Zhang 
94e5acf8a4SHong Zhang #undef __FUNCT__
95053d1c95SHong Zhang #define __FUNCT__ "PetscSubcommView"
96e5acf8a4SHong Zhang /*@C
97e5acf8a4SHong Zhang    PetsSubcommcView - Views a PetscSubcomm of values as either ASCII text or a binary file
98e5acf8a4SHong Zhang 
99e5acf8a4SHong Zhang    Collective on PetscSubcomm
100e5acf8a4SHong Zhang 
101e5acf8a4SHong Zhang    Input Parameter:
102e5acf8a4SHong Zhang +  psubcomm - PetscSubcomm context
103e5acf8a4SHong Zhang -  viewer - location to view the values
104e5acf8a4SHong Zhang 
105e5acf8a4SHong Zhang    Level: beginner
106e5acf8a4SHong Zhang @*/
107053d1c95SHong Zhang PetscErrorCode PetscSubcommView(PetscSubcomm psubcomm,PetscViewer viewer)
108053d1c95SHong Zhang {
109053d1c95SHong Zhang   PetscErrorCode    ierr;
110053d1c95SHong Zhang   PetscBool         iascii;
111053d1c95SHong Zhang   PetscViewerFormat format;
112053d1c95SHong Zhang 
113053d1c95SHong Zhang   PetscFunctionBegin;
114053d1c95SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
115053d1c95SHong Zhang   if (iascii) {
116053d1c95SHong Zhang     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
117053d1c95SHong Zhang     if (format == PETSC_VIEWER_DEFAULT) {
118053d1c95SHong Zhang       MPI_Comm    comm=psubcomm->parent;
119053d1c95SHong Zhang       PetscMPIInt rank,size,subsize,subrank,duprank;
120053d1c95SHong Zhang 
121053d1c95SHong Zhang       ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
12245487dadSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"PetscSubcomm type %s with total %d MPI processes:\n",PetscSubcommTypes[psubcomm->type],size);CHKERRQ(ierr);
123053d1c95SHong Zhang       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
124306c2d5bSBarry Smith       ierr = MPI_Comm_size(psubcomm->child,&subsize);CHKERRQ(ierr);
125306c2d5bSBarry Smith       ierr = MPI_Comm_rank(psubcomm->child,&subrank);CHKERRQ(ierr);
126053d1c95SHong Zhang       ierr = MPI_Comm_rank(psubcomm->dupparent,&duprank);CHKERRQ(ierr);
127302440fdSBarry Smith       ierr = PetscSynchronizedPrintf(comm,"  [%d], color %d, sub-size %d, sub-rank %d, duprank %d\n",rank,psubcomm->color,subsize,subrank,duprank);CHKERRQ(ierr);
1280ec8b6e3SBarry Smith       ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
129053d1c95SHong Zhang     }
130053d1c95SHong Zhang   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported yet");
131053d1c95SHong Zhang   PetscFunctionReturn(0);
132053d1c95SHong Zhang }
133053d1c95SHong Zhang 
134053d1c95SHong Zhang #undef __FUNCT__
135d8a68f86SHong Zhang #define __FUNCT__ "PetscSubcommSetNumber"
136d8a68f86SHong Zhang /*@C
137d8a68f86SHong Zhang   PetscSubcommSetNumber - Set total number of subcommunicators.
138d8a68f86SHong Zhang 
139d8a68f86SHong Zhang    Collective on MPI_Comm
140d8a68f86SHong Zhang 
141d8a68f86SHong Zhang    Input Parameter:
142d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
143d8a68f86SHong Zhang -  nsubcomm - the total number of subcommunicators in psubcomm
144d8a68f86SHong Zhang 
145d8a68f86SHong Zhang    Level: advanced
146d8a68f86SHong Zhang 
147d8a68f86SHong Zhang .keywords: communicator
148d8a68f86SHong Zhang 
149d8a68f86SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetType(),PetscSubcommSetTypeGeneral()
150d8a68f86SHong Zhang @*/
1517087cfbeSBarry Smith PetscErrorCode  PetscSubcommSetNumber(PetscSubcomm psubcomm,PetscInt nsubcomm)
152d8a68f86SHong Zhang {
153d8a68f86SHong Zhang   PetscErrorCode ierr;
154d8a68f86SHong Zhang   MPI_Comm       comm=psubcomm->parent;
15545487dadSJed Brown   PetscMPIInt    msub,size;
156d8a68f86SHong Zhang 
157d8a68f86SHong Zhang   PetscFunctionBegin;
158d8a68f86SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate() first");
159d8a68f86SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
16045487dadSJed Brown   ierr = PetscMPIIntCast(nsubcomm,&msub);CHKERRQ(ierr);
16145487dadSJed Brown   if (msub < 1 || msub > size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Num of subcommunicators %d cannot be < 1 or > input comm size %d",msub,size);
162d8a68f86SHong Zhang 
16345487dadSJed Brown   psubcomm->n = msub;
164d8a68f86SHong Zhang   PetscFunctionReturn(0);
165d8a68f86SHong Zhang }
166d8a68f86SHong Zhang 
167d8a68f86SHong Zhang #undef __FUNCT__
168d8a68f86SHong Zhang #define __FUNCT__ "PetscSubcommSetType"
169d8a68f86SHong Zhang /*@C
170d8a68f86SHong Zhang   PetscSubcommSetType - Set type of subcommunicators.
171d8a68f86SHong Zhang 
172d8a68f86SHong Zhang    Collective on MPI_Comm
173d8a68f86SHong Zhang 
174d8a68f86SHong Zhang    Input Parameter:
175d8a68f86SHong Zhang +  psubcomm - PetscSubcomm context
1761ba920a7SHong Zhang -  subcommtype - subcommunicator type, PETSC_SUBCOMM_CONTIGUOUS,PETSC_SUBCOMM_INTERLACED
177d8a68f86SHong Zhang 
178d8a68f86SHong Zhang    Level: advanced
179d8a68f86SHong Zhang 
180d8a68f86SHong Zhang .keywords: communicator
181d8a68f86SHong Zhang 
182d8a68f86SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetNumber(),PetscSubcommSetTypeGeneral()
183d8a68f86SHong Zhang @*/
1847c764164SBarry Smith PetscErrorCode  PetscSubcommSetType(PetscSubcomm psubcomm,PetscSubcommType subcommtype)
185d8a68f86SHong Zhang {
186d8a68f86SHong Zhang   PetscErrorCode ierr;
187d8a68f86SHong Zhang 
188d8a68f86SHong Zhang   PetscFunctionBegin;
189d8a68f86SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
19045487dadSJed Brown   if (psubcomm->n < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",psubcomm->n);
191d8a68f86SHong Zhang 
192d8a68f86SHong Zhang   if (subcommtype == PETSC_SUBCOMM_CONTIGUOUS) {
193d8a68f86SHong Zhang     ierr = PetscSubcommCreate_contiguous(psubcomm);CHKERRQ(ierr);
194d8a68f86SHong Zhang   } else if (subcommtype == PETSC_SUBCOMM_INTERLACED) {
195d8a68f86SHong Zhang     ierr = PetscSubcommCreate_interlaced(psubcomm);CHKERRQ(ierr);
19645487dadSJed Brown   } else SETERRQ1(psubcomm->parent,PETSC_ERR_SUP,"PetscSubcommType %s is not supported yet",PetscSubcommTypes[subcommtype]);
197d8a68f86SHong Zhang   PetscFunctionReturn(0);
198d8a68f86SHong Zhang }
199d8a68f86SHong Zhang 
200d8a68f86SHong Zhang #undef __FUNCT__
201d8a68f86SHong Zhang #define __FUNCT__ "PetscSubcommSetTypeGeneral"
2021ba920a7SHong Zhang /*@C
20365d9b8f1SHong Zhang   PetscSubcommSetTypeGeneral - Set a PetscSubcomm from user's specifications
2041ba920a7SHong Zhang 
2051ba920a7SHong Zhang    Collective on MPI_Comm
2061ba920a7SHong Zhang 
2071ba920a7SHong Zhang    Input Parameter:
2081ba920a7SHong Zhang +  psubcomm - PetscSubcomm context
2091ba920a7SHong Zhang .  color   - control of subset assignment (nonnegative integer). Processes with the same color are in the same subcommunicator.
21065d9b8f1SHong Zhang -  subrank - rank in the subcommunicator
2111ba920a7SHong Zhang 
2121ba920a7SHong Zhang    Level: advanced
2131ba920a7SHong Zhang 
2141ba920a7SHong Zhang .keywords: communicator, create
2151ba920a7SHong Zhang 
2161ba920a7SHong Zhang .seealso: PetscSubcommCreate(),PetscSubcommDestroy(),PetscSubcommSetNumber(),PetscSubcommSetType()
2171ba920a7SHong Zhang @*/
21865d9b8f1SHong Zhang PetscErrorCode PetscSubcommSetTypeGeneral(PetscSubcomm psubcomm,PetscMPIInt color,PetscMPIInt subrank)
219d8a68f86SHong Zhang {
2201ba920a7SHong Zhang   PetscErrorCode ierr;
2211ba920a7SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
222c9e2ceb8SHong Zhang   PetscMPIInt    size,icolor,duprank,*recvbuf,sendbuf[3],mysubsize,rank,*subsize;
22345487dadSJed Brown   PetscMPIInt    i,nsubcomm=psubcomm->n;
2241ba920a7SHong Zhang 
225d8a68f86SHong Zhang   PetscFunctionBegin;
2261ba920a7SHong Zhang   if (!psubcomm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"PetscSubcomm is not created. Call PetscSubcommCreate()");
22745487dadSJed Brown   if (nsubcomm < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"number of subcommunicators %d is incorrect. Call PetscSubcommSetNumber()",nsubcomm);
2281ba920a7SHong Zhang 
2291ba920a7SHong Zhang   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr);
2301ba920a7SHong Zhang 
23165d9b8f1SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
2329abe469cSDmitry 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(). */
2331ba920a7SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
234785e854fSJed Brown   ierr = PetscMalloc1(2*size,&recvbuf);CHKERRQ(ierr);
23565d9b8f1SHong Zhang 
23665d9b8f1SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
237c9e2ceb8SHong Zhang   ierr = MPI_Comm_size(subcomm,&mysubsize);CHKERRQ(ierr);
23865d9b8f1SHong Zhang 
23965d9b8f1SHong Zhang   sendbuf[0] = color;
240c9e2ceb8SHong Zhang   sendbuf[1] = mysubsize;
241c9e2ceb8SHong Zhang   ierr = MPI_Allgather(sendbuf,2,MPI_INT,recvbuf,2,MPI_INT,comm);CHKERRQ(ierr);
24265d9b8f1SHong Zhang 
243eca4a452SHong Zhang   ierr = PetscCalloc1(nsubcomm,&subsize);CHKERRQ(ierr);
2449972d2ceSHong Zhang   for (i=0; i<2*size; i+=2) {
245c9e2ceb8SHong Zhang     subsize[recvbuf[i]] = recvbuf[i+1];
2461ba920a7SHong Zhang   }
24765d9b8f1SHong Zhang   ierr = PetscFree(recvbuf);CHKERRQ(ierr);
24865d9b8f1SHong Zhang 
24965d9b8f1SHong Zhang   duprank = 0;
250c9e2ceb8SHong Zhang   for (icolor=0; icolor<nsubcomm; icolor++) {
25165d9b8f1SHong Zhang     if (icolor != color) { /* not color of this process */
252c9e2ceb8SHong Zhang       duprank += subsize[icolor];
25365d9b8f1SHong Zhang     } else {
25465d9b8f1SHong Zhang       duprank += subrank;
25565d9b8f1SHong Zhang       break;
25665d9b8f1SHong Zhang     }
25765d9b8f1SHong Zhang   }
25865d9b8f1SHong Zhang   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr);
25965d9b8f1SHong Zhang 
2600298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
261306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
262b89831e5SBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRQ(ierr);
263b89831e5SBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
264a297a907SKarl Rupp 
2651ba920a7SHong Zhang   psubcomm->color   = color;
266c9e2ceb8SHong Zhang   psubcomm->subsize = subsize;
267c9e2ceb8SHong Zhang   psubcomm->type    = PETSC_SUBCOMM_GENERAL;
268d8a68f86SHong Zhang   PetscFunctionReturn(0);
269d8a68f86SHong Zhang }
270638faf0bSHong Zhang 
271cd05a4c0SHong Zhang #undef __FUNCT__
272cd05a4c0SHong Zhang #define __FUNCT__ "PetscSubcommDestroy"
273*89587e68SDave May /*@C
274*89587e68SDave May   PetscSubcommDestroy - Destroys a PetscSubcomm object
275*89587e68SDave May 
276*89587e68SDave May    Collective on PetscSubcomm
277*89587e68SDave May 
278*89587e68SDave May    Input Parameter:
279*89587e68SDave May    .  psubcomm - the PetscSubcomm context
280*89587e68SDave May 
281*89587e68SDave May    Level: advanced
282*89587e68SDave May 
283*89587e68SDave May .seealso: PetscSubcommCreate(),PetscSubcommSetType()
284*89587e68SDave May @*/
2856bf464f9SBarry Smith PetscErrorCode  PetscSubcommDestroy(PetscSubcomm *psubcomm)
286cd05a4c0SHong Zhang {
287cd05a4c0SHong Zhang   PetscErrorCode ierr;
288cd05a4c0SHong Zhang 
289cd05a4c0SHong Zhang   PetscFunctionBegin;
2906bf464f9SBarry Smith   if (!*psubcomm) PetscFunctionReturn(0);
291aa9c1079SBarry Smith   ierr = PetscCommDestroy(&(*psubcomm)->dupparent);CHKERRQ(ierr);
292306c2d5bSBarry Smith   ierr = PetscCommDestroy(&(*psubcomm)->child);CHKERRQ(ierr);
293e37c6257SHong Zhang   ierr = PetscFree((*psubcomm)->subsize);CHKERRQ(ierr);
294e5acf8a4SHong Zhang   if ((*psubcomm)->subcommprefix) { ierr = PetscFree((*psubcomm)->subcommprefix);CHKERRQ(ierr); }
2956bf464f9SBarry Smith   ierr = PetscFree((*psubcomm));CHKERRQ(ierr);
296cd05a4c0SHong Zhang   PetscFunctionReturn(0);
297cd05a4c0SHong Zhang }
298cd05a4c0SHong Zhang 
299cd05a4c0SHong Zhang #undef __FUNCT__
300cd05a4c0SHong Zhang #define __FUNCT__ "PetscSubcommCreate"
301ab8c242fSMatthew Knepley /*@C
302cd05a4c0SHong Zhang   PetscSubcommCreate - Create a PetscSubcomm context.
303cd05a4c0SHong Zhang 
304cd05a4c0SHong Zhang    Collective on MPI_Comm
305cd05a4c0SHong Zhang 
306cd05a4c0SHong Zhang    Input Parameter:
3079873d53eSJed Brown .  comm - MPI communicator
308cd05a4c0SHong Zhang 
309cd05a4c0SHong Zhang    Output Parameter:
310cd05a4c0SHong Zhang .  psubcomm - location to store the PetscSubcomm context
311cd05a4c0SHong Zhang 
312638faf0bSHong Zhang    Level: advanced
313cd05a4c0SHong Zhang 
314638faf0bSHong Zhang .keywords: communicator, create
315638faf0bSHong Zhang 
316638faf0bSHong Zhang .seealso: PetscSubcommDestroy()
317638faf0bSHong Zhang @*/
3187087cfbeSBarry Smith PetscErrorCode  PetscSubcommCreate(MPI_Comm comm,PetscSubcomm *psubcomm)
319638faf0bSHong Zhang {
320638faf0bSHong Zhang   PetscErrorCode ierr;
321d3b23db5SHong Zhang   PetscMPIInt    rank,size;
322638faf0bSHong Zhang 
323638faf0bSHong Zhang   PetscFunctionBegin;
324b00a9115SJed Brown   ierr = PetscNew(psubcomm);CHKERRQ(ierr);
325a297a907SKarl Rupp 
326d3b23db5SHong Zhang   /* set defaults */
327d3b23db5SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
328d3b23db5SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
329f68be91cSHong Zhang 
330d8a68f86SHong Zhang   (*psubcomm)->parent    = comm;
331d3b23db5SHong Zhang   (*psubcomm)->dupparent = comm;
332306c2d5bSBarry Smith   (*psubcomm)->child     = PETSC_COMM_SELF;
333d3b23db5SHong Zhang   (*psubcomm)->n         = size;
334d3b23db5SHong Zhang   (*psubcomm)->color     = rank;
335e37c6257SHong Zhang   (*psubcomm)->subsize   = NULL;
336d3b23db5SHong Zhang   (*psubcomm)->type      = PETSC_SUBCOMM_INTERLACED;
337638faf0bSHong Zhang   PetscFunctionReturn(0);
338638faf0bSHong Zhang }
339638faf0bSHong Zhang 
340638faf0bSHong Zhang #undef __FUNCT__
34153c77d0aSJed Brown #define __FUNCT__ "PetscSubcommCreate_contiguous"
342d8a68f86SHong Zhang PetscErrorCode PetscSubcommCreate_contiguous(PetscSubcomm psubcomm)
343638faf0bSHong Zhang {
344638faf0bSHong Zhang   PetscErrorCode ierr;
345d6037b41SHong Zhang   PetscMPIInt    rank,size,*subsize,duprank=-1,subrank=-1;
34645487dadSJed Brown   PetscMPIInt    np_subcomm,nleftover,i,color=-1,rankstart,nsubcomm=psubcomm->n;
347d8a68f86SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
348638faf0bSHong Zhang 
349638faf0bSHong Zhang   PetscFunctionBegin;
35055e3b8d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
35155e3b8d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
35255e3b8d2SHong Zhang 
353638faf0bSHong Zhang   /* get size of each subcommunicator */
354854ce69bSBarry Smith   ierr = PetscMalloc1(1+nsubcomm,&subsize);CHKERRQ(ierr);
355a297a907SKarl Rupp 
356638faf0bSHong Zhang   np_subcomm = size/nsubcomm;
357638faf0bSHong Zhang   nleftover  = size - nsubcomm*np_subcomm;
358638faf0bSHong Zhang   for (i=0; i<nsubcomm; i++) {
359638faf0bSHong Zhang     subsize[i] = np_subcomm;
360638faf0bSHong Zhang     if (i<nleftover) subsize[i]++;
361638faf0bSHong Zhang   }
362638faf0bSHong Zhang 
363638faf0bSHong Zhang   /* get color and subrank of this proc */
364638faf0bSHong Zhang   rankstart = 0;
365638faf0bSHong Zhang   for (i=0; i<nsubcomm; i++) {
366638faf0bSHong Zhang     if (rank >= rankstart && rank < rankstart+subsize[i]) {
367638faf0bSHong Zhang       color   = i;
368638faf0bSHong Zhang       subrank = rank - rankstart;
369638faf0bSHong Zhang       duprank = rank;
370638faf0bSHong Zhang       break;
371a297a907SKarl Rupp     } else rankstart += subsize[i];
372638faf0bSHong Zhang   }
373638faf0bSHong Zhang 
374638faf0bSHong Zhang   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr);
375638faf0bSHong Zhang 
376638faf0bSHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
377638faf0bSHong Zhang   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr);
3780298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
379306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
380b89831e5SBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRQ(ierr);
381b89831e5SBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
382a297a907SKarl Rupp 
383d8a68f86SHong Zhang   psubcomm->color   = color;
384e37c6257SHong Zhang   psubcomm->subsize = subsize;
385f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_CONTIGUOUS;
386638faf0bSHong Zhang   PetscFunctionReturn(0);
387638faf0bSHong Zhang }
388638faf0bSHong Zhang 
389638faf0bSHong Zhang #undef __FUNCT__
390638faf0bSHong Zhang #define __FUNCT__ "PetscSubcommCreate_interlaced"
391638faf0bSHong Zhang /*
392638faf0bSHong Zhang    Note:
393638faf0bSHong Zhang    In PCREDUNDANT, to avoid data scattering from subcomm back to original comm, we create subcommunicators
39445fc02eaSBarry Smith    by iteratively taking a process into a subcommunicator.
395cd05a4c0SHong Zhang    Example: size=4, nsubcomm=(*psubcomm)->n=3
396cd05a4c0SHong Zhang      comm=(*psubcomm)->parent:
397cd05a4c0SHong Zhang       rank:     [0]  [1]  [2]  [3]
398cd05a4c0SHong Zhang       color:     0    1    2    0
399cd05a4c0SHong Zhang 
400cd05a4c0SHong Zhang      subcomm=(*psubcomm)->comm:
401cd05a4c0SHong Zhang       subrank:  [0]  [0]  [0]  [1]
402cd05a4c0SHong Zhang 
403cd05a4c0SHong Zhang      dupcomm=(*psubcomm)->dupparent:
404cd05a4c0SHong Zhang       duprank:  [0]  [2]  [3]  [1]
405cd05a4c0SHong Zhang 
406cd05a4c0SHong Zhang      Here, subcomm[color = 0] has subsize=2, owns process [0] and [3]
407cd05a4c0SHong Zhang            subcomm[color = 1] has subsize=1, owns process [1]
408cd05a4c0SHong Zhang            subcomm[color = 2] has subsize=1, owns process [2]
409cd05a4c0SHong Zhang            dupcomm has same number of processes as comm, and its duprank maps
410cd05a4c0SHong Zhang            processes in subcomm contiguously into a 1d array:
411cd05a4c0SHong Zhang             duprank: [0] [1]      [2]         [3]
412cd05a4c0SHong Zhang             rank:    [0] [3]      [1]         [2]
413cd05a4c0SHong Zhang                     subcomm[0] subcomm[1]  subcomm[2]
414638faf0bSHong Zhang */
415cd05a4c0SHong Zhang 
416d8a68f86SHong Zhang PetscErrorCode PetscSubcommCreate_interlaced(PetscSubcomm psubcomm)
417cd05a4c0SHong Zhang {
418cd05a4c0SHong Zhang   PetscErrorCode ierr;
419cd05a4c0SHong Zhang   PetscMPIInt    rank,size,*subsize,duprank,subrank;
42045487dadSJed Brown   PetscMPIInt    np_subcomm,nleftover,i,j,color,nsubcomm=psubcomm->n;
421d8a68f86SHong Zhang   MPI_Comm       subcomm=0,dupcomm=0,comm=psubcomm->parent;
422cd05a4c0SHong Zhang 
423cd05a4c0SHong Zhang   PetscFunctionBegin;
42455e3b8d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
42555e3b8d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
42655e3b8d2SHong Zhang 
427cd05a4c0SHong Zhang   /* get size of each subcommunicator */
428854ce69bSBarry Smith   ierr = PetscMalloc1(1+nsubcomm,&subsize);CHKERRQ(ierr);
429a297a907SKarl Rupp 
430cd05a4c0SHong Zhang   np_subcomm = size/nsubcomm;
431cd05a4c0SHong Zhang   nleftover  = size - nsubcomm*np_subcomm;
432cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
433cd05a4c0SHong Zhang     subsize[i] = np_subcomm;
434cd05a4c0SHong Zhang     if (i<nleftover) subsize[i]++;
435cd05a4c0SHong Zhang   }
436cd05a4c0SHong Zhang 
437cd05a4c0SHong Zhang   /* find color for this proc */
438cd05a4c0SHong Zhang   color   = rank%nsubcomm;
439cd05a4c0SHong Zhang   subrank = rank/nsubcomm;
440cd05a4c0SHong Zhang 
441cd05a4c0SHong Zhang   ierr = MPI_Comm_split(comm,color,subrank,&subcomm);CHKERRQ(ierr);
442cd05a4c0SHong Zhang 
443cd05a4c0SHong Zhang   j = 0; duprank = 0;
444cd05a4c0SHong Zhang   for (i=0; i<nsubcomm; i++) {
445cd05a4c0SHong Zhang     if (j == color) {
446cd05a4c0SHong Zhang       duprank += subrank;
447cd05a4c0SHong Zhang       break;
448cd05a4c0SHong Zhang     }
449cd05a4c0SHong Zhang     duprank += subsize[i]; j++;
450cd05a4c0SHong Zhang   }
451cd05a4c0SHong Zhang 
452cd05a4c0SHong Zhang   /* create dupcomm with same size as comm, but its rank, duprank, maps subcomm's contiguously into dupcomm */
453cd05a4c0SHong Zhang   ierr = MPI_Comm_split(comm,0,duprank,&dupcomm);CHKERRQ(ierr);
4540298fd71SBarry Smith   ierr = PetscCommDuplicate(dupcomm,&psubcomm->dupparent,NULL);CHKERRQ(ierr);
455306c2d5bSBarry Smith   ierr = PetscCommDuplicate(subcomm,&psubcomm->child,NULL);CHKERRQ(ierr);
456b89831e5SBarry Smith   ierr = MPI_Comm_free(&dupcomm);CHKERRQ(ierr);
457b89831e5SBarry Smith   ierr = MPI_Comm_free(&subcomm);CHKERRQ(ierr);
458a297a907SKarl Rupp 
459d8a68f86SHong Zhang   psubcomm->color   = color;
460e37c6257SHong Zhang   psubcomm->subsize = subsize;
461f38d543fSHong Zhang   psubcomm->type    = PETSC_SUBCOMM_INTERLACED;
462cd05a4c0SHong Zhang   PetscFunctionReturn(0);
463cd05a4c0SHong Zhang }
464638faf0bSHong Zhang 
465638faf0bSHong Zhang 
466