xref: /petsc/src/vec/is/utils/isltog.c (revision 30dcb7c9e14dd0b49400573560f124f1246db00f)
1*30dcb7c9SBarry Smith /*$Id: isltog.c,v 1.46 2000/06/26 03:50:54 bsmith Exp bsmith $*/
22362add9SBarry Smith 
3e090d566SSatish Balay #include "petscsys.h"   /*I "petscsys.h" I*/
4e090d566SSatish Balay #include "src/vec/is/isimpl.h"    /*I "petscis.h"  I*/
52362add9SBarry Smith 
65615d1e5SSatish Balay #undef __FUNC__
73b9aefa3SBarry Smith #define __FUNC__ /*<a name="ISLocalToGlobalMappingGetSize"></a>*/"ISLocalToGlobalMappingGetSize"
83b9aefa3SBarry Smith /*@C
93b9aefa3SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping.
103b9aefa3SBarry Smith 
113b9aefa3SBarry Smith     Not Collective
123b9aefa3SBarry Smith 
133b9aefa3SBarry Smith     Input Parameter:
143b9aefa3SBarry Smith .   ltog - local to global mapping
153b9aefa3SBarry Smith 
163b9aefa3SBarry Smith     Output Parameter:
173b9aefa3SBarry Smith .   n - the number of entries in the local mapping
183b9aefa3SBarry Smith 
193b9aefa3SBarry Smith     Level: advanced
203b9aefa3SBarry Smith 
213b9aefa3SBarry Smith .keywords: IS, local-to-global mapping, create
223b9aefa3SBarry Smith 
233b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
243b9aefa3SBarry Smith @*/
253b9aefa3SBarry Smith int ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,int *n)
263b9aefa3SBarry Smith {
273b9aefa3SBarry Smith   PetscFunctionBegin;
283b9aefa3SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
293b9aefa3SBarry Smith   *n = mapping->n;
303b9aefa3SBarry Smith   PetscFunctionReturn(0);
313b9aefa3SBarry Smith }
323b9aefa3SBarry Smith 
333b9aefa3SBarry Smith #undef __FUNC__
34b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingView"
355a5d4f66SBarry Smith /*@C
365a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
375a5d4f66SBarry Smith 
38b9cd556bSLois Curfman McInnes     Not Collective
39b9cd556bSLois Curfman McInnes 
405a5d4f66SBarry Smith     Input Parameters:
413b9aefa3SBarry Smith +   ltog - local to global mapping
423b9aefa3SBarry Smith -   viewer - viewer
435a5d4f66SBarry Smith 
44a997ad1aSLois Curfman McInnes     Level: advanced
45a997ad1aSLois Curfman McInnes 
465a5d4f66SBarry Smith .keywords: IS, local-to-global mapping, create
475a5d4f66SBarry Smith 
485a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
495a5d4f66SBarry Smith @*/
505a5d4f66SBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,Viewer viewer)
515a5d4f66SBarry Smith {
52f1af5d2fSBarry Smith   int        i,ierr,rank;
536831982aSBarry Smith   PetscTruth isascii;
545a5d4f66SBarry Smith 
555a5d4f66SBarry Smith   PetscFunctionBegin;
566831982aSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
573eda8832SBarry Smith   if (!viewer) viewer = VIEWER_STDOUT_(mapping->comm);
586831982aSBarry Smith   PetscValidHeaderSpecific(viewer,VIEWER_COOKIE);
596831982aSBarry Smith   PetscCheckSameComm(mapping,viewer);
605a5d4f66SBarry Smith 
61f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
626831982aSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr);
636831982aSBarry Smith   if (isascii) {
645a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
65f1af5d2fSBarry Smith       ierr = ViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
666831982aSBarry Smith     }
676831982aSBarry Smith     ierr = ViewerFlush(viewer);CHKERRQ(ierr);
686831982aSBarry Smith   } else {
696831982aSBarry Smith     SETERRQ1(1,1,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
705a5d4f66SBarry Smith   }
715a5d4f66SBarry Smith 
725a5d4f66SBarry Smith   PetscFunctionReturn(0);
735a5d4f66SBarry Smith }
745a5d4f66SBarry Smith 
755a5d4f66SBarry Smith #undef __FUNC__
76b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingCreateIS"
772bdab257SBarry Smith /*@C
782bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
792bdab257SBarry Smith     ordering and a global parallel ordering.
802bdab257SBarry Smith 
810f5bd95cSBarry Smith     Not collective
82b9cd556bSLois Curfman McInnes 
83a997ad1aSLois Curfman McInnes     Input Parameter:
842bdab257SBarry Smith .   is - index set containing the global numbers for each local
852bdab257SBarry Smith 
86a997ad1aSLois Curfman McInnes     Output Parameter:
872bdab257SBarry Smith .   mapping - new mapping data structure
882bdab257SBarry Smith 
89a997ad1aSLois Curfman McInnes     Level: advanced
90a997ad1aSLois Curfman McInnes 
912bdab257SBarry Smith .keywords: IS, local-to-global mapping, create
922bdab257SBarry Smith 
932bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
942bdab257SBarry Smith @*/
952bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
962bdab257SBarry Smith {
972bdab257SBarry Smith   int      n,*indices,ierr;
982bdab257SBarry Smith   MPI_Comm comm;
993a40ed3dSBarry Smith 
1003a40ed3dSBarry Smith   PetscFunctionBegin;
1012bdab257SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
1022bdab257SBarry Smith 
1032bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1043b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1052bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1062bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
1072bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1082bdab257SBarry Smith 
1093a40ed3dSBarry Smith   PetscFunctionReturn(0);
1102bdab257SBarry Smith }
1115a5d4f66SBarry Smith 
1122bdab257SBarry Smith #undef __FUNC__
113b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingCreate"
114dd7157adSSatish Balay /*@C
11590f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
11690f02eecSBarry Smith     ordering and a global parallel ordering.
1172362add9SBarry Smith 
11889d82c54SBarry Smith     Not Collective, but communicator may have more than one process
119b9cd556bSLois Curfman McInnes 
1202362add9SBarry Smith     Input Parameters:
12189d82c54SBarry Smith +   comm - MPI communicator
12290f02eecSBarry Smith .   n - the number of local elements
123b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
1242362add9SBarry Smith 
125a997ad1aSLois Curfman McInnes     Output Parameter:
12690f02eecSBarry Smith .   mapping - new mapping data structure
1272362add9SBarry Smith 
128a997ad1aSLois Curfman McInnes     Level: advanced
129a997ad1aSLois Curfman McInnes 
1303acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, create
1312362add9SBarry Smith 
1322bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
1332362add9SBarry Smith @*/
134987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1352362add9SBarry Smith {
136549d3d68SSatish Balay   int ierr;
137549d3d68SSatish Balay 
1383a40ed3dSBarry Smith   PetscFunctionBegin;
13990f02eecSBarry Smith   PetscValidIntPointer(indices);
14090f02eecSBarry Smith   PetscValidPointer(mapping);
1412362add9SBarry Smith 
1423f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1433f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
144d4bb536fSBarry Smith   PLogObjectCreate(*mapping);
145d4bb536fSBarry Smith   PLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
146d4bb536fSBarry Smith 
147d4bb536fSBarry Smith   (*mapping)->n       = n;
14890f02eecSBarry Smith   (*mapping)->indices = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ((*mapping)->indices);
149549d3d68SSatish Balay   ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr);
150d4bb536fSBarry Smith 
151d4bb536fSBarry Smith   /*
152d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
153d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
154d4bb536fSBarry Smith   */
155d4bb536fSBarry Smith   (*mapping)->globals = 0;
1563a40ed3dSBarry Smith   PetscFunctionReturn(0);
1572362add9SBarry Smith }
1582362add9SBarry Smith 
1595615d1e5SSatish Balay #undef __FUNC__
160b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingDestroy"
16190f02eecSBarry Smith /*@
16290f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
16390f02eecSBarry Smith    ordering and a global parallel ordering.
16490f02eecSBarry Smith 
1650f5bd95cSBarry Smith    Note Collective
166b9cd556bSLois Curfman McInnes 
16790f02eecSBarry Smith    Input Parameters:
16890f02eecSBarry Smith .  mapping - mapping data structure
16990f02eecSBarry Smith 
170a997ad1aSLois Curfman McInnes    Level: advanced
171a997ad1aSLois Curfman McInnes 
1723acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, destroy
17390f02eecSBarry Smith 
1743acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
17590f02eecSBarry Smith @*/
17690f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
17790f02eecSBarry Smith {
178606d414cSSatish Balay   int ierr;
1793a40ed3dSBarry Smith   PetscFunctionBegin;
18090f02eecSBarry Smith   PetscValidPointer(mapping);
1813a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
18285614651SBarry Smith   if (mapping->refct < 0) {
18385614651SBarry Smith     SETERRQ(1,1,"Mapping already destroyed");
18485614651SBarry Smith   }
18590f02eecSBarry Smith 
186606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
187606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
188d4bb536fSBarry Smith   PLogObjectDestroy(mapping);
189d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
1903a40ed3dSBarry Smith   PetscFunctionReturn(0);
19190f02eecSBarry Smith }
19290f02eecSBarry Smith 
1935615d1e5SSatish Balay #undef __FUNC__
194b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingApplyIS"
19590f02eecSBarry Smith /*@
1963acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
1973acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
1983acfe500SLois Curfman McInnes     context.
19990f02eecSBarry Smith 
200b9cd556bSLois Curfman McInnes     Not collective
201b9cd556bSLois Curfman McInnes 
20290f02eecSBarry Smith     Input Parameters:
203b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
204b9cd556bSLois Curfman McInnes -   is - index set in local numbering
20590f02eecSBarry Smith 
20690f02eecSBarry Smith     Output Parameters:
20790f02eecSBarry Smith .   newis - index set in global numbering
20890f02eecSBarry Smith 
209a997ad1aSLois Curfman McInnes     Level: advanced
210a997ad1aSLois Curfman McInnes 
2113acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, apply
2123acfe500SLois Curfman McInnes 
21390f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
214d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
21590f02eecSBarry Smith @*/
21690f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
21790f02eecSBarry Smith {
2183b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
2193a40ed3dSBarry Smith 
2203a40ed3dSBarry Smith   PetscFunctionBegin;
22190f02eecSBarry Smith   PetscValidPointer(mapping);
22290f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
22390f02eecSBarry Smith   PetscValidPointer(newis);
22490f02eecSBarry Smith 
2253b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
22690f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
22790f02eecSBarry Smith   idxmap = mapping->indices;
22890f02eecSBarry Smith 
22990f02eecSBarry Smith   idxout = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(idxout);
23090f02eecSBarry Smith   for (i=0; i<n; i++) {
2313b9aefa3SBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,1,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i);
23290f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
23390f02eecSBarry Smith   }
2343b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
235029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
236606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
2373a40ed3dSBarry Smith   PetscFunctionReturn(0);
23890f02eecSBarry Smith }
23990f02eecSBarry Smith 
24089d82c54SBarry Smith /*MC
2413acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2423acfe500SLois Curfman McInnes    and converts them to the global numbering.
24390f02eecSBarry Smith 
244b9cd556bSLois Curfman McInnes    Not collective
245b9cd556bSLois Curfman McInnes 
246bb25748dSBarry Smith    Input Parameters:
247b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
248bb25748dSBarry Smith .  N - number of integers
249b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
250bb25748dSBarry Smith 
251bb25748dSBarry Smith    Output Parameter:
252bb25748dSBarry Smith .  out - indices in global numbering
253bb25748dSBarry Smith 
2543b9aefa3SBarry Smith    Synopsis:
2553b9aefa3SBarry Smith    ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
2563b9aefa3SBarry Smith 
257b9cd556bSLois Curfman McInnes    Notes:
258b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
259d4bb536fSBarry Smith 
260a997ad1aSLois Curfman McInnes    Level: advanced
261a997ad1aSLois Curfman McInnes 
262bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
2630752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
264d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
265bb25748dSBarry Smith 
2663acfe500SLois Curfman McInnes .keywords: local-to-global, mapping, apply
267d4bb536fSBarry Smith 
26889d82c54SBarry Smith M*/
269d4bb536fSBarry Smith 
270d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
271d4bb536fSBarry Smith 
272d4bb536fSBarry Smith #undef __FUNC__
273b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISGlobalToLocalMappingSetUp_Private"
274d4bb536fSBarry Smith /*
275d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
276d4bb536fSBarry Smith */
277d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
278d4bb536fSBarry Smith {
279d4bb536fSBarry Smith   int i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
280d4bb536fSBarry Smith 
2813a40ed3dSBarry Smith   PetscFunctionBegin;
282d4bb536fSBarry Smith   end   = 0;
283d4bb536fSBarry Smith   start = 100000000;
284d4bb536fSBarry Smith 
285d4bb536fSBarry Smith   for (i=0; i<n; i++) {
286d4bb536fSBarry Smith     if (idx[i] < 0) continue;
287d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
288d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
289d4bb536fSBarry Smith   }
290d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
291d4bb536fSBarry Smith   mapping->globalstart = start;
292d4bb536fSBarry Smith   mapping->globalend   = end;
293d4bb536fSBarry Smith 
294d4bb536fSBarry Smith   globals = mapping->globals = (int*)PetscMalloc((end-start+2)*sizeof(int));CHKPTRQ(mapping->globals);
295d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
296d4bb536fSBarry Smith     globals[i] = -1;
297d4bb536fSBarry Smith   }
298d4bb536fSBarry Smith   for (i=0; i<n; i++) {
299d4bb536fSBarry Smith     if (idx[i] < 0) continue;
300d4bb536fSBarry Smith     globals[idx[i] - start] = i;
301d4bb536fSBarry Smith   }
302d4bb536fSBarry Smith 
303d4bb536fSBarry Smith   PLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3043a40ed3dSBarry Smith   PetscFunctionReturn(0);
305d4bb536fSBarry Smith }
306d4bb536fSBarry Smith 
307d4bb536fSBarry Smith #undef __FUNC__
308b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISGlobalToLocalMappingApply"
309d4bb536fSBarry Smith /*@
310a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
311a997ad1aSLois Curfman McInnes     specified with a global numbering.
312d4bb536fSBarry Smith 
313b9cd556bSLois Curfman McInnes     Not collective
314b9cd556bSLois Curfman McInnes 
315d4bb536fSBarry Smith     Input Parameters:
316b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
317d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
318d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
319d4bb536fSBarry Smith .   n - number of global indices to map
320b9cd556bSLois Curfman McInnes -   idx - global indices to map
321d4bb536fSBarry Smith 
322d4bb536fSBarry Smith     Output Parameters:
323b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
324b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
325e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
326e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
327e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
328e182c471SBarry Smith              a second time to set the values.
329d4bb536fSBarry Smith 
330b9cd556bSLois Curfman McInnes     Notes:
331b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
332d4bb536fSBarry Smith 
3330f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
3340f5bd95cSBarry Smith     array to compute these.
3350f5bd95cSBarry Smith 
336a997ad1aSLois Curfman McInnes     Level: advanced
337a997ad1aSLois Curfman McInnes 
338d4bb536fSBarry Smith .keywords: IS, global-to-local mapping, apply
339d4bb536fSBarry Smith 
340d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
341d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
342d4bb536fSBarry Smith @*/
343d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
344987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
345d4bb536fSBarry Smith {
346d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
347d4bb536fSBarry Smith 
3483a40ed3dSBarry Smith   PetscFunctionBegin;
349d4bb536fSBarry Smith   if (!mapping->globals) {
350d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
351d4bb536fSBarry Smith   }
352d4bb536fSBarry Smith   globals = mapping->globals;
353d4bb536fSBarry Smith   start   = mapping->globalstart;
354d4bb536fSBarry Smith   end     = mapping->globalend;
355d4bb536fSBarry Smith 
356d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
357d4bb536fSBarry Smith     if (idxout) {
358d4bb536fSBarry Smith       for (i=0; i<n; i++) {
359d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
360d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
361d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
362d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
363d4bb536fSBarry Smith       }
364d4bb536fSBarry Smith     }
365d4bb536fSBarry Smith     if (nout) *nout = n;
366d4bb536fSBarry Smith   } else {
367d4bb536fSBarry Smith     if (idxout) {
368d4bb536fSBarry Smith       for (i=0; i<n; i++) {
369d4bb536fSBarry Smith         if (idx[i] < 0) continue;
370d4bb536fSBarry Smith         if (idx[i] < start) continue;
371d4bb536fSBarry Smith         if (idx[i] > end) continue;
372d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
373d4bb536fSBarry Smith         if (tmp < 0) continue;
374d4bb536fSBarry Smith         idxout[nf++] = tmp;
375d4bb536fSBarry Smith       }
376d4bb536fSBarry Smith     } else {
377d4bb536fSBarry Smith       for (i=0; i<n; i++) {
378d4bb536fSBarry Smith         if (idx[i] < 0) continue;
379d4bb536fSBarry Smith         if (idx[i] < start) continue;
380d4bb536fSBarry Smith         if (idx[i] > end) continue;
381d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
382d4bb536fSBarry Smith         if (tmp < 0) continue;
383d4bb536fSBarry Smith         nf++;
384d4bb536fSBarry Smith       }
385d4bb536fSBarry Smith     }
386d4bb536fSBarry Smith     if (nout) *nout = nf;
387d4bb536fSBarry Smith   }
388d4bb536fSBarry Smith 
3893a40ed3dSBarry Smith   PetscFunctionReturn(0);
390d4bb536fSBarry Smith }
39190f02eecSBarry Smith 
39289d82c54SBarry Smith #undef __FUNC__
39389d82c54SBarry Smith #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingGetInfo"
39489d82c54SBarry Smith /*@C
39589d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
39689d82c54SBarry Smith      each index shared by more than one processor
39789d82c54SBarry Smith 
39889d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
39989d82c54SBarry Smith 
40089d82c54SBarry Smith     Input Parameters:
40189d82c54SBarry Smith .   mapping - the mapping from local to global indexing
40289d82c54SBarry Smith 
40389d82c54SBarry Smith     Output Parameter:
40489d82c54SBarry Smith +   nproc - number of processors that are connected to this one
40589d82c54SBarry Smith .   proc - neighboring processors
40689d82c54SBarry Smith .   indices - indices of local nodes shared with neighbor (sorted by global numbering)
40789d82c54SBarry Smith 
40889d82c54SBarry Smith     Level: advanced
40989d82c54SBarry Smith 
41089d82c54SBarry Smith .keywords: IS, local-to-global mapping, neighbors
41189d82c54SBarry Smith 
41289d82c54SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate()
41389d82c54SBarry Smith @*/
414*30dcb7c9SBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
41589d82c54SBarry Smith {
4163a96401aSBarry Smith   int         i,n = mapping->n,ierr,Ng,ng = PETSC_DECIDE,max = 0,*lindices = mapping->indices;
4173a96401aSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc;
418bc8ff85bSBarry Smith   int         tag,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
419*30dcb7c9SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs;
42089d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
421*30dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
42289d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
42389d82c54SBarry Smith 
42489d82c54SBarry Smith   PetscFunctionBegin;
4253677ff5aSBarry Smith   /*
4263677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
4273677ff5aSBarry Smith 
4283677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
4293677ff5aSBarry Smith            numbering, just for this routine.
4303677ff5aSBarry Smith 
4313677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
4323677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
4333677ff5aSBarry Smith 
4343677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
4353677ff5aSBarry Smith 
4363677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
4373677ff5aSBarry Smith            local subdomain
4383677ff5aSBarry Smith   */
43989d82c54SBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag);CHKERRQ(ierr);
44089d82c54SBarry Smith 
44189d82c54SBarry Smith   for (i=0; i<n; i++) {
44289d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
44389d82c54SBarry Smith   }
44489d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
44589d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
44689d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
447bc8ff85bSBarry Smith   scale  = Ng/size + 1;
448bc8ff85bSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1);
449caba0dd0SBarry Smith   rstart = scale*rank;
45089d82c54SBarry Smith 
45189d82c54SBarry Smith   /* determine ownership ranges of global indices */
4523a96401aSBarry Smith   nprocs    = (int*)PetscMalloc((2*size+1)*sizeof(int));CHKPTRQ(nprocs);
45389d82c54SBarry Smith   ierr      = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
45489d82c54SBarry Smith 
45589d82c54SBarry Smith   /* determine owners of each local node  */
45689d82c54SBarry Smith   owner    = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(owner);
45789d82c54SBarry Smith   for (i=0; i<n; i++) {
4583677ff5aSBarry Smith     proc              = lindices[i]/scale; /* processor that globally owns this index */
4593677ff5aSBarry Smith     nprocs[size+proc] = 1;                 /* processor globally owns at least one of ours */
4603677ff5aSBarry Smith     owner[i]          = proc;
4613677ff5aSBarry Smith     nprocs[proc]++;                        /* count of how many that processor globally owns of ours */
46289d82c54SBarry Smith   }
46389d82c54SBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i];
46489d82c54SBarry Smith   PLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
46589d82c54SBarry Smith 
46689d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
46789d82c54SBarry Smith   work   = (int*)PetscMalloc(2*size*sizeof(int));CHKPTRQ(work);
46889d82c54SBarry Smith   ierr   = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
46989d82c54SBarry Smith   nmax   = work[rank];
47089d82c54SBarry Smith   nrecvs = work[size+rank];
47189d82c54SBarry Smith   ierr   = PetscFree(work);CHKERRQ(ierr);
47289d82c54SBarry Smith   PLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
47389d82c54SBarry Smith 
47489d82c54SBarry Smith   /* post receives for owned rows */
475*30dcb7c9SBarry Smith   recvs      = (int*)PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int));CHKPTRQ(recvs);
47689d82c54SBarry Smith   recv_waits = (MPI_Request*)PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits);
47789d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
478*30dcb7c9SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
47989d82c54SBarry Smith   }
48089d82c54SBarry Smith 
48189d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
482*30dcb7c9SBarry Smith   sends    = (int*)PetscMalloc((2*n+1)*sizeof(int));CHKPTRQ(sends);
48389d82c54SBarry Smith   starts   = (int*)PetscMalloc((size+1)*sizeof(int));CHKPTRQ(starts);
48489d82c54SBarry Smith   starts[0]  = 0;
485*30dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
48689d82c54SBarry Smith   for (i=0; i<n; i++) {
48789d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
488*30dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
48989d82c54SBarry Smith   }
49089d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
49189d82c54SBarry Smith   starts[0]  = 0;
492*30dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
49389d82c54SBarry Smith 
49489d82c54SBarry Smith   /* send the messages */
49589d82c54SBarry Smith   send_waits = (MPI_Request*)PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
496*30dcb7c9SBarry Smith   dest       = (int*)PetscMalloc((nsends+1)*sizeof(int));CHKPTRQ(dest);
49789d82c54SBarry Smith   cnt = 0;
49889d82c54SBarry Smith   for (i=0; i<size; i++) {
49989d82c54SBarry Smith     if (nprocs[i]) {
500*30dcb7c9SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag,comm,send_waits+cnt);CHKERRQ(ierr);
501*30dcb7c9SBarry Smith       dest[cnt] = i;
50289d82c54SBarry Smith       cnt++;
50389d82c54SBarry Smith     }
50489d82c54SBarry Smith   }
50589d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
50689d82c54SBarry Smith 
50789d82c54SBarry Smith   /* wait on receives */
5083a96401aSBarry Smith   source = (int*)PetscMalloc((2*nrecvs+1)*sizeof(int));CHKPTRQ(source);
50989d82c54SBarry Smith   len    = source + nrecvs;
51089d82c54SBarry Smith   cnt    = nrecvs;
511caba0dd0SBarry Smith   nownedsenders = (int*)PetscMalloc((ng+1)*sizeof(int));CHKPTRQ(nownedsenders);
512caba0dd0SBarry Smith   ierr          = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
51389d82c54SBarry Smith   while (cnt) {
51489d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
51589d82c54SBarry Smith     /* unpack receives into our local space */
51689d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
51789d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
518*30dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
519caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
520*30dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
52189d82c54SBarry Smith     cnt--;
52289d82c54SBarry Smith   }
52389d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
52489d82c54SBarry Smith 
525*30dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
526bc8ff85bSBarry Smith   nowned  = 0;
527bc8ff85bSBarry Smith   nownedm = 0;
528bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
529bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
530bc8ff85bSBarry Smith   }
531bc8ff85bSBarry Smith 
532bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
533bc8ff85bSBarry Smith   ownedsenders = (int*)PetscMalloc((nownedm+1)*sizeof(int));CHKERRQ(ierr);
534*30dcb7c9SBarry Smith   starts       = (int*)PetscMalloc((ng+1)*sizeof(int));CHKPTRQ(starts);
535bc8ff85bSBarry Smith   starts[0]    = 0;
536bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
537bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
538bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
539bc8ff85bSBarry Smith   }
540bc8ff85bSBarry Smith 
541*30dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
542bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
543bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
544*30dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
545bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
546bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
547bc8ff85bSBarry Smith       }
548bc8ff85bSBarry Smith     }
549bc8ff85bSBarry Smith   }
550bc8ff85bSBarry Smith 
551*30dcb7c9SBarry Smith   /* -----------------------------------  */
552*30dcb7c9SBarry Smith   starts[0]    = 0;
553*30dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
554*30dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
555*30dcb7c9SBarry Smith     else starts[i] = starts[i-1];
556*30dcb7c9SBarry Smith   }
557*30dcb7c9SBarry Smith   for (i=0; i<ng; i++) {
558*30dcb7c9SBarry Smith     if (nownedsenders[i] > 1) {
559*30dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
560*30dcb7c9SBarry Smith       for (j=0; j<nownedsenders[i]; j++) {
561*30dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
562*30dcb7c9SBarry Smith       }
563*30dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
564*30dcb7c9SBarry Smith     }
565*30dcb7c9SBarry Smith   }
566*30dcb7c9SBarry Smith   ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
567*30dcb7c9SBarry Smith   /* -----------------------------------  */
568*30dcb7c9SBarry Smith 
5693677ff5aSBarry Smith   /* wait on original sends */
5703a96401aSBarry Smith   if (nsends) {
5713a96401aSBarry Smith     send_status = (MPI_Status*)PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
5723a96401aSBarry Smith     ierr        = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
5733a96401aSBarry Smith     ierr        = PetscFree(send_status);CHKERRQ(ierr);
5743a96401aSBarry Smith   }
57589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
5763a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
5773677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
5783677ff5aSBarry Smith 
5793677ff5aSBarry Smith   /* pack messages to send back to local owners */
580*30dcb7c9SBarry Smith   starts[0]    = 0;
581*30dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
582*30dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
583*30dcb7c9SBarry Smith     else starts[i] = starts[i-1];
584*30dcb7c9SBarry Smith   }
585*30dcb7c9SBarry Smith   nsends2 = nrecvs;
586*30dcb7c9SBarry Smith   nprocs  = (int*)PetscMalloc((nsends2+1)*sizeof(int));CHKPTRQ(nprocs); /* length of each message */
587*30dcb7c9SBarry Smith   cnt    = 0;
588*30dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
589*30dcb7c9SBarry Smith     nprocs[i] = 1;
590*30dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
591*30dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
592*30dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
593*30dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
594*30dcb7c9SBarry Smith       }
595*30dcb7c9SBarry Smith     }
596*30dcb7c9SBarry Smith   }
597*30dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
598*30dcb7c9SBarry Smith   sends2     = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(sends2);
599*30dcb7c9SBarry Smith   starts2    = (int*)PetscMalloc((nsends2+1)*sizeof(int));CHKPTRQ(starts2);
600*30dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
601*30dcb7c9SBarry Smith   /*
602*30dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
603*30dcb7c9SBarry Smith        (0) the number of nodes being sent back
604*30dcb7c9SBarry Smith        (1) the local node number,
605*30dcb7c9SBarry Smith        (2) the number of processors sharing it,
606*30dcb7c9SBarry Smith        (3) the processors sharing it
607*30dcb7c9SBarry Smith   */
608*30dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
609*30dcb7c9SBarry Smith     cnt = 1;
610*30dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
611*30dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
612*30dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
613*30dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
614*30dcb7c9SBarry Smith         sends2[starts2[i]]++;
615*30dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
616*30dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
617*30dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
618*30dcb7c9SBarry Smith         cnt += nownedsenders[node];
619*30dcb7c9SBarry Smith       }
620*30dcb7c9SBarry Smith     }
621*30dcb7c9SBarry Smith   }
622*30dcb7c9SBarry Smith 
623*30dcb7c9SBarry Smith   /* send the message lengths */
624*30dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
625*30dcb7c9SBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag-1,comm);CHKERRQ(ierr);
626*30dcb7c9SBarry Smith   }
627*30dcb7c9SBarry Smith 
628*30dcb7c9SBarry Smith   /* receive the message lengths */
629*30dcb7c9SBarry Smith   nrecvs2 = nsends;
630*30dcb7c9SBarry Smith   lens2   = (int*)PetscMalloc((nrecvs2+1)*sizeof(int));CHKPTRQ(lens2);
631*30dcb7c9SBarry Smith   starts3 = (int*)PetscMalloc((nrecvs2+1)*sizeof(int));CHKPTRQ(starts3);
632*30dcb7c9SBarry Smith   nt      = 0;
633*30dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
634*30dcb7c9SBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag-1,comm,&recv_status);CHKERRQ(ierr);
635*30dcb7c9SBarry Smith     nt   += lens2[i];
636*30dcb7c9SBarry Smith   }
637*30dcb7c9SBarry Smith   starts3[0] = 0;
638*30dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
639*30dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
640*30dcb7c9SBarry Smith   }
641*30dcb7c9SBarry Smith   recvs2     = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(recvs2);
642*30dcb7c9SBarry Smith   recv_waits = (MPI_Request*)PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits);
643*30dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
644*30dcb7c9SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag-2,comm,recv_waits+i);CHKERRQ(ierr);
645*30dcb7c9SBarry Smith   }
646*30dcb7c9SBarry Smith 
647*30dcb7c9SBarry Smith   /* send the messages */
648*30dcb7c9SBarry Smith   send_waits = (MPI_Request*)PetscMalloc((nsends2+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
649*30dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
650*30dcb7c9SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag-2,comm,send_waits+i);CHKERRQ(ierr);
651*30dcb7c9SBarry Smith   }
652*30dcb7c9SBarry Smith 
653*30dcb7c9SBarry Smith   /* wait on receives */
654*30dcb7c9SBarry Smith   recv_statuses = (MPI_Status*)PetscMalloc((nrecvs+1)*sizeof(MPI_Status));CHKPTRQ(recv_statuses);
655*30dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
656*30dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
657*30dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
658*30dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
659*30dcb7c9SBarry Smith 
660*30dcb7c9SBarry Smith   /* -----------------------------------  */
661*30dcb7c9SBarry Smith   cnt = 0;
662*30dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
663*30dcb7c9SBarry Smith     nt = recvs2[cnt++];
664*30dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
665*30dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
666*30dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
667*30dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
668*30dcb7c9SBarry Smith       }
669*30dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
670*30dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
671*30dcb7c9SBarry Smith     }
672*30dcb7c9SBarry Smith   }
673*30dcb7c9SBarry Smith   ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
674*30dcb7c9SBarry Smith   /* -----------------------------------  */
675*30dcb7c9SBarry Smith 
676*30dcb7c9SBarry Smith   /* count number subdomains for each local node */
677*30dcb7c9SBarry Smith   nprocs = (int*)PetscMalloc(size*sizeof(int));CHKPTRQ(nprocs);
678*30dcb7c9SBarry Smith   ierr   = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
679*30dcb7c9SBarry Smith   cnt = 0;
680*30dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
681*30dcb7c9SBarry Smith     nt = recvs2[cnt++];
682*30dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
683*30dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
684*30dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
685*30dcb7c9SBarry Smith       }
686*30dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
687*30dcb7c9SBarry Smith     }
688*30dcb7c9SBarry Smith   }
689*30dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
690*30dcb7c9SBarry Smith   *nproc    = nt;
691*30dcb7c9SBarry Smith   *procs    = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(procs);
692*30dcb7c9SBarry Smith   *numprocs = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(numprocs);
693*30dcb7c9SBarry Smith   *indices  = (int**)PetscMalloc((nt+1)*sizeof(int*));CHKPTRQ(procs);
694*30dcb7c9SBarry Smith   bprocs    = (int*)PetscMalloc(size*sizeof(int));CHKERRQ(ierr);
695*30dcb7c9SBarry Smith   cnt       = 0;
696*30dcb7c9SBarry Smith   for (i=0; i<size; i++) {
697*30dcb7c9SBarry Smith     if (nprocs[i] > 0) {
698*30dcb7c9SBarry Smith       bprocs[i]        = cnt;
699*30dcb7c9SBarry Smith       (*procs)[cnt]    = i;
700*30dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
701*30dcb7c9SBarry Smith       (*indices)[cnt]  = (int*)PetscMalloc(nprocs[i]*sizeof(int));CHKPTRQ((*indices)[cnt]);
702*30dcb7c9SBarry Smith       cnt++;
703*30dcb7c9SBarry Smith     }
704*30dcb7c9SBarry Smith   }
705*30dcb7c9SBarry Smith 
706*30dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
707*30dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
708*30dcb7c9SBarry Smith   cnt  = 0;
709*30dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
710*30dcb7c9SBarry Smith     nt = recvs2[cnt++];
711*30dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
712*30dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
713*30dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
714*30dcb7c9SBarry Smith       }
715*30dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
716*30dcb7c9SBarry Smith     }
717*30dcb7c9SBarry Smith   }
718*30dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
719*30dcb7c9SBarry Smith 
720*30dcb7c9SBarry Smith   /* -----------------------------------  */
721*30dcb7c9SBarry Smith   nt = *nproc;
722*30dcb7c9SBarry Smith   for (i=0; i<nt; i++) {
723*30dcb7c9SBarry Smith     ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
724*30dcb7c9SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
725*30dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
726*30dcb7c9SBarry Smith     }
727*30dcb7c9SBarry Smith     ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
728*30dcb7c9SBarry Smith   }
729*30dcb7c9SBarry Smith   ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
730*30dcb7c9SBarry Smith   /* -----------------------------------  */
731*30dcb7c9SBarry Smith 
732*30dcb7c9SBarry Smith 
733*30dcb7c9SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
734*30dcb7c9SBarry Smith 
735*30dcb7c9SBarry Smith   /* wait on sends */
736*30dcb7c9SBarry Smith   if (nsends2) {
737*30dcb7c9SBarry Smith     send_status = (MPI_Status*)PetscMalloc(nsends2*sizeof(MPI_Status));CHKPTRQ(send_status);
738*30dcb7c9SBarry Smith     ierr        = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
739*30dcb7c9SBarry Smith     ierr        = PetscFree(send_status);CHKERRQ(ierr);
740*30dcb7c9SBarry Smith   }
741*30dcb7c9SBarry Smith 
742*30dcb7c9SBarry Smith 
743*30dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
744*30dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
745*30dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
7463677ff5aSBarry Smith 
747bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
748bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
749bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
750*30dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
751*30dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
75289d82c54SBarry Smith 
75389d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
75489d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
7553a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
756*30dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
75789d82c54SBarry Smith   PetscFunctionReturn(0);
75889d82c54SBarry Smith }
75989d82c54SBarry Smith 
76089d82c54SBarry Smith 
76189d82c54SBarry Smith 
762bc8ff85bSBarry Smith 
763bc8ff85bSBarry Smith 
764bc8ff85bSBarry Smith 
765bc8ff85bSBarry Smith 
766bc8ff85bSBarry Smith 
767bc8ff85bSBarry Smith 
768bc8ff85bSBarry Smith 
769bc8ff85bSBarry Smith 
770bc8ff85bSBarry Smith 
771bc8ff85bSBarry Smith 
772bc8ff85bSBarry Smith 
773bc8ff85bSBarry Smith 
774bc8ff85bSBarry Smith 
775bc8ff85bSBarry Smith 
776bc8ff85bSBarry Smith 
777bc8ff85bSBarry Smith 
778