xref: /petsc/src/vec/is/utils/isltog.c (revision 323b833ffd2abbc021b1f705dc98117c2173689c)
1*323b833fSBarry Smith /*$Id: isltog.c,v 1.60 2001/01/15 21:44:35 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__
7b0a32e0cSBarry 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__
34b0a32e0cSBarry 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 @*/
50b0a32e0cSBarry 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);
57b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
58b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
596831982aSBarry Smith   PetscCheckSameComm(mapping,viewer);
605a5d4f66SBarry Smith 
61f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
62b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
636831982aSBarry Smith   if (isascii) {
645a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
65b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
666831982aSBarry Smith     }
67b0a32e0cSBarry 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__
76b0a32e0cSBarry 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__
113b0a32e0cSBarry 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);
144b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
145b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
146d4bb536fSBarry Smith 
147d4bb536fSBarry Smith   (*mapping)->n       = n;
148b0a32e0cSBarry 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*323b833fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingBlock"
161*323b833fSBarry Smith /*@C
162*323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
163*323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
164*323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
165*323b833fSBarry Smith 
166*323b833fSBarry Smith     Not Collective, but communicator may have more than one process
167*323b833fSBarry Smith 
168*323b833fSBarry Smith     Input Parameters:
169*323b833fSBarry Smith +    inmap - original point-wise mapping
170*323b833fSBarry Smith -    bs - block size
171*323b833fSBarry Smith 
172*323b833fSBarry Smith     Output Parameter:
173*323b833fSBarry Smith .   outmap - block based mapping
174*323b833fSBarry Smith 
175*323b833fSBarry Smith     Level: advanced
176*323b833fSBarry Smith 
177*323b833fSBarry Smith     Concepts: mapping^local to global
178*323b833fSBarry Smith 
179*323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
180*323b833fSBarry Smith @*/
181*323b833fSBarry Smith int ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
182*323b833fSBarry Smith {
183*323b833fSBarry Smith   int ierr,*ii,i,n;
184*323b833fSBarry Smith 
185*323b833fSBarry Smith   PetscFunctionBegin;
186*323b833fSBarry Smith 
187*323b833fSBarry Smith   if (bs > 1) {
188*323b833fSBarry Smith     n    = inmap->n/bs;
189*323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
190*323b833fSBarry Smith     for (i=0; i<n; i++) {
191*323b833fSBarry Smith       ii[i] = inmap->indices[bs*i];
192*323b833fSBarry Smith     }
193*323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
194*323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
195*323b833fSBarry Smith   } else {
196*323b833fSBarry Smith     *outmap = inmap;
197*323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
198*323b833fSBarry Smith   }
199*323b833fSBarry Smith   PetscFunctionReturn(0);
200*323b833fSBarry Smith }
201*323b833fSBarry Smith 
202*323b833fSBarry Smith #undef __FUNC__
203b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingDestroy"
20490f02eecSBarry Smith /*@
20590f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
20690f02eecSBarry Smith    ordering and a global parallel ordering.
20790f02eecSBarry Smith 
2080f5bd95cSBarry Smith    Note Collective
209b9cd556bSLois Curfman McInnes 
21090f02eecSBarry Smith    Input Parameters:
21190f02eecSBarry Smith .  mapping - mapping data structure
21290f02eecSBarry Smith 
213a997ad1aSLois Curfman McInnes    Level: advanced
214a997ad1aSLois Curfman McInnes 
2153acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
21690f02eecSBarry Smith @*/
21790f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
21890f02eecSBarry Smith {
219606d414cSSatish Balay   int ierr;
2203a40ed3dSBarry Smith   PetscFunctionBegin;
22190f02eecSBarry Smith   PetscValidPointer(mapping);
2223a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
22385614651SBarry Smith   if (mapping->refct < 0) {
22429bbc08cSBarry Smith     SETERRQ(1,"Mapping already destroyed");
22585614651SBarry Smith   }
22690f02eecSBarry Smith 
227606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
228606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
229b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
230d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2313a40ed3dSBarry Smith   PetscFunctionReturn(0);
23290f02eecSBarry Smith }
23390f02eecSBarry Smith 
2345615d1e5SSatish Balay #undef __FUNC__
235b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingApplyIS"
23690f02eecSBarry Smith /*@
2373acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2383acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2393acfe500SLois Curfman McInnes     context.
24090f02eecSBarry Smith 
241b9cd556bSLois Curfman McInnes     Not collective
242b9cd556bSLois Curfman McInnes 
24390f02eecSBarry Smith     Input Parameters:
244b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
245b9cd556bSLois Curfman McInnes -   is - index set in local numbering
24690f02eecSBarry Smith 
24790f02eecSBarry Smith     Output Parameters:
24890f02eecSBarry Smith .   newis - index set in global numbering
24990f02eecSBarry Smith 
250a997ad1aSLois Curfman McInnes     Level: advanced
251a997ad1aSLois Curfman McInnes 
252273d9f13SBarry Smith     Concepts: mapping^local to global
2533acfe500SLois Curfman McInnes 
25490f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
255d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
25690f02eecSBarry Smith @*/
25790f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
25890f02eecSBarry Smith {
2593b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
2603a40ed3dSBarry Smith 
2613a40ed3dSBarry Smith   PetscFunctionBegin;
26290f02eecSBarry Smith   PetscValidPointer(mapping);
26390f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
26490f02eecSBarry Smith   PetscValidPointer(newis);
26590f02eecSBarry Smith 
2663b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
26790f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
26890f02eecSBarry Smith   idxmap = mapping->indices;
26990f02eecSBarry Smith 
270b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
27190f02eecSBarry Smith   for (i=0; i<n; i++) {
27229bbc08cSBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i);
27390f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
27490f02eecSBarry Smith   }
2753b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
276029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
277606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
2783a40ed3dSBarry Smith   PetscFunctionReturn(0);
27990f02eecSBarry Smith }
28090f02eecSBarry Smith 
28189d82c54SBarry Smith /*MC
2823acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2833acfe500SLois Curfman McInnes    and converts them to the global numbering.
28490f02eecSBarry Smith 
285b9cd556bSLois Curfman McInnes    Not collective
286b9cd556bSLois Curfman McInnes 
287bb25748dSBarry Smith    Input Parameters:
288b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
289bb25748dSBarry Smith .  N - number of integers
290b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
291bb25748dSBarry Smith 
292bb25748dSBarry Smith    Output Parameter:
293bb25748dSBarry Smith .  out - indices in global numbering
294bb25748dSBarry Smith 
2953b9aefa3SBarry Smith    Synopsis:
2963b9aefa3SBarry Smith    ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
2973b9aefa3SBarry Smith 
298b9cd556bSLois Curfman McInnes    Notes:
299b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
300d4bb536fSBarry Smith 
301a997ad1aSLois Curfman McInnes    Level: advanced
302a997ad1aSLois Curfman McInnes 
303bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3040752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
305d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
306bb25748dSBarry Smith 
307273d9f13SBarry Smith     Concepts: mapping^local to global
308d4bb536fSBarry Smith 
30989d82c54SBarry Smith M*/
310d4bb536fSBarry Smith 
311d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
312d4bb536fSBarry Smith 
313d4bb536fSBarry Smith #undef __FUNC__
314b0a32e0cSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingSetUp_Private"
315d4bb536fSBarry Smith /*
316d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
317d4bb536fSBarry Smith */
318d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
319d4bb536fSBarry Smith {
320b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
321d4bb536fSBarry Smith 
3223a40ed3dSBarry Smith   PetscFunctionBegin;
323d4bb536fSBarry Smith   end   = 0;
324d4bb536fSBarry Smith   start = 100000000;
325d4bb536fSBarry Smith 
326d4bb536fSBarry Smith   for (i=0; i<n; i++) {
327d4bb536fSBarry Smith     if (idx[i] < 0) continue;
328d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
329d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
330d4bb536fSBarry Smith   }
331d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
332d4bb536fSBarry Smith   mapping->globalstart = start;
333d4bb536fSBarry Smith   mapping->globalend   = end;
334d4bb536fSBarry Smith 
335b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
336b0a32e0cSBarry Smith   mapping->globals = globals;
337d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
338d4bb536fSBarry Smith     globals[i] = -1;
339d4bb536fSBarry Smith   }
340d4bb536fSBarry Smith   for (i=0; i<n; i++) {
341d4bb536fSBarry Smith     if (idx[i] < 0) continue;
342d4bb536fSBarry Smith     globals[idx[i] - start] = i;
343d4bb536fSBarry Smith   }
344d4bb536fSBarry Smith 
345b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3463a40ed3dSBarry Smith   PetscFunctionReturn(0);
347d4bb536fSBarry Smith }
348d4bb536fSBarry Smith 
349d4bb536fSBarry Smith #undef __FUNC__
350b0a32e0cSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingApply"
351d4bb536fSBarry Smith /*@
352a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
353a997ad1aSLois Curfman McInnes     specified with a global numbering.
354d4bb536fSBarry Smith 
355b9cd556bSLois Curfman McInnes     Not collective
356b9cd556bSLois Curfman McInnes 
357d4bb536fSBarry Smith     Input Parameters:
358b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
359d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
360d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
361d4bb536fSBarry Smith .   n - number of global indices to map
362b9cd556bSLois Curfman McInnes -   idx - global indices to map
363d4bb536fSBarry Smith 
364d4bb536fSBarry Smith     Output Parameters:
365b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
366b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
367e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
368e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
369e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
370e182c471SBarry Smith              a second time to set the values.
371d4bb536fSBarry Smith 
372b9cd556bSLois Curfman McInnes     Notes:
373b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
374d4bb536fSBarry Smith 
3750f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
3760f5bd95cSBarry Smith     array to compute these.
3770f5bd95cSBarry Smith 
378a997ad1aSLois Curfman McInnes     Level: advanced
379a997ad1aSLois Curfman McInnes 
380273d9f13SBarry Smith     Concepts: mapping^global to local
381d4bb536fSBarry Smith 
382d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
383d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
384d4bb536fSBarry Smith @*/
385d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
386987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
387d4bb536fSBarry Smith {
388d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
389d4bb536fSBarry Smith 
3903a40ed3dSBarry Smith   PetscFunctionBegin;
391d4bb536fSBarry Smith   if (!mapping->globals) {
392d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
393d4bb536fSBarry Smith   }
394d4bb536fSBarry Smith   globals = mapping->globals;
395d4bb536fSBarry Smith   start   = mapping->globalstart;
396d4bb536fSBarry Smith   end     = mapping->globalend;
397d4bb536fSBarry Smith 
398d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
399d4bb536fSBarry Smith     if (idxout) {
400d4bb536fSBarry Smith       for (i=0; i<n; i++) {
401d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
402d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
403d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
404d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
405d4bb536fSBarry Smith       }
406d4bb536fSBarry Smith     }
407d4bb536fSBarry Smith     if (nout) *nout = n;
408d4bb536fSBarry Smith   } else {
409d4bb536fSBarry Smith     if (idxout) {
410d4bb536fSBarry Smith       for (i=0; i<n; i++) {
411d4bb536fSBarry Smith         if (idx[i] < 0) continue;
412d4bb536fSBarry Smith         if (idx[i] < start) continue;
413d4bb536fSBarry Smith         if (idx[i] > end) continue;
414d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
415d4bb536fSBarry Smith         if (tmp < 0) continue;
416d4bb536fSBarry Smith         idxout[nf++] = tmp;
417d4bb536fSBarry Smith       }
418d4bb536fSBarry Smith     } else {
419d4bb536fSBarry Smith       for (i=0; i<n; i++) {
420d4bb536fSBarry Smith         if (idx[i] < 0) continue;
421d4bb536fSBarry Smith         if (idx[i] < start) continue;
422d4bb536fSBarry Smith         if (idx[i] > end) continue;
423d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
424d4bb536fSBarry Smith         if (tmp < 0) continue;
425d4bb536fSBarry Smith         nf++;
426d4bb536fSBarry Smith       }
427d4bb536fSBarry Smith     }
428d4bb536fSBarry Smith     if (nout) *nout = nf;
429d4bb536fSBarry Smith   }
430d4bb536fSBarry Smith 
4313a40ed3dSBarry Smith   PetscFunctionReturn(0);
432d4bb536fSBarry Smith }
43390f02eecSBarry Smith 
43489d82c54SBarry Smith #undef __FUNC__
435b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingGetInfo"
43689d82c54SBarry Smith /*@C
43789d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
43889d82c54SBarry Smith      each index shared by more than one processor
43989d82c54SBarry Smith 
44089d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
44189d82c54SBarry Smith 
44289d82c54SBarry Smith     Input Parameters:
44389d82c54SBarry Smith .   mapping - the mapping from local to global indexing
44489d82c54SBarry Smith 
44589d82c54SBarry Smith     Output Parameter:
44689d82c54SBarry Smith +   nproc - number of processors that are connected to this one
44789d82c54SBarry Smith .   proc - neighboring processors
44807b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
44907b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
45089d82c54SBarry Smith 
45189d82c54SBarry Smith     Level: advanced
45289d82c54SBarry Smith 
453273d9f13SBarry Smith     Concepts: mapping^local to global
45489d82c54SBarry Smith 
45507b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
45607b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
45789d82c54SBarry Smith @*/
45830dcb7c9SBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
45989d82c54SBarry Smith {
4603a96401aSBarry Smith   int         i,n = mapping->n,ierr,Ng,ng = PETSC_DECIDE,max = 0,*lindices = mapping->indices;
4613a96401aSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc;
46224cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
46307b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
46424cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
46589d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
46630dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
46789d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
46807b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
46989d82c54SBarry Smith 
47089d82c54SBarry Smith   PetscFunctionBegin;
47124cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
47224cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
47324cf384cSBarry Smith   if (size == 1) {
47424cf384cSBarry Smith     *nproc         = 0;
47524cf384cSBarry Smith     *procs         = PETSC_NULL;
476b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
4771e2105dcSBarry Smith     (*numprocs)[0] = 0;
478b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
4791e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
48024cf384cSBarry Smith     PetscFunctionReturn(0);
48124cf384cSBarry Smith   }
48224cf384cSBarry Smith 
483b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
48407b52d57SBarry Smith 
4853677ff5aSBarry Smith   /*
4863677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
4873677ff5aSBarry Smith 
4883677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
4893677ff5aSBarry Smith            numbering, just for this routine.
4903677ff5aSBarry Smith 
4913677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
4923677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
4933677ff5aSBarry Smith 
4943677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
4953677ff5aSBarry Smith 
4963677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
4973677ff5aSBarry Smith            local subdomain
4983677ff5aSBarry Smith   */
49924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
50024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
50124cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
50289d82c54SBarry Smith 
50389d82c54SBarry Smith   for (i=0; i<n; i++) {
50489d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
50589d82c54SBarry Smith   }
50689d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
50778058e43SBarry Smith   Ng++;
50889d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
50989d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
510bc8ff85bSBarry Smith   scale  = Ng/size + 1;
511a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
512caba0dd0SBarry Smith   rstart = scale*rank;
51389d82c54SBarry Smith 
51489d82c54SBarry Smith   /* determine ownership ranges of global indices */
515b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5162880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
51789d82c54SBarry Smith 
51889d82c54SBarry Smith   /* determine owners of each local node  */
519b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
52089d82c54SBarry Smith   for (i=0; i<n; i++) {
5213677ff5aSBarry Smith     proc              = lindices[i]/scale; /* processor that globally owns this index */
5223677ff5aSBarry Smith     nprocs[size+proc] = 1;                 /* processor globally owns at least one of ours */
5233677ff5aSBarry Smith     owner[i]          = proc;
5243677ff5aSBarry Smith     nprocs[proc]++;                        /* count of how many that processor globally owns of ours */
52589d82c54SBarry Smith   }
52689d82c54SBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i];
527b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
52889d82c54SBarry Smith 
52989d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
530b0a32e0cSBarry Smith   ierr = PetscMalloc(2*size*sizeof(int),&work);CHKERRQ(ierr);
53189d82c54SBarry Smith   ierr   = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
53289d82c54SBarry Smith   nmax   = work[rank];
53389d82c54SBarry Smith   nrecvs = work[size+rank];
53489d82c54SBarry Smith   ierr   = PetscFree(work);CHKERRQ(ierr);
535b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
53689d82c54SBarry Smith 
53789d82c54SBarry Smith   /* post receives for owned rows */
538b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
539b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
54089d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
54124cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
54289d82c54SBarry Smith   }
54389d82c54SBarry Smith 
54489d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
545b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
546b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
54789d82c54SBarry Smith   starts[0]  = 0;
54830dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
54989d82c54SBarry Smith   for (i=0; i<n; i++) {
55089d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
55130dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
55289d82c54SBarry Smith   }
55389d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
55489d82c54SBarry Smith   starts[0]  = 0;
55530dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
55689d82c54SBarry Smith 
55789d82c54SBarry Smith   /* send the messages */
558b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
559b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
56089d82c54SBarry Smith   cnt = 0;
56189d82c54SBarry Smith   for (i=0; i<size; i++) {
56289d82c54SBarry Smith     if (nprocs[i]) {
56324cf384cSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
56430dcb7c9SBarry Smith       dest[cnt] = i;
56589d82c54SBarry Smith       cnt++;
56689d82c54SBarry Smith     }
56789d82c54SBarry Smith   }
56889d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
56989d82c54SBarry Smith 
57089d82c54SBarry Smith   /* wait on receives */
571b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
57289d82c54SBarry Smith   len  = source + nrecvs;
57389d82c54SBarry Smith   cnt  = nrecvs;
574b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
575caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
57689d82c54SBarry Smith   while (cnt) {
57789d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
57889d82c54SBarry Smith     /* unpack receives into our local space */
57989d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
58089d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
58130dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
582caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
58330dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
58489d82c54SBarry Smith     cnt--;
58589d82c54SBarry Smith   }
58689d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
58789d82c54SBarry Smith 
58830dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
589bc8ff85bSBarry Smith   nowned  = 0;
590bc8ff85bSBarry Smith   nownedm = 0;
591bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
592bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
593bc8ff85bSBarry Smith   }
594bc8ff85bSBarry Smith 
595bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
596b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
597b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
598bc8ff85bSBarry Smith   starts[0] = 0;
599bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
600bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
601bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
602bc8ff85bSBarry Smith   }
603bc8ff85bSBarry Smith 
60430dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
605bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
606bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
60730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
608bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
609bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
610bc8ff85bSBarry Smith       }
611bc8ff85bSBarry Smith     }
612bc8ff85bSBarry Smith   }
613bc8ff85bSBarry Smith 
61407b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
61530dcb7c9SBarry Smith     starts[0]    = 0;
61630dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
61730dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
61830dcb7c9SBarry Smith       else starts[i] = starts[i-1];
61930dcb7c9SBarry Smith     }
62030dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
62130dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
62230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
62330dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
62430dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
62530dcb7c9SBarry Smith         }
62630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
62730dcb7c9SBarry Smith       }
62830dcb7c9SBarry Smith     }
62930dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
63007b52d57SBarry Smith   }/* -----------------------------------  */
63130dcb7c9SBarry Smith 
6323677ff5aSBarry Smith   /* wait on original sends */
6333a96401aSBarry Smith   if (nsends) {
634b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6353a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6363a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6373a96401aSBarry Smith   }
63889d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6393a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6403677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6413677ff5aSBarry Smith 
6423677ff5aSBarry Smith   /* pack messages to send back to local owners */
64330dcb7c9SBarry Smith   starts[0]    = 0;
64430dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
64530dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
64630dcb7c9SBarry Smith     else starts[i] = starts[i-1];
64730dcb7c9SBarry Smith   }
64830dcb7c9SBarry Smith   nsends2 = nrecvs;
649b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
65030dcb7c9SBarry Smith   cnt     = 0;
65130dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
65230dcb7c9SBarry Smith     nprocs[i] = 1;
65330dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
65430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
65530dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
65630dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
65730dcb7c9SBarry Smith       }
65830dcb7c9SBarry Smith     }
65930dcb7c9SBarry Smith   }
66030dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
661b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
662b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
66330dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
66430dcb7c9SBarry Smith   /*
66530dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
66630dcb7c9SBarry Smith        (0) the number of nodes being sent back
66730dcb7c9SBarry Smith        (1) the local node number,
66830dcb7c9SBarry Smith        (2) the number of processors sharing it,
66930dcb7c9SBarry Smith        (3) the processors sharing it
67030dcb7c9SBarry Smith   */
67130dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
67230dcb7c9SBarry Smith     cnt = 1;
67330dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
67430dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
67530dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
67630dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
67730dcb7c9SBarry Smith         sends2[starts2[i]]++;
67830dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
67930dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
68030dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
68130dcb7c9SBarry Smith         cnt += nownedsenders[node];
68230dcb7c9SBarry Smith       }
68330dcb7c9SBarry Smith     }
68430dcb7c9SBarry Smith   }
68530dcb7c9SBarry Smith 
68630dcb7c9SBarry Smith   /* send the message lengths */
68730dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
68824cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
68930dcb7c9SBarry Smith   }
69030dcb7c9SBarry Smith 
69130dcb7c9SBarry Smith   /* receive the message lengths */
69230dcb7c9SBarry Smith   nrecvs2 = nsends;
693b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
694b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
69530dcb7c9SBarry Smith   nt      = 0;
69630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
69724cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
69830dcb7c9SBarry Smith     nt   += lens2[i];
69930dcb7c9SBarry Smith   }
70030dcb7c9SBarry Smith   starts3[0] = 0;
70130dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
70230dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
70330dcb7c9SBarry Smith   }
704b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
705b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
70652b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
70724cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
70830dcb7c9SBarry Smith   }
70930dcb7c9SBarry Smith 
71030dcb7c9SBarry Smith   /* send the messages */
711b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
71230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
71324cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
71430dcb7c9SBarry Smith   }
71530dcb7c9SBarry Smith 
71630dcb7c9SBarry Smith   /* wait on receives */
717b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
71830dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
71930dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
72030dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
72130dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
72230dcb7c9SBarry Smith 
72307b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
72430dcb7c9SBarry Smith     cnt = 0;
72530dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
72630dcb7c9SBarry Smith       nt = recvs2[cnt++];
72730dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
72830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
72930dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
73030dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
73130dcb7c9SBarry Smith         }
73230dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
73330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
73430dcb7c9SBarry Smith       }
73530dcb7c9SBarry Smith     }
73630dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
73707b52d57SBarry Smith   } /* -----------------------------------  */
73830dcb7c9SBarry Smith 
73930dcb7c9SBarry Smith   /* count number subdomains for each local node */
740b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
74130dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
74230dcb7c9SBarry Smith   cnt  = 0;
74330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
74430dcb7c9SBarry Smith     nt = recvs2[cnt++];
74530dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
74630dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
74730dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
74830dcb7c9SBarry Smith       }
74930dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
75030dcb7c9SBarry Smith     }
75130dcb7c9SBarry Smith   }
75230dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
75330dcb7c9SBarry Smith   *nproc    = nt;
754b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
755b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
756b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
757b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
75830dcb7c9SBarry Smith   cnt       = 0;
75930dcb7c9SBarry Smith   for (i=0; i<size; i++) {
76030dcb7c9SBarry Smith     if (nprocs[i] > 0) {
76130dcb7c9SBarry Smith       bprocs[i]        = cnt;
76230dcb7c9SBarry Smith       (*procs)[cnt]    = i;
76330dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
764b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
76530dcb7c9SBarry Smith       cnt++;
76630dcb7c9SBarry Smith     }
76730dcb7c9SBarry Smith   }
76830dcb7c9SBarry Smith 
76930dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
77030dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
77130dcb7c9SBarry Smith   cnt  = 0;
77230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
77330dcb7c9SBarry Smith     nt = recvs2[cnt++];
77430dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
77530dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
77630dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
77730dcb7c9SBarry Smith       }
77830dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
77930dcb7c9SBarry Smith     }
78030dcb7c9SBarry Smith   }
78130dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
78207b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
78330dcb7c9SBarry Smith 
78407b52d57SBarry Smith   /* sort the node indexing by their global numbers */
78507b52d57SBarry Smith   nt = *nproc;
78607b52d57SBarry Smith   for (i=0; i<nt; i++) {
787b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
78807b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
78907b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
79007b52d57SBarry Smith     }
79107b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
79207b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
79307b52d57SBarry Smith   }
79407b52d57SBarry Smith 
79507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
79630dcb7c9SBarry Smith     nt = *nproc;
79730dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
79830dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
79930dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
80030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
80130dcb7c9SBarry Smith       }
80230dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
80330dcb7c9SBarry Smith     }
80430dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
80507b52d57SBarry Smith   } /* -----------------------------------  */
80630dcb7c9SBarry Smith 
80730dcb7c9SBarry Smith   /* wait on sends */
80830dcb7c9SBarry Smith   if (nsends2) {
809b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
81030dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
81130dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
81230dcb7c9SBarry Smith   }
81330dcb7c9SBarry Smith 
81430dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
81530dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
81630dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8173677ff5aSBarry Smith 
818bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
819bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
820bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
82130dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
82230dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
82389d82c54SBarry Smith 
82489d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
82589d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8263a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
82730dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
82824cf384cSBarry Smith 
82924cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
83024cf384cSBarry Smith   first_procs    = (*procs)[0];
83124cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
83224cf384cSBarry Smith   first_indices  = (*indices)[0];
83324cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
83424cf384cSBarry Smith     if ((*procs)[i] == rank) {
83524cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
83624cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
83724cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
83824cf384cSBarry Smith       (*procs)[i]    = first_procs;
83924cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
84024cf384cSBarry Smith       (*indices)[i]  = first_indices;
84124cf384cSBarry Smith       break;
84224cf384cSBarry Smith     }
84324cf384cSBarry Smith   }
84424cf384cSBarry Smith 
84589d82c54SBarry Smith   PetscFunctionReturn(0);
84689d82c54SBarry Smith }
84789d82c54SBarry Smith 
84807b52d57SBarry Smith #undef __FUNC__
849b0a32e0cSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingRestoreInfo"
85007b52d57SBarry Smith /*@C
85107b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
85289d82c54SBarry Smith 
85307b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
85407b52d57SBarry Smith 
85507b52d57SBarry Smith     Input Parameters:
85607b52d57SBarry Smith .   mapping - the mapping from local to global indexing
85707b52d57SBarry Smith 
85807b52d57SBarry Smith     Output Parameter:
85907b52d57SBarry Smith +   nproc - number of processors that are connected to this one
86007b52d57SBarry Smith .   proc - neighboring processors
86107b52d57SBarry Smith .   numproc - number of indices for each processor
86207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
86307b52d57SBarry Smith 
86407b52d57SBarry Smith     Level: advanced
86507b52d57SBarry Smith 
86607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
86707b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
86807b52d57SBarry Smith @*/
86907b52d57SBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
87007b52d57SBarry Smith {
87107b52d57SBarry Smith   int ierr,i;
87207b52d57SBarry Smith 
87307b52d57SBarry Smith   PetscFunctionBegin;
87400ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
87500ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
87600ff320aSBarry Smith   if (*indices) {
87700ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
87800ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
87924cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
88007b52d57SBarry Smith     }
88107b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
88224cf384cSBarry Smith   }
88307b52d57SBarry Smith   PetscFunctionReturn(0);
88407b52d57SBarry Smith }
88589d82c54SBarry Smith 
886bc8ff85bSBarry Smith 
887bc8ff85bSBarry Smith 
888bc8ff85bSBarry Smith 
889bc8ff85bSBarry 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 
90224cf384cSBarry Smith 
903