xref: /petsc/src/vec/is/utils/isltog.c (revision 8e58c17d92fd182847eda150482aa81aa9e1fb44)
173f4d377SMatthew Knepley /*$Id: isltog.c,v 1.65 2001/05/21 14:16:29 bsmith Exp $*/
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 
6*8e58c17dSMatthew Knepley EXTERN int VecInitializePackage(char *);
7*8e58c17dSMatthew Knepley 
84a2ae208SSatish Balay #undef __FUNCT__
94a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
103b9aefa3SBarry Smith /*@C
113b9aefa3SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping.
123b9aefa3SBarry Smith 
133b9aefa3SBarry Smith     Not Collective
143b9aefa3SBarry Smith 
153b9aefa3SBarry Smith     Input Parameter:
163b9aefa3SBarry Smith .   ltog - local to global mapping
173b9aefa3SBarry Smith 
183b9aefa3SBarry Smith     Output Parameter:
193b9aefa3SBarry Smith .   n - the number of entries in the local mapping
203b9aefa3SBarry Smith 
213b9aefa3SBarry Smith     Level: advanced
223b9aefa3SBarry Smith 
23273d9f13SBarry Smith     Concepts: mapping^local to global
243b9aefa3SBarry Smith 
253b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
263b9aefa3SBarry Smith @*/
273b9aefa3SBarry Smith int ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,int *n)
283b9aefa3SBarry Smith {
293b9aefa3SBarry Smith   PetscFunctionBegin;
303b9aefa3SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
313b9aefa3SBarry Smith   *n = mapping->n;
323b9aefa3SBarry Smith   PetscFunctionReturn(0);
333b9aefa3SBarry Smith }
343b9aefa3SBarry Smith 
354a2ae208SSatish Balay #undef __FUNCT__
364a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
375a5d4f66SBarry Smith /*@C
385a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
395a5d4f66SBarry Smith 
40b9cd556bSLois Curfman McInnes     Not Collective
41b9cd556bSLois Curfman McInnes 
425a5d4f66SBarry Smith     Input Parameters:
433b9aefa3SBarry Smith +   ltog - local to global mapping
443b9aefa3SBarry Smith -   viewer - viewer
455a5d4f66SBarry Smith 
46a997ad1aSLois Curfman McInnes     Level: advanced
47a997ad1aSLois Curfman McInnes 
48273d9f13SBarry Smith     Concepts: mapping^local to global
495a5d4f66SBarry Smith 
505a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
515a5d4f66SBarry Smith @*/
52b0a32e0cSBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
535a5d4f66SBarry Smith {
54f1af5d2fSBarry Smith   int        i,ierr,rank;
556831982aSBarry Smith   PetscTruth isascii;
565a5d4f66SBarry Smith 
575a5d4f66SBarry Smith   PetscFunctionBegin;
586831982aSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
59b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
60b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
615a5d4f66SBarry Smith 
62f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
63b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
646831982aSBarry Smith   if (isascii) {
655a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
66b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
676831982aSBarry Smith     }
68b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
696831982aSBarry Smith   } else {
7029bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
715a5d4f66SBarry Smith   }
725a5d4f66SBarry Smith 
735a5d4f66SBarry Smith   PetscFunctionReturn(0);
745a5d4f66SBarry Smith }
755a5d4f66SBarry Smith 
764a2ae208SSatish Balay #undef __FUNCT__
774a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
782bdab257SBarry Smith /*@C
792bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
802bdab257SBarry Smith     ordering and a global parallel ordering.
812bdab257SBarry Smith 
820f5bd95cSBarry Smith     Not collective
83b9cd556bSLois Curfman McInnes 
84a997ad1aSLois Curfman McInnes     Input Parameter:
852bdab257SBarry Smith .   is - index set containing the global numbers for each local
862bdab257SBarry Smith 
87a997ad1aSLois Curfman McInnes     Output Parameter:
882bdab257SBarry Smith .   mapping - new mapping data structure
892bdab257SBarry Smith 
90a997ad1aSLois Curfman McInnes     Level: advanced
91a997ad1aSLois Curfman McInnes 
92273d9f13SBarry Smith     Concepts: mapping^local to global
932bdab257SBarry Smith 
942bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
952bdab257SBarry Smith @*/
962bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
972bdab257SBarry Smith {
982bdab257SBarry Smith   int      n,*indices,ierr;
992bdab257SBarry Smith   MPI_Comm comm;
1003a40ed3dSBarry Smith 
1013a40ed3dSBarry Smith   PetscFunctionBegin;
1022bdab257SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
1032bdab257SBarry Smith 
1042bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1053b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1062bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1072bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
1082bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1092bdab257SBarry Smith 
1103a40ed3dSBarry Smith   PetscFunctionReturn(0);
1112bdab257SBarry Smith }
1125a5d4f66SBarry Smith 
1134a2ae208SSatish Balay #undef __FUNCT__
1144a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
115dd7157adSSatish Balay /*@C
11690f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
11790f02eecSBarry Smith     ordering and a global parallel ordering.
1182362add9SBarry Smith 
11989d82c54SBarry Smith     Not Collective, but communicator may have more than one process
120b9cd556bSLois Curfman McInnes 
1212362add9SBarry Smith     Input Parameters:
12289d82c54SBarry Smith +   comm - MPI communicator
12390f02eecSBarry Smith .   n - the number of local elements
124b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
1252362add9SBarry Smith 
126a997ad1aSLois Curfman McInnes     Output Parameter:
12790f02eecSBarry Smith .   mapping - new mapping data structure
1282362add9SBarry Smith 
129a997ad1aSLois Curfman McInnes     Level: advanced
130a997ad1aSLois Curfman McInnes 
131273d9f13SBarry Smith     Concepts: mapping^local to global
1322362add9SBarry Smith 
1332bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
1342362add9SBarry Smith @*/
135987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1362362add9SBarry Smith {
137549d3d68SSatish Balay   int ierr;
138549d3d68SSatish Balay 
1393a40ed3dSBarry Smith   PetscFunctionBegin;
14090f02eecSBarry Smith   PetscValidIntPointer(indices);
14190f02eecSBarry Smith   PetscValidPointer(mapping);
142*8e58c17dSMatthew Knepley   *mapping = PETSC_NULL;
143*8e58c17dSMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
144*8e58c17dSMatthew Knepley   ierr = VecInitializePackage(PETSC_NULL);                                                                CHKERRQ(ierr);
145*8e58c17dSMatthew Knepley #endif
1462362add9SBarry Smith 
1473f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1483f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
149b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
150b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
151d4bb536fSBarry Smith 
152d4bb536fSBarry Smith   (*mapping)->n       = n;
153b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&(*mapping)->indices);CHKERRQ(ierr);
154549d3d68SSatish Balay   ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr);
155d4bb536fSBarry Smith 
156d4bb536fSBarry Smith   /*
157d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
158d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
159d4bb536fSBarry Smith   */
160d4bb536fSBarry Smith   (*mapping)->globals = 0;
1613a40ed3dSBarry Smith   PetscFunctionReturn(0);
1622362add9SBarry Smith }
1632362add9SBarry Smith 
1644a2ae208SSatish Balay #undef __FUNCT__
1654a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
166323b833fSBarry Smith /*@C
167323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
168323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
169323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
170323b833fSBarry Smith 
171323b833fSBarry Smith     Not Collective, but communicator may have more than one process
172323b833fSBarry Smith 
173323b833fSBarry Smith     Input Parameters:
174323b833fSBarry Smith +    inmap - original point-wise mapping
175323b833fSBarry Smith -    bs - block size
176323b833fSBarry Smith 
177323b833fSBarry Smith     Output Parameter:
178323b833fSBarry Smith .   outmap - block based mapping
179323b833fSBarry Smith 
180323b833fSBarry Smith     Level: advanced
181323b833fSBarry Smith 
182323b833fSBarry Smith     Concepts: mapping^local to global
183323b833fSBarry Smith 
184323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
185323b833fSBarry Smith @*/
186323b833fSBarry Smith int ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
187323b833fSBarry Smith {
188323b833fSBarry Smith   int ierr,*ii,i,n;
189323b833fSBarry Smith 
190323b833fSBarry Smith   PetscFunctionBegin;
191323b833fSBarry Smith 
192323b833fSBarry Smith   if (bs > 1) {
193323b833fSBarry Smith     n    = inmap->n/bs;
194323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
195323b833fSBarry Smith     for (i=0; i<n; i++) {
196b8ee7809SBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
197323b833fSBarry Smith     }
198323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
199323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
200323b833fSBarry Smith   } else {
201323b833fSBarry Smith     *outmap = inmap;
202323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
203323b833fSBarry Smith   }
204323b833fSBarry Smith   PetscFunctionReturn(0);
205323b833fSBarry Smith }
206323b833fSBarry Smith 
2074a2ae208SSatish Balay #undef __FUNCT__
2084a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
20990f02eecSBarry Smith /*@
21090f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
21190f02eecSBarry Smith    ordering and a global parallel ordering.
21290f02eecSBarry Smith 
2130f5bd95cSBarry Smith    Note Collective
214b9cd556bSLois Curfman McInnes 
21590f02eecSBarry Smith    Input Parameters:
21690f02eecSBarry Smith .  mapping - mapping data structure
21790f02eecSBarry Smith 
218a997ad1aSLois Curfman McInnes    Level: advanced
219a997ad1aSLois Curfman McInnes 
2203acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
22190f02eecSBarry Smith @*/
22290f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
22390f02eecSBarry Smith {
224606d414cSSatish Balay   int ierr;
2253a40ed3dSBarry Smith   PetscFunctionBegin;
22690f02eecSBarry Smith   PetscValidPointer(mapping);
2273a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
22885614651SBarry Smith   if (mapping->refct < 0) {
22929bbc08cSBarry Smith     SETERRQ(1,"Mapping already destroyed");
23085614651SBarry Smith   }
23190f02eecSBarry Smith 
232606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
233606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
234b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
235d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2363a40ed3dSBarry Smith   PetscFunctionReturn(0);
23790f02eecSBarry Smith }
23890f02eecSBarry Smith 
2394a2ae208SSatish Balay #undef __FUNCT__
2404a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
24190f02eecSBarry Smith /*@
2423acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2433acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2443acfe500SLois Curfman McInnes     context.
24590f02eecSBarry Smith 
246b9cd556bSLois Curfman McInnes     Not collective
247b9cd556bSLois Curfman McInnes 
24890f02eecSBarry Smith     Input Parameters:
249b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
250b9cd556bSLois Curfman McInnes -   is - index set in local numbering
25190f02eecSBarry Smith 
25290f02eecSBarry Smith     Output Parameters:
25390f02eecSBarry Smith .   newis - index set in global numbering
25490f02eecSBarry Smith 
255a997ad1aSLois Curfman McInnes     Level: advanced
256a997ad1aSLois Curfman McInnes 
257273d9f13SBarry Smith     Concepts: mapping^local to global
2583acfe500SLois Curfman McInnes 
25990f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
260d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
26190f02eecSBarry Smith @*/
26290f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
26390f02eecSBarry Smith {
2643b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
2653a40ed3dSBarry Smith 
2663a40ed3dSBarry Smith   PetscFunctionBegin;
26790f02eecSBarry Smith   PetscValidPointer(mapping);
26890f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
26990f02eecSBarry Smith   PetscValidPointer(newis);
27090f02eecSBarry Smith 
2713b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
27290f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
27390f02eecSBarry Smith   idxmap = mapping->indices;
27490f02eecSBarry Smith 
275b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
27690f02eecSBarry Smith   for (i=0; i<n; i++) {
27729bbc08cSBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i);
27890f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
27990f02eecSBarry Smith   }
2803b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
281029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
282606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
2833a40ed3dSBarry Smith   PetscFunctionReturn(0);
28490f02eecSBarry Smith }
28590f02eecSBarry Smith 
28689d82c54SBarry Smith /*MC
2873acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2883acfe500SLois Curfman McInnes    and converts them to the global numbering.
28990f02eecSBarry Smith 
290b9cd556bSLois Curfman McInnes    Not collective
291b9cd556bSLois Curfman McInnes 
292bb25748dSBarry Smith    Input Parameters:
293b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
294bb25748dSBarry Smith .  N - number of integers
295b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
296bb25748dSBarry Smith 
297bb25748dSBarry Smith    Output Parameter:
298bb25748dSBarry Smith .  out - indices in global numbering
299bb25748dSBarry Smith 
3003b9aefa3SBarry Smith    Synopsis:
301216e7ba4SBarry Smith    int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
3023b9aefa3SBarry Smith 
303b9cd556bSLois Curfman McInnes    Notes:
304b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
305d4bb536fSBarry Smith 
306a997ad1aSLois Curfman McInnes    Level: advanced
307a997ad1aSLois Curfman McInnes 
308bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3090752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
310d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
311bb25748dSBarry Smith 
312273d9f13SBarry Smith     Concepts: mapping^local to global
313d4bb536fSBarry Smith 
31489d82c54SBarry Smith M*/
315d4bb536fSBarry Smith 
316d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
317d4bb536fSBarry Smith 
3184a2ae208SSatish Balay #undef __FUNCT__
3194a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
320d4bb536fSBarry Smith /*
321d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
322d4bb536fSBarry Smith */
323d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
324d4bb536fSBarry Smith {
325b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
326d4bb536fSBarry Smith 
3273a40ed3dSBarry Smith   PetscFunctionBegin;
328d4bb536fSBarry Smith   end   = 0;
329d4bb536fSBarry Smith   start = 100000000;
330d4bb536fSBarry Smith 
331d4bb536fSBarry Smith   for (i=0; i<n; i++) {
332d4bb536fSBarry Smith     if (idx[i] < 0) continue;
333d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
334d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
335d4bb536fSBarry Smith   }
336d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
337d4bb536fSBarry Smith   mapping->globalstart = start;
338d4bb536fSBarry Smith   mapping->globalend   = end;
339d4bb536fSBarry Smith 
340b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
341b0a32e0cSBarry Smith   mapping->globals = globals;
342d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
343d4bb536fSBarry Smith     globals[i] = -1;
344d4bb536fSBarry Smith   }
345d4bb536fSBarry Smith   for (i=0; i<n; i++) {
346d4bb536fSBarry Smith     if (idx[i] < 0) continue;
347d4bb536fSBarry Smith     globals[idx[i] - start] = i;
348d4bb536fSBarry Smith   }
349d4bb536fSBarry Smith 
350b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3513a40ed3dSBarry Smith   PetscFunctionReturn(0);
352d4bb536fSBarry Smith }
353d4bb536fSBarry Smith 
3544a2ae208SSatish Balay #undef __FUNCT__
3554a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
356d4bb536fSBarry Smith /*@
357a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
358a997ad1aSLois Curfman McInnes     specified with a global numbering.
359d4bb536fSBarry Smith 
360b9cd556bSLois Curfman McInnes     Not collective
361b9cd556bSLois Curfman McInnes 
362d4bb536fSBarry Smith     Input Parameters:
363b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
364d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
365d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
366d4bb536fSBarry Smith .   n - number of global indices to map
367b9cd556bSLois Curfman McInnes -   idx - global indices to map
368d4bb536fSBarry Smith 
369d4bb536fSBarry Smith     Output Parameters:
370b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
371b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
372e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
373e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
374e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
375e182c471SBarry Smith              a second time to set the values.
376d4bb536fSBarry Smith 
377b9cd556bSLois Curfman McInnes     Notes:
378b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
379d4bb536fSBarry Smith 
3800f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
3810f5bd95cSBarry Smith     array to compute these.
3820f5bd95cSBarry Smith 
383a997ad1aSLois Curfman McInnes     Level: advanced
384a997ad1aSLois Curfman McInnes 
385273d9f13SBarry Smith     Concepts: mapping^global to local
386d4bb536fSBarry Smith 
387d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
388d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
389d4bb536fSBarry Smith @*/
390d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
391987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
392d4bb536fSBarry Smith {
393d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
394d4bb536fSBarry Smith 
3953a40ed3dSBarry Smith   PetscFunctionBegin;
396d4bb536fSBarry Smith   if (!mapping->globals) {
397d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
398d4bb536fSBarry Smith   }
399d4bb536fSBarry Smith   globals = mapping->globals;
400d4bb536fSBarry Smith   start   = mapping->globalstart;
401d4bb536fSBarry Smith   end     = mapping->globalend;
402d4bb536fSBarry Smith 
403d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
404d4bb536fSBarry Smith     if (idxout) {
405d4bb536fSBarry Smith       for (i=0; i<n; i++) {
406d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
407d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
408d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
409d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
410d4bb536fSBarry Smith       }
411d4bb536fSBarry Smith     }
412d4bb536fSBarry Smith     if (nout) *nout = n;
413d4bb536fSBarry Smith   } else {
414d4bb536fSBarry Smith     if (idxout) {
415d4bb536fSBarry Smith       for (i=0; i<n; i++) {
416d4bb536fSBarry Smith         if (idx[i] < 0) continue;
417d4bb536fSBarry Smith         if (idx[i] < start) continue;
418d4bb536fSBarry Smith         if (idx[i] > end) continue;
419d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
420d4bb536fSBarry Smith         if (tmp < 0) continue;
421d4bb536fSBarry Smith         idxout[nf++] = tmp;
422d4bb536fSBarry Smith       }
423d4bb536fSBarry Smith     } else {
424d4bb536fSBarry Smith       for (i=0; i<n; i++) {
425d4bb536fSBarry Smith         if (idx[i] < 0) continue;
426d4bb536fSBarry Smith         if (idx[i] < start) continue;
427d4bb536fSBarry Smith         if (idx[i] > end) continue;
428d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
429d4bb536fSBarry Smith         if (tmp < 0) continue;
430d4bb536fSBarry Smith         nf++;
431d4bb536fSBarry Smith       }
432d4bb536fSBarry Smith     }
433d4bb536fSBarry Smith     if (nout) *nout = nf;
434d4bb536fSBarry Smith   }
435d4bb536fSBarry Smith 
4363a40ed3dSBarry Smith   PetscFunctionReturn(0);
437d4bb536fSBarry Smith }
43890f02eecSBarry Smith 
4394a2ae208SSatish Balay #undef __FUNCT__
4404a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
44189d82c54SBarry Smith /*@C
44289d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
44389d82c54SBarry Smith      each index shared by more than one processor
44489d82c54SBarry Smith 
44589d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
44689d82c54SBarry Smith 
44789d82c54SBarry Smith     Input Parameters:
44889d82c54SBarry Smith .   mapping - the mapping from local to global indexing
44989d82c54SBarry Smith 
45089d82c54SBarry Smith     Output Parameter:
45189d82c54SBarry Smith +   nproc - number of processors that are connected to this one
45289d82c54SBarry Smith .   proc - neighboring processors
45307b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
45407b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
45589d82c54SBarry Smith 
45689d82c54SBarry Smith     Level: advanced
45789d82c54SBarry Smith 
458273d9f13SBarry Smith     Concepts: mapping^local to global
45989d82c54SBarry Smith 
46007b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
46107b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
46289d82c54SBarry Smith @*/
46330dcb7c9SBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
46489d82c54SBarry Smith {
465fa7fbcffSSatish Balay   int         i,n = mapping->n,ierr,Ng,ng,max = 0,*lindices = mapping->indices;
4663a96401aSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc;
46724cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
46807b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
46924cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
47089d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
47130dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
47289d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
47307b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
47489d82c54SBarry Smith 
47589d82c54SBarry Smith   PetscFunctionBegin;
47624cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
47724cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
47824cf384cSBarry Smith   if (size == 1) {
47924cf384cSBarry Smith     *nproc         = 0;
48024cf384cSBarry Smith     *procs         = PETSC_NULL;
481b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
4821e2105dcSBarry Smith     (*numprocs)[0] = 0;
483b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
4841e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
48524cf384cSBarry Smith     PetscFunctionReturn(0);
48624cf384cSBarry Smith   }
48724cf384cSBarry Smith 
488b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
48907b52d57SBarry Smith 
4903677ff5aSBarry Smith   /*
4913677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
4923677ff5aSBarry Smith 
4933677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
4943677ff5aSBarry Smith            numbering, just for this routine.
4953677ff5aSBarry Smith 
4963677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
4973677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
4983677ff5aSBarry Smith 
4993677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
5003677ff5aSBarry Smith 
5013677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
5023677ff5aSBarry Smith            local subdomain
5033677ff5aSBarry Smith   */
50424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
50524cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
50624cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
50789d82c54SBarry Smith 
50889d82c54SBarry Smith   for (i=0; i<n; i++) {
50989d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
51089d82c54SBarry Smith   }
51189d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
51278058e43SBarry Smith   Ng++;
51389d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
51489d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
515bc8ff85bSBarry Smith   scale  = Ng/size + 1;
516a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
517caba0dd0SBarry Smith   rstart = scale*rank;
51889d82c54SBarry Smith 
51989d82c54SBarry Smith   /* determine ownership ranges of global indices */
520b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5212880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
52289d82c54SBarry Smith 
52389d82c54SBarry Smith   /* determine owners of each local node  */
524b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
52589d82c54SBarry Smith   for (i=0; i<n; i++) {
5263677ff5aSBarry Smith     proc              = lindices[i]/scale; /* processor that globally owns this index */
5273677ff5aSBarry Smith     nprocs[size+proc] = 1;                 /* processor globally owns at least one of ours */
5283677ff5aSBarry Smith     owner[i]          = proc;
5293677ff5aSBarry Smith     nprocs[proc]++;                        /* count of how many that processor globally owns of ours */
53089d82c54SBarry Smith   }
53189d82c54SBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i];
532b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
53389d82c54SBarry Smith 
53489d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
535b0a32e0cSBarry Smith   ierr = PetscMalloc(2*size*sizeof(int),&work);CHKERRQ(ierr);
53689d82c54SBarry Smith   ierr   = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
53789d82c54SBarry Smith   nmax   = work[rank];
53889d82c54SBarry Smith   nrecvs = work[size+rank];
53989d82c54SBarry Smith   ierr   = PetscFree(work);CHKERRQ(ierr);
540b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
54189d82c54SBarry Smith 
54289d82c54SBarry Smith   /* post receives for owned rows */
543b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
544b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
54589d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
54624cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
54789d82c54SBarry Smith   }
54889d82c54SBarry Smith 
54989d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
550b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
551b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
55289d82c54SBarry Smith   starts[0]  = 0;
55330dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
55489d82c54SBarry Smith   for (i=0; i<n; i++) {
55589d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
55630dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
55789d82c54SBarry Smith   }
55889d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
55989d82c54SBarry Smith   starts[0]  = 0;
56030dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
56189d82c54SBarry Smith 
56289d82c54SBarry Smith   /* send the messages */
563b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
564b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
56589d82c54SBarry Smith   cnt = 0;
56689d82c54SBarry Smith   for (i=0; i<size; i++) {
56789d82c54SBarry Smith     if (nprocs[i]) {
56824cf384cSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
56930dcb7c9SBarry Smith       dest[cnt] = i;
57089d82c54SBarry Smith       cnt++;
57189d82c54SBarry Smith     }
57289d82c54SBarry Smith   }
57389d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
57489d82c54SBarry Smith 
57589d82c54SBarry Smith   /* wait on receives */
576b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
57789d82c54SBarry Smith   len  = source + nrecvs;
57889d82c54SBarry Smith   cnt  = nrecvs;
579b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
580caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
58189d82c54SBarry Smith   while (cnt) {
58289d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
58389d82c54SBarry Smith     /* unpack receives into our local space */
58489d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
58589d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
58630dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
587caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
58830dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
58989d82c54SBarry Smith     cnt--;
59089d82c54SBarry Smith   }
59189d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
59289d82c54SBarry Smith 
59330dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
594bc8ff85bSBarry Smith   nowned  = 0;
595bc8ff85bSBarry Smith   nownedm = 0;
596bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
597bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
598bc8ff85bSBarry Smith   }
599bc8ff85bSBarry Smith 
600bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
601b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
602b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
603bc8ff85bSBarry Smith   starts[0] = 0;
604bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
605bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
606bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
607bc8ff85bSBarry Smith   }
608bc8ff85bSBarry Smith 
60930dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
610bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
611bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
61230dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
613bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
614bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
615bc8ff85bSBarry Smith       }
616bc8ff85bSBarry Smith     }
617bc8ff85bSBarry Smith   }
618bc8ff85bSBarry Smith 
61907b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
62030dcb7c9SBarry Smith     starts[0]    = 0;
62130dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
62230dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
62330dcb7c9SBarry Smith       else starts[i] = starts[i-1];
62430dcb7c9SBarry Smith     }
62530dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
62630dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
62730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
62830dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
62930dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
63030dcb7c9SBarry Smith         }
63130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
63230dcb7c9SBarry Smith       }
63330dcb7c9SBarry Smith     }
63430dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
63507b52d57SBarry Smith   }/* -----------------------------------  */
63630dcb7c9SBarry Smith 
6373677ff5aSBarry Smith   /* wait on original sends */
6383a96401aSBarry Smith   if (nsends) {
639b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6403a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6413a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6423a96401aSBarry Smith   }
64389d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6443a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6453677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6463677ff5aSBarry Smith 
6473677ff5aSBarry Smith   /* pack messages to send back to local owners */
64830dcb7c9SBarry Smith   starts[0]    = 0;
64930dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
65030dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
65130dcb7c9SBarry Smith     else starts[i] = starts[i-1];
65230dcb7c9SBarry Smith   }
65330dcb7c9SBarry Smith   nsends2 = nrecvs;
654b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
65530dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
65630dcb7c9SBarry Smith     nprocs[i] = 1;
65730dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
65830dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
65930dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
66030dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
66130dcb7c9SBarry Smith       }
66230dcb7c9SBarry Smith     }
66330dcb7c9SBarry Smith   }
66430dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
665b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
666b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
66730dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
66830dcb7c9SBarry Smith   /*
66930dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
67030dcb7c9SBarry Smith        (0) the number of nodes being sent back
67130dcb7c9SBarry Smith        (1) the local node number,
67230dcb7c9SBarry Smith        (2) the number of processors sharing it,
67330dcb7c9SBarry Smith        (3) the processors sharing it
67430dcb7c9SBarry Smith   */
67530dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
67630dcb7c9SBarry Smith     cnt = 1;
67730dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
67830dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
67930dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
68030dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
68130dcb7c9SBarry Smith         sends2[starts2[i]]++;
68230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
68330dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
68430dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
68530dcb7c9SBarry Smith         cnt += nownedsenders[node];
68630dcb7c9SBarry Smith       }
68730dcb7c9SBarry Smith     }
68830dcb7c9SBarry Smith   }
68930dcb7c9SBarry Smith 
69030dcb7c9SBarry Smith   /* send the message lengths */
69130dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
69224cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
69330dcb7c9SBarry Smith   }
69430dcb7c9SBarry Smith 
69530dcb7c9SBarry Smith   /* receive the message lengths */
69630dcb7c9SBarry Smith   nrecvs2 = nsends;
697b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
698b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
69930dcb7c9SBarry Smith   nt      = 0;
70030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
70124cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
70230dcb7c9SBarry Smith     nt   += lens2[i];
70330dcb7c9SBarry Smith   }
70430dcb7c9SBarry Smith   starts3[0] = 0;
70530dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
70630dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
70730dcb7c9SBarry Smith   }
708b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
709b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
71052b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
71124cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
71230dcb7c9SBarry Smith   }
71330dcb7c9SBarry Smith 
71430dcb7c9SBarry Smith   /* send the messages */
715b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
71630dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
71724cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
71830dcb7c9SBarry Smith   }
71930dcb7c9SBarry Smith 
72030dcb7c9SBarry Smith   /* wait on receives */
721b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
72230dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
72330dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
72430dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
72530dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
72630dcb7c9SBarry Smith 
72707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
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         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
73330dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
73430dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
73530dcb7c9SBarry Smith         }
73630dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
73730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
73830dcb7c9SBarry Smith       }
73930dcb7c9SBarry Smith     }
74030dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
74107b52d57SBarry Smith   } /* -----------------------------------  */
74230dcb7c9SBarry Smith 
74330dcb7c9SBarry Smith   /* count number subdomains for each local node */
744b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
74530dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
74630dcb7c9SBarry Smith   cnt  = 0;
74730dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
74830dcb7c9SBarry Smith     nt = recvs2[cnt++];
74930dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
75030dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
75130dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
75230dcb7c9SBarry Smith       }
75330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
75430dcb7c9SBarry Smith     }
75530dcb7c9SBarry Smith   }
75630dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
75730dcb7c9SBarry Smith   *nproc    = nt;
758b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
759b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
760b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
761b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
76230dcb7c9SBarry Smith   cnt       = 0;
76330dcb7c9SBarry Smith   for (i=0; i<size; i++) {
76430dcb7c9SBarry Smith     if (nprocs[i] > 0) {
76530dcb7c9SBarry Smith       bprocs[i]        = cnt;
76630dcb7c9SBarry Smith       (*procs)[cnt]    = i;
76730dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
768b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
76930dcb7c9SBarry Smith       cnt++;
77030dcb7c9SBarry Smith     }
77130dcb7c9SBarry Smith   }
77230dcb7c9SBarry Smith 
77330dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
77430dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
77530dcb7c9SBarry Smith   cnt  = 0;
77630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
77730dcb7c9SBarry Smith     nt = recvs2[cnt++];
77830dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
77930dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
78030dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
78130dcb7c9SBarry Smith       }
78230dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
78330dcb7c9SBarry Smith     }
78430dcb7c9SBarry Smith   }
78530dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
78607b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
78730dcb7c9SBarry Smith 
78807b52d57SBarry Smith   /* sort the node indexing by their global numbers */
78907b52d57SBarry Smith   nt = *nproc;
79007b52d57SBarry Smith   for (i=0; i<nt; i++) {
791b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
79207b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
79307b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
79407b52d57SBarry Smith     }
79507b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
79607b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
79707b52d57SBarry Smith   }
79807b52d57SBarry Smith 
79907b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
80030dcb7c9SBarry Smith     nt = *nproc;
80130dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
80230dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
80330dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
80430dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
80530dcb7c9SBarry Smith       }
80630dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
80730dcb7c9SBarry Smith     }
80830dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
80907b52d57SBarry Smith   } /* -----------------------------------  */
81030dcb7c9SBarry Smith 
81130dcb7c9SBarry Smith   /* wait on sends */
81230dcb7c9SBarry Smith   if (nsends2) {
813b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
81430dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
81530dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
81630dcb7c9SBarry Smith   }
81730dcb7c9SBarry Smith 
81830dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
81930dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
82030dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8213677ff5aSBarry Smith 
822bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
823bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
824bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
82530dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
82630dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
82789d82c54SBarry Smith 
82889d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
82989d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8303a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
83130dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
83224cf384cSBarry Smith 
83324cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
83424cf384cSBarry Smith   first_procs    = (*procs)[0];
83524cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
83624cf384cSBarry Smith   first_indices  = (*indices)[0];
83724cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
83824cf384cSBarry Smith     if ((*procs)[i] == rank) {
83924cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
84024cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
84124cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
84224cf384cSBarry Smith       (*procs)[i]    = first_procs;
84324cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
84424cf384cSBarry Smith       (*indices)[i]  = first_indices;
84524cf384cSBarry Smith       break;
84624cf384cSBarry Smith     }
84724cf384cSBarry Smith   }
84824cf384cSBarry Smith 
84989d82c54SBarry Smith   PetscFunctionReturn(0);
85089d82c54SBarry Smith }
85189d82c54SBarry Smith 
8524a2ae208SSatish Balay #undef __FUNCT__
8534a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
85407b52d57SBarry Smith /*@C
85507b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
85689d82c54SBarry Smith 
85707b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
85807b52d57SBarry Smith 
85907b52d57SBarry Smith     Input Parameters:
86007b52d57SBarry Smith .   mapping - the mapping from local to global indexing
86107b52d57SBarry Smith 
86207b52d57SBarry Smith     Output Parameter:
86307b52d57SBarry Smith +   nproc - number of processors that are connected to this one
86407b52d57SBarry Smith .   proc - neighboring processors
86507b52d57SBarry Smith .   numproc - number of indices for each processor
86607b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
86707b52d57SBarry Smith 
86807b52d57SBarry Smith     Level: advanced
86907b52d57SBarry Smith 
87007b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
87107b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
87207b52d57SBarry Smith @*/
87307b52d57SBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
87407b52d57SBarry Smith {
87507b52d57SBarry Smith   int ierr,i;
87607b52d57SBarry Smith 
87707b52d57SBarry Smith   PetscFunctionBegin;
87800ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
87900ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
88000ff320aSBarry Smith   if (*indices) {
88100ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
88200ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
88324cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
88407b52d57SBarry Smith     }
88507b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
88624cf384cSBarry Smith   }
88707b52d57SBarry Smith   PetscFunctionReturn(0);
88807b52d57SBarry Smith }
88989d82c54SBarry Smith 
890bc8ff85bSBarry Smith 
891bc8ff85bSBarry Smith 
892bc8ff85bSBarry Smith 
893bc8ff85bSBarry Smith 
894bc8ff85bSBarry Smith 
895bc8ff85bSBarry Smith 
896bc8ff85bSBarry Smith 
897bc8ff85bSBarry Smith 
898bc8ff85bSBarry Smith 
899bc8ff85bSBarry Smith 
900bc8ff85bSBarry Smith 
901bc8ff85bSBarry Smith 
902bc8ff85bSBarry Smith 
903bc8ff85bSBarry Smith 
904bc8ff85bSBarry Smith 
905bc8ff85bSBarry Smith 
90624cf384cSBarry Smith 
907