xref: /petsc/src/vec/is/utils/isltog.c (revision b0a32e0c6855ee6a6cd3495fa7da12ea9885bc5d)
1*b0a32e0cSBarry Smith /*$Id: isltog.c,v 1.59 2000/10/24 20:24:56 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__
7*b0a32e0cSBarry Smith #define __FUNC__ "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 
21273d9f13SBarry Smith     Concepts: mapping^local to global
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__
34*b0a32e0cSBarry Smith #define __FUNC__ "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 
46273d9f13SBarry Smith     Concepts: mapping^local to global
475a5d4f66SBarry Smith 
485a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
495a5d4f66SBarry Smith @*/
50*b0a32e0cSBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer 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);
57*b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
58*b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
596831982aSBarry Smith   PetscCheckSameComm(mapping,viewer);
605a5d4f66SBarry Smith 
61f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
62*b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
636831982aSBarry Smith   if (isascii) {
645a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
65*b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
666831982aSBarry Smith     }
67*b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
686831982aSBarry Smith   } else {
6929bbc08cSBarry Smith     SETERRQ1(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__
76*b0a32e0cSBarry Smith #define __FUNC__ "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 
91273d9f13SBarry Smith     Concepts: mapping^local to global
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__
113*b0a32e0cSBarry Smith #define __FUNC__ "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 
130273d9f13SBarry Smith     Concepts: mapping^local to global
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);
144*b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
145*b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
146d4bb536fSBarry Smith 
147d4bb536fSBarry Smith   (*mapping)->n       = n;
148*b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&(*mapping)->indices);CHKERRQ(ierr);
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__
160*b0a32e0cSBarry Smith #define __FUNC__ "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 .seealso: ISLocalToGlobalMappingCreate()
17390f02eecSBarry Smith @*/
17490f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
17590f02eecSBarry Smith {
176606d414cSSatish Balay   int ierr;
1773a40ed3dSBarry Smith   PetscFunctionBegin;
17890f02eecSBarry Smith   PetscValidPointer(mapping);
1793a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
18085614651SBarry Smith   if (mapping->refct < 0) {
18129bbc08cSBarry Smith     SETERRQ(1,"Mapping already destroyed");
18285614651SBarry Smith   }
18390f02eecSBarry Smith 
184606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
185606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
186*b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
187d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
1883a40ed3dSBarry Smith   PetscFunctionReturn(0);
18990f02eecSBarry Smith }
19090f02eecSBarry Smith 
1915615d1e5SSatish Balay #undef __FUNC__
192*b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingApplyIS"
19390f02eecSBarry Smith /*@
1943acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
1953acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
1963acfe500SLois Curfman McInnes     context.
19790f02eecSBarry Smith 
198b9cd556bSLois Curfman McInnes     Not collective
199b9cd556bSLois Curfman McInnes 
20090f02eecSBarry Smith     Input Parameters:
201b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
202b9cd556bSLois Curfman McInnes -   is - index set in local numbering
20390f02eecSBarry Smith 
20490f02eecSBarry Smith     Output Parameters:
20590f02eecSBarry Smith .   newis - index set in global numbering
20690f02eecSBarry Smith 
207a997ad1aSLois Curfman McInnes     Level: advanced
208a997ad1aSLois Curfman McInnes 
209273d9f13SBarry Smith     Concepts: mapping^local to global
2103acfe500SLois Curfman McInnes 
21190f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
212d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
21390f02eecSBarry Smith @*/
21490f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
21590f02eecSBarry Smith {
2163b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
2173a40ed3dSBarry Smith 
2183a40ed3dSBarry Smith   PetscFunctionBegin;
21990f02eecSBarry Smith   PetscValidPointer(mapping);
22090f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
22190f02eecSBarry Smith   PetscValidPointer(newis);
22290f02eecSBarry Smith 
2233b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
22490f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
22590f02eecSBarry Smith   idxmap = mapping->indices;
22690f02eecSBarry Smith 
227*b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
22890f02eecSBarry Smith   for (i=0; i<n; i++) {
22929bbc08cSBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i);
23090f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
23190f02eecSBarry Smith   }
2323b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
233029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
234606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
2353a40ed3dSBarry Smith   PetscFunctionReturn(0);
23690f02eecSBarry Smith }
23790f02eecSBarry Smith 
23889d82c54SBarry Smith /*MC
2393acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2403acfe500SLois Curfman McInnes    and converts them to the global numbering.
24190f02eecSBarry Smith 
242b9cd556bSLois Curfman McInnes    Not collective
243b9cd556bSLois Curfman McInnes 
244bb25748dSBarry Smith    Input Parameters:
245b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
246bb25748dSBarry Smith .  N - number of integers
247b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
248bb25748dSBarry Smith 
249bb25748dSBarry Smith    Output Parameter:
250bb25748dSBarry Smith .  out - indices in global numbering
251bb25748dSBarry Smith 
2523b9aefa3SBarry Smith    Synopsis:
2533b9aefa3SBarry Smith    ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
2543b9aefa3SBarry Smith 
255b9cd556bSLois Curfman McInnes    Notes:
256b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
257d4bb536fSBarry Smith 
258a997ad1aSLois Curfman McInnes    Level: advanced
259a997ad1aSLois Curfman McInnes 
260bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
2610752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
262d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
263bb25748dSBarry Smith 
264273d9f13SBarry Smith     Concepts: mapping^local to global
265d4bb536fSBarry Smith 
26689d82c54SBarry Smith M*/
267d4bb536fSBarry Smith 
268d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
269d4bb536fSBarry Smith 
270d4bb536fSBarry Smith #undef __FUNC__
271*b0a32e0cSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingSetUp_Private"
272d4bb536fSBarry Smith /*
273d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
274d4bb536fSBarry Smith */
275d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
276d4bb536fSBarry Smith {
277*b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
278d4bb536fSBarry Smith 
2793a40ed3dSBarry Smith   PetscFunctionBegin;
280d4bb536fSBarry Smith   end   = 0;
281d4bb536fSBarry Smith   start = 100000000;
282d4bb536fSBarry Smith 
283d4bb536fSBarry Smith   for (i=0; i<n; i++) {
284d4bb536fSBarry Smith     if (idx[i] < 0) continue;
285d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
286d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
287d4bb536fSBarry Smith   }
288d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
289d4bb536fSBarry Smith   mapping->globalstart = start;
290d4bb536fSBarry Smith   mapping->globalend   = end;
291d4bb536fSBarry Smith 
292*b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
293*b0a32e0cSBarry Smith   mapping->globals = globals;
294d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
295d4bb536fSBarry Smith     globals[i] = -1;
296d4bb536fSBarry Smith   }
297d4bb536fSBarry Smith   for (i=0; i<n; i++) {
298d4bb536fSBarry Smith     if (idx[i] < 0) continue;
299d4bb536fSBarry Smith     globals[idx[i] - start] = i;
300d4bb536fSBarry Smith   }
301d4bb536fSBarry Smith 
302*b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3033a40ed3dSBarry Smith   PetscFunctionReturn(0);
304d4bb536fSBarry Smith }
305d4bb536fSBarry Smith 
306d4bb536fSBarry Smith #undef __FUNC__
307*b0a32e0cSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingApply"
308d4bb536fSBarry Smith /*@
309a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
310a997ad1aSLois Curfman McInnes     specified with a global numbering.
311d4bb536fSBarry Smith 
312b9cd556bSLois Curfman McInnes     Not collective
313b9cd556bSLois Curfman McInnes 
314d4bb536fSBarry Smith     Input Parameters:
315b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
316d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
317d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
318d4bb536fSBarry Smith .   n - number of global indices to map
319b9cd556bSLois Curfman McInnes -   idx - global indices to map
320d4bb536fSBarry Smith 
321d4bb536fSBarry Smith     Output Parameters:
322b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
323b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
324e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
325e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
326e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
327e182c471SBarry Smith              a second time to set the values.
328d4bb536fSBarry Smith 
329b9cd556bSLois Curfman McInnes     Notes:
330b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
331d4bb536fSBarry Smith 
3320f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
3330f5bd95cSBarry Smith     array to compute these.
3340f5bd95cSBarry Smith 
335a997ad1aSLois Curfman McInnes     Level: advanced
336a997ad1aSLois Curfman McInnes 
337273d9f13SBarry Smith     Concepts: mapping^global to local
338d4bb536fSBarry Smith 
339d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
340d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
341d4bb536fSBarry Smith @*/
342d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
343987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
344d4bb536fSBarry Smith {
345d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
346d4bb536fSBarry Smith 
3473a40ed3dSBarry Smith   PetscFunctionBegin;
348d4bb536fSBarry Smith   if (!mapping->globals) {
349d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
350d4bb536fSBarry Smith   }
351d4bb536fSBarry Smith   globals = mapping->globals;
352d4bb536fSBarry Smith   start   = mapping->globalstart;
353d4bb536fSBarry Smith   end     = mapping->globalend;
354d4bb536fSBarry Smith 
355d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
356d4bb536fSBarry Smith     if (idxout) {
357d4bb536fSBarry Smith       for (i=0; i<n; i++) {
358d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
359d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
360d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
361d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
362d4bb536fSBarry Smith       }
363d4bb536fSBarry Smith     }
364d4bb536fSBarry Smith     if (nout) *nout = n;
365d4bb536fSBarry Smith   } else {
366d4bb536fSBarry Smith     if (idxout) {
367d4bb536fSBarry Smith       for (i=0; i<n; i++) {
368d4bb536fSBarry Smith         if (idx[i] < 0) continue;
369d4bb536fSBarry Smith         if (idx[i] < start) continue;
370d4bb536fSBarry Smith         if (idx[i] > end) continue;
371d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
372d4bb536fSBarry Smith         if (tmp < 0) continue;
373d4bb536fSBarry Smith         idxout[nf++] = tmp;
374d4bb536fSBarry Smith       }
375d4bb536fSBarry Smith     } else {
376d4bb536fSBarry Smith       for (i=0; i<n; i++) {
377d4bb536fSBarry Smith         if (idx[i] < 0) continue;
378d4bb536fSBarry Smith         if (idx[i] < start) continue;
379d4bb536fSBarry Smith         if (idx[i] > end) continue;
380d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
381d4bb536fSBarry Smith         if (tmp < 0) continue;
382d4bb536fSBarry Smith         nf++;
383d4bb536fSBarry Smith       }
384d4bb536fSBarry Smith     }
385d4bb536fSBarry Smith     if (nout) *nout = nf;
386d4bb536fSBarry Smith   }
387d4bb536fSBarry Smith 
3883a40ed3dSBarry Smith   PetscFunctionReturn(0);
389d4bb536fSBarry Smith }
39090f02eecSBarry Smith 
39189d82c54SBarry Smith #undef __FUNC__
392*b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingGetInfo"
39389d82c54SBarry Smith /*@C
39489d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
39589d82c54SBarry Smith      each index shared by more than one processor
39689d82c54SBarry Smith 
39789d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
39889d82c54SBarry Smith 
39989d82c54SBarry Smith     Input Parameters:
40089d82c54SBarry Smith .   mapping - the mapping from local to global indexing
40189d82c54SBarry Smith 
40289d82c54SBarry Smith     Output Parameter:
40389d82c54SBarry Smith +   nproc - number of processors that are connected to this one
40489d82c54SBarry Smith .   proc - neighboring processors
40507b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
40607b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
40789d82c54SBarry Smith 
40889d82c54SBarry Smith     Level: advanced
40989d82c54SBarry Smith 
410273d9f13SBarry Smith     Concepts: mapping^local to global
41189d82c54SBarry Smith 
41207b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
41307b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
41489d82c54SBarry Smith @*/
41530dcb7c9SBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
41689d82c54SBarry Smith {
4173a96401aSBarry Smith   int         i,n = mapping->n,ierr,Ng,ng = PETSC_DECIDE,max = 0,*lindices = mapping->indices;
4183a96401aSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc;
41924cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
42007b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
42124cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
42289d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
42330dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
42489d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
42507b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
42689d82c54SBarry Smith 
42789d82c54SBarry Smith   PetscFunctionBegin;
42824cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
42924cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
43024cf384cSBarry Smith   if (size == 1) {
43124cf384cSBarry Smith     *nproc         = 0;
43224cf384cSBarry Smith     *procs         = PETSC_NULL;
433*b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
4341e2105dcSBarry Smith     (*numprocs)[0] = 0;
435*b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
4361e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
43724cf384cSBarry Smith     PetscFunctionReturn(0);
43824cf384cSBarry Smith   }
43924cf384cSBarry Smith 
440*b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
44107b52d57SBarry Smith 
4423677ff5aSBarry Smith   /*
4433677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
4443677ff5aSBarry Smith 
4453677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
4463677ff5aSBarry Smith            numbering, just for this routine.
4473677ff5aSBarry Smith 
4483677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
4493677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
4503677ff5aSBarry Smith 
4513677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
4523677ff5aSBarry Smith 
4533677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
4543677ff5aSBarry Smith            local subdomain
4553677ff5aSBarry Smith   */
45624cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
45724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
45824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
45989d82c54SBarry Smith 
46089d82c54SBarry Smith   for (i=0; i<n; i++) {
46189d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
46289d82c54SBarry Smith   }
46389d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
46478058e43SBarry Smith   Ng++;
46589d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
46689d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
467bc8ff85bSBarry Smith   scale  = Ng/size + 1;
468a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
469caba0dd0SBarry Smith   rstart = scale*rank;
47089d82c54SBarry Smith 
47189d82c54SBarry Smith   /* determine ownership ranges of global indices */
472*b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
4732880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
47489d82c54SBarry Smith 
47589d82c54SBarry Smith   /* determine owners of each local node  */
476*b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
47789d82c54SBarry Smith   for (i=0; i<n; i++) {
4783677ff5aSBarry Smith     proc              = lindices[i]/scale; /* processor that globally owns this index */
4793677ff5aSBarry Smith     nprocs[size+proc] = 1;                 /* processor globally owns at least one of ours */
4803677ff5aSBarry Smith     owner[i]          = proc;
4813677ff5aSBarry Smith     nprocs[proc]++;                        /* count of how many that processor globally owns of ours */
48289d82c54SBarry Smith   }
48389d82c54SBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i];
484*b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
48589d82c54SBarry Smith 
48689d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
487*b0a32e0cSBarry Smith   ierr = PetscMalloc(2*size*sizeof(int),&work);CHKERRQ(ierr);
48889d82c54SBarry Smith   ierr   = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
48989d82c54SBarry Smith   nmax   = work[rank];
49089d82c54SBarry Smith   nrecvs = work[size+rank];
49189d82c54SBarry Smith   ierr   = PetscFree(work);CHKERRQ(ierr);
492*b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
49389d82c54SBarry Smith 
49489d82c54SBarry Smith   /* post receives for owned rows */
495*b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
496*b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
49789d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
49824cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
49989d82c54SBarry Smith   }
50089d82c54SBarry Smith 
50189d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
502*b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
503*b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
50489d82c54SBarry Smith   starts[0]  = 0;
50530dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
50689d82c54SBarry Smith   for (i=0; i<n; i++) {
50789d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
50830dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
50989d82c54SBarry Smith   }
51089d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
51189d82c54SBarry Smith   starts[0]  = 0;
51230dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
51389d82c54SBarry Smith 
51489d82c54SBarry Smith   /* send the messages */
515*b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
516*b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
51789d82c54SBarry Smith   cnt = 0;
51889d82c54SBarry Smith   for (i=0; i<size; i++) {
51989d82c54SBarry Smith     if (nprocs[i]) {
52024cf384cSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
52130dcb7c9SBarry Smith       dest[cnt] = i;
52289d82c54SBarry Smith       cnt++;
52389d82c54SBarry Smith     }
52489d82c54SBarry Smith   }
52589d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
52689d82c54SBarry Smith 
52789d82c54SBarry Smith   /* wait on receives */
528*b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
52989d82c54SBarry Smith   len  = source + nrecvs;
53089d82c54SBarry Smith   cnt  = nrecvs;
531*b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
532caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
53389d82c54SBarry Smith   while (cnt) {
53489d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
53589d82c54SBarry Smith     /* unpack receives into our local space */
53689d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
53789d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
53830dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
539caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
54030dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
54189d82c54SBarry Smith     cnt--;
54289d82c54SBarry Smith   }
54389d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
54489d82c54SBarry Smith 
54530dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
546bc8ff85bSBarry Smith   nowned  = 0;
547bc8ff85bSBarry Smith   nownedm = 0;
548bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
549bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
550bc8ff85bSBarry Smith   }
551bc8ff85bSBarry Smith 
552bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
553*b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
554*b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
555bc8ff85bSBarry Smith   starts[0] = 0;
556bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
557bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
558bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
559bc8ff85bSBarry Smith   }
560bc8ff85bSBarry Smith 
56130dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
562bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
563bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
56430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
565bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
566bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
567bc8ff85bSBarry Smith       }
568bc8ff85bSBarry Smith     }
569bc8ff85bSBarry Smith   }
570bc8ff85bSBarry Smith 
57107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
57230dcb7c9SBarry Smith     starts[0]    = 0;
57330dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
57430dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
57530dcb7c9SBarry Smith       else starts[i] = starts[i-1];
57630dcb7c9SBarry Smith     }
57730dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
57830dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
57930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
58030dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
58130dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
58230dcb7c9SBarry Smith         }
58330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
58430dcb7c9SBarry Smith       }
58530dcb7c9SBarry Smith     }
58630dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
58707b52d57SBarry Smith   }/* -----------------------------------  */
58830dcb7c9SBarry Smith 
5893677ff5aSBarry Smith   /* wait on original sends */
5903a96401aSBarry Smith   if (nsends) {
591*b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
5923a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
5933a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
5943a96401aSBarry Smith   }
59589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
5963a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
5973677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
5983677ff5aSBarry Smith 
5993677ff5aSBarry Smith   /* pack messages to send back to local owners */
60030dcb7c9SBarry Smith   starts[0]    = 0;
60130dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
60230dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
60330dcb7c9SBarry Smith     else starts[i] = starts[i-1];
60430dcb7c9SBarry Smith   }
60530dcb7c9SBarry Smith   nsends2 = nrecvs;
606*b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
60730dcb7c9SBarry Smith   cnt     = 0;
60830dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
60930dcb7c9SBarry Smith     nprocs[i] = 1;
61030dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
61130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
61230dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
61330dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
61430dcb7c9SBarry Smith       }
61530dcb7c9SBarry Smith     }
61630dcb7c9SBarry Smith   }
61730dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
618*b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
619*b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
62030dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
62130dcb7c9SBarry Smith   /*
62230dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
62330dcb7c9SBarry Smith        (0) the number of nodes being sent back
62430dcb7c9SBarry Smith        (1) the local node number,
62530dcb7c9SBarry Smith        (2) the number of processors sharing it,
62630dcb7c9SBarry Smith        (3) the processors sharing it
62730dcb7c9SBarry Smith   */
62830dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
62930dcb7c9SBarry Smith     cnt = 1;
63030dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
63130dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
63230dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
63330dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
63430dcb7c9SBarry Smith         sends2[starts2[i]]++;
63530dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
63630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
63730dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
63830dcb7c9SBarry Smith         cnt += nownedsenders[node];
63930dcb7c9SBarry Smith       }
64030dcb7c9SBarry Smith     }
64130dcb7c9SBarry Smith   }
64230dcb7c9SBarry Smith 
64330dcb7c9SBarry Smith   /* send the message lengths */
64430dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
64524cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
64630dcb7c9SBarry Smith   }
64730dcb7c9SBarry Smith 
64830dcb7c9SBarry Smith   /* receive the message lengths */
64930dcb7c9SBarry Smith   nrecvs2 = nsends;
650*b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
651*b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
65230dcb7c9SBarry Smith   nt      = 0;
65330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
65424cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
65530dcb7c9SBarry Smith     nt   += lens2[i];
65630dcb7c9SBarry Smith   }
65730dcb7c9SBarry Smith   starts3[0] = 0;
65830dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
65930dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
66030dcb7c9SBarry Smith   }
661*b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
662*b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
66352b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
66424cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
66530dcb7c9SBarry Smith   }
66630dcb7c9SBarry Smith 
66730dcb7c9SBarry Smith   /* send the messages */
668*b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
66930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
67024cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
67130dcb7c9SBarry Smith   }
67230dcb7c9SBarry Smith 
67330dcb7c9SBarry Smith   /* wait on receives */
674*b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
67530dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
67630dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
67730dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
67830dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
67930dcb7c9SBarry Smith 
68007b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
68130dcb7c9SBarry Smith     cnt = 0;
68230dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
68330dcb7c9SBarry Smith       nt = recvs2[cnt++];
68430dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
68530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
68630dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
68730dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
68830dcb7c9SBarry Smith         }
68930dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
69030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
69130dcb7c9SBarry Smith       }
69230dcb7c9SBarry Smith     }
69330dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
69407b52d57SBarry Smith   } /* -----------------------------------  */
69530dcb7c9SBarry Smith 
69630dcb7c9SBarry Smith   /* count number subdomains for each local node */
697*b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
69830dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
69930dcb7c9SBarry Smith   cnt  = 0;
70030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
70130dcb7c9SBarry Smith     nt = recvs2[cnt++];
70230dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
70330dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
70430dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
70530dcb7c9SBarry Smith       }
70630dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
70730dcb7c9SBarry Smith     }
70830dcb7c9SBarry Smith   }
70930dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
71030dcb7c9SBarry Smith   *nproc    = nt;
711*b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
712*b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
713*b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
714*b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
71530dcb7c9SBarry Smith   cnt       = 0;
71630dcb7c9SBarry Smith   for (i=0; i<size; i++) {
71730dcb7c9SBarry Smith     if (nprocs[i] > 0) {
71830dcb7c9SBarry Smith       bprocs[i]        = cnt;
71930dcb7c9SBarry Smith       (*procs)[cnt]    = i;
72030dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
721*b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
72230dcb7c9SBarry Smith       cnt++;
72330dcb7c9SBarry Smith     }
72430dcb7c9SBarry Smith   }
72530dcb7c9SBarry Smith 
72630dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
72730dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
72830dcb7c9SBarry Smith   cnt  = 0;
72930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
73030dcb7c9SBarry Smith     nt = recvs2[cnt++];
73130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
73230dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
73330dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
73430dcb7c9SBarry Smith       }
73530dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
73630dcb7c9SBarry Smith     }
73730dcb7c9SBarry Smith   }
73830dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
73907b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
74030dcb7c9SBarry Smith 
74107b52d57SBarry Smith   /* sort the node indexing by their global numbers */
74207b52d57SBarry Smith   nt = *nproc;
74307b52d57SBarry Smith   for (i=0; i<nt; i++) {
744*b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
74507b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
74607b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
74707b52d57SBarry Smith     }
74807b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
74907b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
75007b52d57SBarry Smith   }
75107b52d57SBarry Smith 
75207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
75330dcb7c9SBarry Smith     nt = *nproc;
75430dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
75530dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
75630dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
75730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
75830dcb7c9SBarry Smith       }
75930dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
76030dcb7c9SBarry Smith     }
76130dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
76207b52d57SBarry Smith   } /* -----------------------------------  */
76330dcb7c9SBarry Smith 
76430dcb7c9SBarry Smith   /* wait on sends */
76530dcb7c9SBarry Smith   if (nsends2) {
766*b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
76730dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
76830dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
76930dcb7c9SBarry Smith   }
77030dcb7c9SBarry Smith 
77130dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
77230dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
77330dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
7743677ff5aSBarry Smith 
775bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
776bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
777bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
77830dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
77930dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
78089d82c54SBarry Smith 
78189d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
78289d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
7833a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
78430dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
78524cf384cSBarry Smith 
78624cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
78724cf384cSBarry Smith   first_procs    = (*procs)[0];
78824cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
78924cf384cSBarry Smith   first_indices  = (*indices)[0];
79024cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
79124cf384cSBarry Smith     if ((*procs)[i] == rank) {
79224cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
79324cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
79424cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
79524cf384cSBarry Smith       (*procs)[i]    = first_procs;
79624cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
79724cf384cSBarry Smith       (*indices)[i]  = first_indices;
79824cf384cSBarry Smith       break;
79924cf384cSBarry Smith     }
80024cf384cSBarry Smith   }
80124cf384cSBarry Smith 
80289d82c54SBarry Smith   PetscFunctionReturn(0);
80389d82c54SBarry Smith }
80489d82c54SBarry Smith 
80507b52d57SBarry Smith #undef __FUNC__
806*b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingRestoreInfo"
80707b52d57SBarry Smith /*@C
80807b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
80989d82c54SBarry Smith 
81007b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
81107b52d57SBarry Smith 
81207b52d57SBarry Smith     Input Parameters:
81307b52d57SBarry Smith .   mapping - the mapping from local to global indexing
81407b52d57SBarry Smith 
81507b52d57SBarry Smith     Output Parameter:
81607b52d57SBarry Smith +   nproc - number of processors that are connected to this one
81707b52d57SBarry Smith .   proc - neighboring processors
81807b52d57SBarry Smith .   numproc - number of indices for each processor
81907b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
82007b52d57SBarry Smith 
82107b52d57SBarry Smith     Level: advanced
82207b52d57SBarry Smith 
82307b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
82407b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
82507b52d57SBarry Smith @*/
82607b52d57SBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
82707b52d57SBarry Smith {
82807b52d57SBarry Smith   int ierr,i;
82907b52d57SBarry Smith 
83007b52d57SBarry Smith   PetscFunctionBegin;
83100ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
83200ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
83300ff320aSBarry Smith   if (*indices) {
83400ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
83500ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
83624cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
83707b52d57SBarry Smith     }
83807b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
83924cf384cSBarry Smith   }
84007b52d57SBarry Smith   PetscFunctionReturn(0);
84107b52d57SBarry Smith }
84289d82c54SBarry Smith 
843bc8ff85bSBarry Smith 
844bc8ff85bSBarry Smith 
845bc8ff85bSBarry Smith 
846bc8ff85bSBarry Smith 
847bc8ff85bSBarry Smith 
848bc8ff85bSBarry Smith 
849bc8ff85bSBarry Smith 
850bc8ff85bSBarry Smith 
851bc8ff85bSBarry Smith 
852bc8ff85bSBarry Smith 
853bc8ff85bSBarry Smith 
854bc8ff85bSBarry Smith 
855bc8ff85bSBarry Smith 
856bc8ff85bSBarry Smith 
857bc8ff85bSBarry Smith 
858bc8ff85bSBarry Smith 
85924cf384cSBarry Smith 
860