xref: /petsc/src/vec/is/utils/isltog.c (revision 04a59952075a8203023532fbff2cf20558f6a7c6)
12362add9SBarry Smith 
2b45d2f2cSJed Brown #include <petsc-private/isimpl.h>    /*I "petscis.h"  I*/
30c312b8eSJed Brown #include <petscsf.h>
4665c2dedSJed Brown #include <petscviewer.h>
52362add9SBarry Smith 
67087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID;
78e58c17dSMatthew Knepley 
8*04a59952SBarry Smith 
94a2ae208SSatish Balay #undef __FUNCT__
10743c9b42SStefano Zampini #define __FUNCT__ "ISG2LMapApply"
11186d4ecdSBarry Smith PetscErrorCode ISG2LMapApply(ISLocalToGlobalMapping mapping,PetscInt n,const PetscInt in[],PetscInt out[])
12186d4ecdSBarry Smith {
13186d4ecdSBarry Smith   PetscErrorCode ierr;
14743c9b42SStefano Zampini   PetscInt       i,start,end;
15186d4ecdSBarry Smith 
16186d4ecdSBarry Smith   PetscFunctionBegin;
17186d4ecdSBarry Smith   if (!mapping->globals) {
18186d4ecdSBarry Smith     ierr = ISGlobalToLocalMappingApply(mapping,IS_GTOLM_MASK,0,0,0,0);CHKERRQ(ierr);
19186d4ecdSBarry Smith   }
20743c9b42SStefano Zampini   start = mapping->globalstart;
21743c9b42SStefano Zampini   end = mapping->globalend;
22186d4ecdSBarry Smith   for (i=0; i<n; i++) {
23186d4ecdSBarry Smith     if (in[i] < 0)          out[i] = in[i];
24186d4ecdSBarry Smith     else if (in[i] < start) out[i] = -1;
25186d4ecdSBarry Smith     else if (in[i] > end)   out[i] = -1;
26743c9b42SStefano Zampini     else                    out[i] = mapping->globals[in[i] - start];
27186d4ecdSBarry Smith   }
28186d4ecdSBarry Smith   PetscFunctionReturn(0);
29186d4ecdSBarry Smith }
30186d4ecdSBarry Smith 
31186d4ecdSBarry Smith 
32186d4ecdSBarry Smith #undef __FUNCT__
334a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
343b9aefa3SBarry Smith /*@C
353b9aefa3SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping.
363b9aefa3SBarry Smith 
373b9aefa3SBarry Smith     Not Collective
383b9aefa3SBarry Smith 
393b9aefa3SBarry Smith     Input Parameter:
403b9aefa3SBarry Smith .   ltog - local to global mapping
413b9aefa3SBarry Smith 
423b9aefa3SBarry Smith     Output Parameter:
433b9aefa3SBarry Smith .   n - the number of entries in the local mapping
443b9aefa3SBarry Smith 
453b9aefa3SBarry Smith     Level: advanced
463b9aefa3SBarry Smith 
47273d9f13SBarry Smith     Concepts: mapping^local to global
483b9aefa3SBarry Smith 
493b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
503b9aefa3SBarry Smith @*/
517087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
523b9aefa3SBarry Smith {
533b9aefa3SBarry Smith   PetscFunctionBegin;
540700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
554482741eSBarry Smith   PetscValidIntPointer(n,2);
563b9aefa3SBarry Smith   *n = mapping->n;
573b9aefa3SBarry Smith   PetscFunctionReturn(0);
583b9aefa3SBarry Smith }
593b9aefa3SBarry Smith 
604a2ae208SSatish Balay #undef __FUNCT__
614a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
625a5d4f66SBarry Smith /*@C
635a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
645a5d4f66SBarry Smith 
65b9cd556bSLois Curfman McInnes     Not Collective
66b9cd556bSLois Curfman McInnes 
675a5d4f66SBarry Smith     Input Parameters:
683b9aefa3SBarry Smith +   ltog - local to global mapping
693b9aefa3SBarry Smith -   viewer - viewer
705a5d4f66SBarry Smith 
71a997ad1aSLois Curfman McInnes     Level: advanced
72a997ad1aSLois Curfman McInnes 
73273d9f13SBarry Smith     Concepts: mapping^local to global
745a5d4f66SBarry Smith 
755a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
765a5d4f66SBarry Smith @*/
777087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
785a5d4f66SBarry Smith {
7932dcc486SBarry Smith   PetscInt       i;
8032dcc486SBarry Smith   PetscMPIInt    rank;
81ace3abfcSBarry Smith   PetscBool      iascii;
826849ba73SBarry Smith   PetscErrorCode ierr;
835a5d4f66SBarry Smith 
845a5d4f66SBarry Smith   PetscFunctionBegin;
850700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
863050cee2SBarry Smith   if (!viewer) {
87ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
883050cee2SBarry Smith   }
890700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
905a5d4f66SBarry Smith 
91ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
92251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
9332077d6dSBarry Smith   if (iascii) {
947b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
955a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
96b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
976831982aSBarry Smith     }
98b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
997b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
1007b23a99aSBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
1015a5d4f66SBarry Smith   PetscFunctionReturn(0);
1025a5d4f66SBarry Smith }
1035a5d4f66SBarry Smith 
1044a2ae208SSatish Balay #undef __FUNCT__
1054a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1061f428162SBarry Smith /*@
1072bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1082bdab257SBarry Smith     ordering and a global parallel ordering.
1092bdab257SBarry Smith 
1100f5bd95cSBarry Smith     Not collective
111b9cd556bSLois Curfman McInnes 
112a997ad1aSLois Curfman McInnes     Input Parameter:
1138c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1142bdab257SBarry Smith 
115a997ad1aSLois Curfman McInnes     Output Parameter:
1162bdab257SBarry Smith .   mapping - new mapping data structure
1172bdab257SBarry Smith 
118a997ad1aSLois Curfman McInnes     Level: advanced
119a997ad1aSLois Curfman McInnes 
120273d9f13SBarry Smith     Concepts: mapping^local to global
1212bdab257SBarry Smith 
1222bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1232bdab257SBarry Smith @*/
1247087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1252bdab257SBarry Smith {
1266849ba73SBarry Smith   PetscErrorCode ierr;
1275d0c19d7SBarry Smith   PetscInt       n;
1285d0c19d7SBarry Smith   const PetscInt *indices;
1292bdab257SBarry Smith   MPI_Comm       comm;
1303a40ed3dSBarry Smith 
1313a40ed3dSBarry Smith   PetscFunctionBegin;
1320700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1334482741eSBarry Smith   PetscValidPointer(mapping,2);
1342bdab257SBarry Smith 
1352bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1363b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1372bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
138d5ad8652SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1392bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1403a40ed3dSBarry Smith   PetscFunctionReturn(0);
1412bdab257SBarry Smith }
1425a5d4f66SBarry Smith 
143a4d96a55SJed Brown #undef __FUNCT__
144a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
145a4d96a55SJed Brown /*@C
146a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
147a4d96a55SJed Brown     ordering and a global parallel ordering.
148a4d96a55SJed Brown 
149a4d96a55SJed Brown     Collective
150a4d96a55SJed Brown 
151a4d96a55SJed Brown     Input Parameter:
152a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
153a4d96a55SJed Brown -   start - first global index on this process
154a4d96a55SJed Brown 
155a4d96a55SJed Brown     Output Parameter:
156a4d96a55SJed Brown .   mapping - new mapping data structure
157a4d96a55SJed Brown 
158a4d96a55SJed Brown     Level: advanced
159a4d96a55SJed Brown 
160a4d96a55SJed Brown     Concepts: mapping^local to global
161a4d96a55SJed Brown 
162a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
163a4d96a55SJed Brown @*/
164a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
165a4d96a55SJed Brown {
166a4d96a55SJed Brown   PetscErrorCode ierr;
167a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
168a4d96a55SJed Brown   const PetscInt *ilocal;
169a4d96a55SJed Brown   MPI_Comm       comm;
170a4d96a55SJed Brown 
171a4d96a55SJed Brown   PetscFunctionBegin;
172a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
173a4d96a55SJed Brown   PetscValidPointer(mapping,3);
174a4d96a55SJed Brown 
175a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1760298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
177f6e5521dSKarl Rupp   if (ilocal) {
178f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
179f6e5521dSKarl Rupp   }
180a4d96a55SJed Brown   else maxlocal = nleaves;
181a4d96a55SJed Brown   ierr = PetscMalloc(nroots*sizeof(PetscInt),&globals);CHKERRQ(ierr);
182a4d96a55SJed Brown   ierr = PetscMalloc(maxlocal*sizeof(PetscInt),&ltog);CHKERRQ(ierr);
183a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
184a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
185a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
186a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
187a4d96a55SJed Brown   ierr = ISLocalToGlobalMappingCreate(comm,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
188a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
189a4d96a55SJed Brown   PetscFunctionReturn(0);
190a4d96a55SJed Brown }
191b46b645bSBarry Smith 
1924a2ae208SSatish Balay #undef __FUNCT__
1934a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
194ba5bb76aSSatish Balay /*@
19590f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
19690f02eecSBarry Smith     ordering and a global parallel ordering.
1972362add9SBarry Smith 
19889d82c54SBarry Smith     Not Collective, but communicator may have more than one process
199b9cd556bSLois Curfman McInnes 
2002362add9SBarry Smith     Input Parameters:
20189d82c54SBarry Smith +   comm - MPI communicator
20290f02eecSBarry Smith .   n - the number of local elements
2039669e4d8SBarry Smith .   indices - the global index for each local element, these do not need to be in increasing order (sorted)
204d5ad8652SBarry Smith -   mode - see PetscCopyMode
2052362add9SBarry Smith 
206a997ad1aSLois Curfman McInnes     Output Parameter:
20790f02eecSBarry Smith .   mapping - new mapping data structure
2082362add9SBarry Smith 
209a997ad1aSLois Curfman McInnes     Level: advanced
210a997ad1aSLois Curfman McInnes 
211273d9f13SBarry Smith     Concepts: mapping^local to global
2122362add9SBarry Smith 
213d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2142362add9SBarry Smith @*/
2157087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2162362add9SBarry Smith {
2176849ba73SBarry Smith   PetscErrorCode ierr;
21832dcc486SBarry Smith   PetscInt       *in;
219b46b645bSBarry Smith 
220b46b645bSBarry Smith   PetscFunctionBegin;
22173911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2224482741eSBarry Smith   PetscValidPointer(mapping,4);
223b46b645bSBarry Smith 
2240298fd71SBarry Smith   *mapping = NULL;
225519f805aSKarl Rupp #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
226607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2278e58c17dSMatthew Knepley #endif
2282362add9SBarry Smith 
22967c2884eSBarry Smith   ierr = PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
23052e6d16bSBarry Smith                            cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
231d4bb536fSBarry Smith   (*mapping)->n = n;
232d4bb536fSBarry Smith   /*
233d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
234d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
235d4bb536fSBarry Smith   */
236d4bb536fSBarry Smith   (*mapping)->globals = 0;
237d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
238d5ad8652SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&in);CHKERRQ(ierr);
239d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
2403bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
241d5ad8652SBarry Smith     (*mapping)->indices = in;
242f6e5521dSKarl Rupp   } else if (mode == PETSC_OWN_POINTER) (*mapping)->indices = (PetscInt*)indices;
243f6e5521dSKarl Rupp   else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
2443a40ed3dSBarry Smith   PetscFunctionReturn(0);
2452362add9SBarry Smith }
2462362add9SBarry Smith 
2474a2ae208SSatish Balay #undef __FUNCT__
2484a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
249bce096a4SSatish Balay /*@
250323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
251323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
252323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
253323b833fSBarry Smith 
254323b833fSBarry Smith     Not Collective, but communicator may have more than one process
255323b833fSBarry Smith 
256323b833fSBarry Smith     Input Parameters:
257323b833fSBarry Smith +    inmap - original point-wise mapping
258323b833fSBarry Smith -    bs - block size
259323b833fSBarry Smith 
260323b833fSBarry Smith     Output Parameter:
26169eb54c3SBarry Smith .   outmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
262323b833fSBarry Smith 
263323b833fSBarry Smith     Level: advanced
264323b833fSBarry Smith 
265323b833fSBarry Smith     Concepts: mapping^local to global
266323b833fSBarry Smith 
267323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
268323b833fSBarry Smith @*/
2697087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
270323b833fSBarry Smith {
2716849ba73SBarry Smith   PetscErrorCode ierr;
27232dcc486SBarry Smith   PetscInt       *ii,i,n;
273323b833fSBarry Smith 
274323b833fSBarry Smith   PetscFunctionBegin;
2750700a824SBarry Smith   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
276b2beed0aSJed Brown   PetscValidPointer(outmap,3);
277323b833fSBarry Smith   if (bs > 1) {
278323b833fSBarry Smith     n = inmap->n/bs;
279e32f2f54SBarry Smith     if (n*bs != inmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Pointwise mapping length is not divisible by block size");
28032dcc486SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&ii);CHKERRQ(ierr);
281f6e5521dSKarl Rupp     for (i=0; i<n; i++) ii[i] = inmap->indices[bs*i]/bs;
282ce94432eSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)inmap),n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
283323b833fSBarry Smith   } else {
284323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
285c3122656SLisandro Dalcin     *outmap = inmap;
286323b833fSBarry Smith   }
287323b833fSBarry Smith   PetscFunctionReturn(0);
288323b833fSBarry Smith }
289323b833fSBarry Smith 
2904a2ae208SSatish Balay #undef __FUNCT__
2918ab951edSJed Brown #define __FUNCT__ "ISLocalToGlobalMappingUnBlock"
292b2beed0aSJed Brown /*@
293b2beed0aSJed Brown     ISLocalToGlobalMappingUnBlock - Creates a scalar index version of a blocked
294b2beed0aSJed Brown        ISLocalToGlobalMapping
295b2beed0aSJed Brown 
296b2beed0aSJed Brown     Not Collective, but communicator may have more than one process
297b2beed0aSJed Brown 
298b2beed0aSJed Brown     Input Parameter:
299b2beed0aSJed Brown + inmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
300b2beed0aSJed Brown - bs - block size
301b2beed0aSJed Brown 
302b2beed0aSJed Brown     Output Parameter:
303b2beed0aSJed Brown .   outmap - pointwise mapping
304b2beed0aSJed Brown 
305b2beed0aSJed Brown     Level: advanced
306b2beed0aSJed Brown 
307b2beed0aSJed Brown     Concepts: mapping^local to global
308b2beed0aSJed Brown 
309b2beed0aSJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingBlock()
310b2beed0aSJed Brown @*/
3117087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingUnBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
312b2beed0aSJed Brown {
313b2beed0aSJed Brown   PetscErrorCode ierr;
314b2beed0aSJed Brown   PetscInt       *ii,i,n;
315b2beed0aSJed Brown 
316b2beed0aSJed Brown   PetscFunctionBegin;
317b2beed0aSJed Brown   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
318b2beed0aSJed Brown   PetscValidPointer(outmap,2);
319b2beed0aSJed Brown   if (bs > 1) {
320b2beed0aSJed Brown     n    = inmap->n*bs;
321b2beed0aSJed Brown     ierr = PetscMalloc(n*sizeof(PetscInt),&ii);CHKERRQ(ierr);
322f6e5521dSKarl Rupp     for (i=0; i<n; i++) ii[i] = inmap->indices[i/bs]*bs + (i%bs);
323ce94432eSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)inmap),n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
324b2beed0aSJed Brown   } else {
325b2beed0aSJed Brown     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
326b2beed0aSJed Brown     *outmap = inmap;
327b2beed0aSJed Brown   }
328b2beed0aSJed Brown   PetscFunctionReturn(0);
329b2beed0aSJed Brown }
330b2beed0aSJed Brown 
331b2beed0aSJed Brown #undef __FUNCT__
3324a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
33390f02eecSBarry Smith /*@
33490f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
33590f02eecSBarry Smith    ordering and a global parallel ordering.
33690f02eecSBarry Smith 
3370f5bd95cSBarry Smith    Note Collective
338b9cd556bSLois Curfman McInnes 
33990f02eecSBarry Smith    Input Parameters:
34090f02eecSBarry Smith .  mapping - mapping data structure
34190f02eecSBarry Smith 
342a997ad1aSLois Curfman McInnes    Level: advanced
343a997ad1aSLois Curfman McInnes 
3443acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
34590f02eecSBarry Smith @*/
3466bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
34790f02eecSBarry Smith {
348dfbe8321SBarry Smith   PetscErrorCode ierr;
3495fd66863SKarl Rupp 
3503a40ed3dSBarry Smith   PetscFunctionBegin;
3516bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3526bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
353997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3546bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3556bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->globals);CHKERRQ(ierr);
356d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
357992144d0SBarry Smith   *mapping = 0;
3583a40ed3dSBarry Smith   PetscFunctionReturn(0);
35990f02eecSBarry Smith }
36090f02eecSBarry Smith 
3614a2ae208SSatish Balay #undef __FUNCT__
3624a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
36390f02eecSBarry Smith /*@
3643acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3653acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3663acfe500SLois Curfman McInnes     context.
36790f02eecSBarry Smith 
368b9cd556bSLois Curfman McInnes     Not collective
369b9cd556bSLois Curfman McInnes 
37090f02eecSBarry Smith     Input Parameters:
371b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
372b9cd556bSLois Curfman McInnes -   is - index set in local numbering
37390f02eecSBarry Smith 
37490f02eecSBarry Smith     Output Parameters:
37590f02eecSBarry Smith .   newis - index set in global numbering
37690f02eecSBarry Smith 
377a997ad1aSLois Curfman McInnes     Level: advanced
378a997ad1aSLois Curfman McInnes 
379273d9f13SBarry Smith     Concepts: mapping^local to global
3803acfe500SLois Curfman McInnes 
38190f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
382d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
38390f02eecSBarry Smith @*/
3847087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
38590f02eecSBarry Smith {
3866849ba73SBarry Smith   PetscErrorCode ierr;
3875d0c19d7SBarry Smith   PetscInt       n,i,*idxmap,*idxout,Nmax = mapping->n;
3885d0c19d7SBarry Smith   const PetscInt *idxin;
3893a40ed3dSBarry Smith 
3903a40ed3dSBarry Smith   PetscFunctionBegin;
3910700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3920700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3934482741eSBarry Smith   PetscValidPointer(newis,3);
39490f02eecSBarry Smith 
3953b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
39690f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
39790f02eecSBarry Smith   idxmap = mapping->indices;
39890f02eecSBarry Smith 
3997c334f02SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&idxout);CHKERRQ(ierr);
40090f02eecSBarry Smith   for (i=0; i<n; i++) {
401e32f2f54SBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax-1,i);
40290f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
40390f02eecSBarry Smith   }
4043b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
40570b3c8c7SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4063a40ed3dSBarry Smith   PetscFunctionReturn(0);
40790f02eecSBarry Smith }
40890f02eecSBarry Smith 
409afcb2eb5SJed Brown #undef __FUNCT__
410afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
411b89cb25eSSatish Balay /*@
4123acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4133acfe500SLois Curfman McInnes    and converts them to the global numbering.
41490f02eecSBarry Smith 
415b9cd556bSLois Curfman McInnes    Not collective
416b9cd556bSLois Curfman McInnes 
417bb25748dSBarry Smith    Input Parameters:
418b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
419bb25748dSBarry Smith .  N - number of integers
420b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
421bb25748dSBarry Smith 
422bb25748dSBarry Smith    Output Parameter:
423bb25748dSBarry Smith .  out - indices in global numbering
424bb25748dSBarry Smith 
425b9cd556bSLois Curfman McInnes    Notes:
426b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
427d4bb536fSBarry Smith 
428a997ad1aSLois Curfman McInnes    Level: advanced
429a997ad1aSLois Curfman McInnes 
430bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4310752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
432d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
433bb25748dSBarry Smith 
434273d9f13SBarry Smith     Concepts: mapping^local to global
435afcb2eb5SJed Brown @*/
436afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
437afcb2eb5SJed Brown {
438afcb2eb5SJed Brown   PetscInt       i,Nmax = mapping->n;
439afcb2eb5SJed Brown   const PetscInt *idx = mapping->indices;
440d4bb536fSBarry Smith 
441afcb2eb5SJed Brown   PetscFunctionBegin;
442afcb2eb5SJed Brown   for (i=0; i<N; i++) {
443afcb2eb5SJed Brown     if (in[i] < 0) {
444afcb2eb5SJed Brown       out[i] = in[i];
445afcb2eb5SJed Brown       continue;
446afcb2eb5SJed Brown     }
447afcb2eb5SJed Brown     if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax,i);
448afcb2eb5SJed Brown     out[i] = idx[in[i]];
449afcb2eb5SJed Brown   }
450afcb2eb5SJed Brown   PetscFunctionReturn(0);
451afcb2eb5SJed Brown }
452d4bb536fSBarry Smith 
453d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
454d4bb536fSBarry Smith 
4554a2ae208SSatish Balay #undef __FUNCT__
4564a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
457d4bb536fSBarry Smith /*
458d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
459d4bb536fSBarry Smith */
4606849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
461d4bb536fSBarry Smith {
4626849ba73SBarry Smith   PetscErrorCode ierr;
46332dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
464d4bb536fSBarry Smith 
4653a40ed3dSBarry Smith   PetscFunctionBegin;
466d4bb536fSBarry Smith   end   = 0;
467ec268f7cSJed Brown   start = PETSC_MAX_INT;
468d4bb536fSBarry Smith 
469d4bb536fSBarry Smith   for (i=0; i<n; i++) {
470d4bb536fSBarry Smith     if (idx[i] < 0) continue;
471d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
472d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
473d4bb536fSBarry Smith   }
474d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
475d4bb536fSBarry Smith   mapping->globalstart = start;
476d4bb536fSBarry Smith   mapping->globalend   = end;
477d4bb536fSBarry Smith 
47832dcc486SBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(PetscInt),&globals);CHKERRQ(ierr);
479b0a32e0cSBarry Smith   mapping->globals = globals;
480f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
481d4bb536fSBarry Smith   for (i=0; i<n; i++) {
482d4bb536fSBarry Smith     if (idx[i] < 0) continue;
483d4bb536fSBarry Smith     globals[idx[i] - start] = i;
484d4bb536fSBarry Smith   }
485d4bb536fSBarry Smith 
4863bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
4873a40ed3dSBarry Smith   PetscFunctionReturn(0);
488d4bb536fSBarry Smith }
489d4bb536fSBarry Smith 
4904a2ae208SSatish Balay #undef __FUNCT__
4914a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
492d4bb536fSBarry Smith /*@
493a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
494a997ad1aSLois Curfman McInnes     specified with a global numbering.
495d4bb536fSBarry Smith 
496b9cd556bSLois Curfman McInnes     Not collective
497b9cd556bSLois Curfman McInnes 
498d4bb536fSBarry Smith     Input Parameters:
499b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
500d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
501d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
502d4bb536fSBarry Smith .   n - number of global indices to map
503b9cd556bSLois Curfman McInnes -   idx - global indices to map
504d4bb536fSBarry Smith 
505d4bb536fSBarry Smith     Output Parameters:
506b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
507b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
508e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5090298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
510e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
511e182c471SBarry Smith              a second time to set the values.
512d4bb536fSBarry Smith 
513b9cd556bSLois Curfman McInnes     Notes:
5140298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
515d4bb536fSBarry Smith 
5160f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5170f5bd95cSBarry Smith     array to compute these.
5180f5bd95cSBarry Smith 
519a997ad1aSLois Curfman McInnes     Level: advanced
520a997ad1aSLois Curfman McInnes 
52132fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
52232fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
52332fd6b96SBarry Smith 
524273d9f13SBarry Smith     Concepts: mapping^global to local
525d4bb536fSBarry Smith 
526d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
527d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
528d4bb536fSBarry Smith @*/
5297087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
53032dcc486SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
531d4bb536fSBarry Smith {
53232dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
5336849ba73SBarry Smith   PetscErrorCode ierr;
534d4bb536fSBarry Smith 
5353a40ed3dSBarry Smith   PetscFunctionBegin;
5360700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
537d4bb536fSBarry Smith   if (!mapping->globals) {
538d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
539d4bb536fSBarry Smith   }
540d4bb536fSBarry Smith   globals = mapping->globals;
541d4bb536fSBarry Smith   start   = mapping->globalstart;
542d4bb536fSBarry Smith   end     = mapping->globalend;
543d4bb536fSBarry Smith 
544d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
545d4bb536fSBarry Smith     if (idxout) {
546d4bb536fSBarry Smith       for (i=0; i<n; i++) {
547d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
548d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
549d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
550d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
551d4bb536fSBarry Smith       }
552d4bb536fSBarry Smith     }
553d4bb536fSBarry Smith     if (nout) *nout = n;
554d4bb536fSBarry Smith   } else {
555d4bb536fSBarry Smith     if (idxout) {
556d4bb536fSBarry Smith       for (i=0; i<n; i++) {
557d4bb536fSBarry Smith         if (idx[i] < 0) continue;
558d4bb536fSBarry Smith         if (idx[i] < start) continue;
559d4bb536fSBarry Smith         if (idx[i] > end) continue;
560d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
561d4bb536fSBarry Smith         if (tmp < 0) continue;
562d4bb536fSBarry Smith         idxout[nf++] = tmp;
563d4bb536fSBarry Smith       }
564d4bb536fSBarry Smith     } else {
565d4bb536fSBarry Smith       for (i=0; i<n; i++) {
566d4bb536fSBarry Smith         if (idx[i] < 0) continue;
567d4bb536fSBarry Smith         if (idx[i] < start) continue;
568d4bb536fSBarry Smith         if (idx[i] > end) continue;
569d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
570d4bb536fSBarry Smith         if (tmp < 0) continue;
571d4bb536fSBarry Smith         nf++;
572d4bb536fSBarry Smith       }
573d4bb536fSBarry Smith     }
574d4bb536fSBarry Smith     if (nout) *nout = nf;
575d4bb536fSBarry Smith   }
5763a40ed3dSBarry Smith   PetscFunctionReturn(0);
577d4bb536fSBarry Smith }
57890f02eecSBarry Smith 
5794a2ae208SSatish Balay #undef __FUNCT__
5804a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
58189d82c54SBarry Smith /*@C
58289d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
58389d82c54SBarry Smith      each index shared by more than one processor
58489d82c54SBarry Smith 
58589d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
58689d82c54SBarry Smith 
58789d82c54SBarry Smith     Input Parameters:
58889d82c54SBarry Smith .   mapping - the mapping from local to global indexing
58989d82c54SBarry Smith 
59089d82c54SBarry Smith     Output Parameter:
59189d82c54SBarry Smith +   nproc - number of processors that are connected to this one
59289d82c54SBarry Smith .   proc - neighboring processors
59307b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
5943463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
59589d82c54SBarry Smith 
59689d82c54SBarry Smith     Level: advanced
59789d82c54SBarry Smith 
598273d9f13SBarry Smith     Concepts: mapping^local to global
59989d82c54SBarry Smith 
6002cfcea29SBarry Smith     Fortran Usage:
6012cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
6022cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
6032cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
6042cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
6052cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
6062cfcea29SBarry Smith 
6072cfcea29SBarry Smith 
60807b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
60907b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
61089d82c54SBarry Smith @*/
6117087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
61289d82c54SBarry Smith {
6136849ba73SBarry Smith   PetscErrorCode ierr;
61497f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
61532dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
61632dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
61797f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
61832dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
61932dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
62089d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
62130dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
622ce94432eSBarry Smith   MPI_Comm       comm;
623ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
62489d82c54SBarry Smith 
62589d82c54SBarry Smith   PetscFunctionBegin;
6260700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
627ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
62824cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
62924cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
63024cf384cSBarry Smith   if (size == 1) {
63124cf384cSBarry Smith     *nproc         = 0;
6320298fd71SBarry Smith     *procs         = NULL;
63332dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
6341e2105dcSBarry Smith     (*numprocs)[0] = 0;
63532dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
6360298fd71SBarry Smith     (*indices)[0]  = NULL;
63724cf384cSBarry Smith     PetscFunctionReturn(0);
63824cf384cSBarry Smith   }
63924cf384cSBarry Smith 
6400298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
64107b52d57SBarry Smith 
6423677ff5aSBarry Smith   /*
6433677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
6443677ff5aSBarry Smith 
6453677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
6463677ff5aSBarry Smith            numbering, just for this routine.
6473677ff5aSBarry Smith 
6483677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
6493677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
6503677ff5aSBarry Smith 
6513677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
6523677ff5aSBarry Smith 
6533677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
6543677ff5aSBarry Smith            local subdomain
6553677ff5aSBarry Smith   */
65624cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
65724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
65824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
65989d82c54SBarry Smith 
66089d82c54SBarry Smith   for (i=0; i<n; i++) {
66189d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
66289d82c54SBarry Smith   }
66332dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
66478058e43SBarry Smith   Ng++;
66589d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
66689d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
667bc8ff85bSBarry Smith   scale  = Ng/size + 1;
668a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
669caba0dd0SBarry Smith   rstart = scale*rank;
67089d82c54SBarry Smith 
67189d82c54SBarry Smith   /* determine ownership ranges of global indices */
6727c334f02SBarry Smith   ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
67332dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
67489d82c54SBarry Smith 
67589d82c54SBarry Smith   /* determine owners of each local node  */
6767c334f02SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&owner);CHKERRQ(ierr);
67789d82c54SBarry Smith   for (i=0; i<n; i++) {
6783677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
67927c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
6803677ff5aSBarry Smith     owner[i]         = proc;
68127c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
68289d82c54SBarry Smith   }
68327c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
6841e2582c4SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %d\n",nsends);CHKERRQ(ierr);
68589d82c54SBarry Smith 
68689d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
68727c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
6881e2582c4SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %d\n",nrecvs);CHKERRQ(ierr);
68989d82c54SBarry Smith 
69089d82c54SBarry Smith   /* post receives for owned rows */
69132dcc486SBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(PetscInt),&recvs);CHKERRQ(ierr);
692b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
69389d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
69432dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
69589d82c54SBarry Smith   }
69689d82c54SBarry Smith 
69789d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
69832dcc486SBarry Smith   ierr      = PetscMalloc((2*n+1)*sizeof(PetscInt),&sends);CHKERRQ(ierr);
69932dcc486SBarry Smith   ierr      = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
70089d82c54SBarry Smith   starts[0] = 0;
701f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
70289d82c54SBarry Smith   for (i=0; i<n; i++) {
70389d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
70430dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
70589d82c54SBarry Smith   }
70689d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
70789d82c54SBarry Smith   starts[0] = 0;
708f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
70989d82c54SBarry Smith 
71089d82c54SBarry Smith   /* send the messages */
711b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
71232dcc486SBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(PetscInt),&dest);CHKERRQ(ierr);
71389d82c54SBarry Smith   cnt = 0;
71489d82c54SBarry Smith   for (i=0; i<size; i++) {
71527c402fcSBarry Smith     if (nprocs[2*i]) {
71632dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
71730dcb7c9SBarry Smith       dest[cnt] = i;
71889d82c54SBarry Smith       cnt++;
71989d82c54SBarry Smith     }
72089d82c54SBarry Smith   }
72189d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
72289d82c54SBarry Smith 
72389d82c54SBarry Smith   /* wait on receives */
72497f1f81fSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(PetscMPIInt),&source);CHKERRQ(ierr);
72597f1f81fSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(PetscMPIInt),&len);CHKERRQ(ierr);
72689d82c54SBarry Smith   cnt  = nrecvs;
72732dcc486SBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(PetscInt),&nownedsenders);CHKERRQ(ierr);
72832dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
72989d82c54SBarry Smith   while (cnt) {
73089d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
73189d82c54SBarry Smith     /* unpack receives into our local space */
73232dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
73389d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
73430dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
735caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
73630dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
73789d82c54SBarry Smith     cnt--;
73889d82c54SBarry Smith   }
73989d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
74089d82c54SBarry Smith 
74130dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
742bc8ff85bSBarry Smith   nowned  = 0;
743bc8ff85bSBarry Smith   nownedm = 0;
744bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
745bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
746bc8ff85bSBarry Smith   }
747bc8ff85bSBarry Smith 
748bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
74932dcc486SBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(PetscInt),&ownedsenders);CHKERRQ(ierr);
75032dcc486SBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
751bc8ff85bSBarry Smith   starts[0] = 0;
752bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
753bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
754bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
755bc8ff85bSBarry Smith   }
756bc8ff85bSBarry Smith 
75730dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
758bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
759bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
76030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
761f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
762bc8ff85bSBarry Smith     }
763bc8ff85bSBarry Smith   }
764bc8ff85bSBarry Smith 
76507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
76630dcb7c9SBarry Smith     starts[0] = 0;
76730dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
76830dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
76930dcb7c9SBarry Smith       else starts[i] = starts[i-1];
77030dcb7c9SBarry Smith     }
77130dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
77230dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
77330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
77430dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
77530dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
77630dcb7c9SBarry Smith         }
77730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
77830dcb7c9SBarry Smith       }
77930dcb7c9SBarry Smith     }
78030dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
78107b52d57SBarry Smith   } /* -----------------------------------  */
78230dcb7c9SBarry Smith 
7833677ff5aSBarry Smith   /* wait on original sends */
7843a96401aSBarry Smith   if (nsends) {
785b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
7863a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
7873a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
7883a96401aSBarry Smith   }
78989d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
7903a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
7913677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
7923677ff5aSBarry Smith 
7933677ff5aSBarry Smith   /* pack messages to send back to local owners */
79430dcb7c9SBarry Smith   starts[0] = 0;
79530dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
79630dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
79730dcb7c9SBarry Smith     else starts[i] = starts[i-1];
79830dcb7c9SBarry Smith   }
79930dcb7c9SBarry Smith   nsends2 = nrecvs;
80032dcc486SBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(PetscInt),&nprocs);CHKERRQ(ierr); /* length of each message */
80130dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
80230dcb7c9SBarry Smith     nprocs[i] = 1;
80330dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
80430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
805f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
80630dcb7c9SBarry Smith     }
80730dcb7c9SBarry Smith   }
808f6e5521dSKarl Rupp   nt = 0;
809f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
810f6e5521dSKarl Rupp 
81132dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&sends2);CHKERRQ(ierr);
81232dcc486SBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(PetscInt),&starts2);CHKERRQ(ierr);
813f6e5521dSKarl Rupp 
814f6e5521dSKarl Rupp   starts2[0] = 0;
815f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
81630dcb7c9SBarry Smith   /*
81730dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
81830dcb7c9SBarry Smith        (0) the number of nodes being sent back
81930dcb7c9SBarry Smith        (1) the local node number,
82030dcb7c9SBarry Smith        (2) the number of processors sharing it,
82130dcb7c9SBarry Smith        (3) the processors sharing it
82230dcb7c9SBarry Smith   */
82330dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
82430dcb7c9SBarry Smith     cnt = 1;
82530dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
82630dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
82730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
82830dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
82930dcb7c9SBarry Smith         sends2[starts2[i]]++;
83030dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
83130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
83232dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
83330dcb7c9SBarry Smith         cnt += nownedsenders[node];
83430dcb7c9SBarry Smith       }
83530dcb7c9SBarry Smith     }
83630dcb7c9SBarry Smith   }
83730dcb7c9SBarry Smith 
83830dcb7c9SBarry Smith   /* receive the message lengths */
83930dcb7c9SBarry Smith   nrecvs2 = nsends;
84032dcc486SBarry Smith   ierr    = PetscMalloc((nrecvs2+1)*sizeof(PetscInt),&lens2);CHKERRQ(ierr);
84132dcc486SBarry Smith   ierr    = PetscMalloc((nrecvs2+1)*sizeof(PetscInt),&starts3);CHKERRQ(ierr);
842d44834fbSBarry Smith   ierr    = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
84330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
844d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
84530dcb7c9SBarry Smith   }
846d44834fbSBarry Smith 
8478a8e0b3aSBarry Smith   /* send the message lengths */
8488a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
8498a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
8508a8e0b3aSBarry Smith   }
8518a8e0b3aSBarry Smith 
852d44834fbSBarry Smith   /* wait on receives of lens */
8530c468ba9SBarry Smith   if (nrecvs2) {
8540c468ba9SBarry Smith     ierr = PetscMalloc(nrecvs2*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
855d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
856d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
8570c468ba9SBarry Smith   }
858a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
859d44834fbSBarry Smith 
86030dcb7c9SBarry Smith   starts3[0] = 0;
861d44834fbSBarry Smith   nt         = 0;
86230dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
86330dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
864d44834fbSBarry Smith     nt          += lens2[i];
86530dcb7c9SBarry Smith   }
86676466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
867d44834fbSBarry Smith 
86832dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&recvs2);CHKERRQ(ierr);
869b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
87052b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
87132dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
87230dcb7c9SBarry Smith   }
87330dcb7c9SBarry Smith 
87430dcb7c9SBarry Smith   /* send the messages */
875b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
87630dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
87732dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
87830dcb7c9SBarry Smith   }
87930dcb7c9SBarry Smith 
88030dcb7c9SBarry Smith   /* wait on receives */
8810c468ba9SBarry Smith   if (nrecvs2) {
8820c468ba9SBarry Smith     ierr = PetscMalloc(nrecvs2*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
88330dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
88430dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
8850c468ba9SBarry Smith   }
88630dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
88730dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
88830dcb7c9SBarry Smith 
88907b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
89030dcb7c9SBarry Smith     cnt = 0;
89130dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
89230dcb7c9SBarry Smith       nt = recvs2[cnt++];
89330dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
89430dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
89530dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
89630dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
89730dcb7c9SBarry Smith         }
89830dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
89930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
90030dcb7c9SBarry Smith       }
90130dcb7c9SBarry Smith     }
90230dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
90307b52d57SBarry Smith   } /* -----------------------------------  */
90430dcb7c9SBarry Smith 
90530dcb7c9SBarry Smith   /* count number subdomains for each local node */
90632dcc486SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
90732dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
90830dcb7c9SBarry Smith   cnt  = 0;
90930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
91030dcb7c9SBarry Smith     nt = recvs2[cnt++];
91130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
912f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
91330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
91430dcb7c9SBarry Smith     }
91530dcb7c9SBarry Smith   }
91630dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
91730dcb7c9SBarry Smith   *nproc    = nt;
91832dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),procs);CHKERRQ(ierr);
91932dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),numprocs);CHKERRQ(ierr);
92032dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt*),indices);CHKERRQ(ierr);
9210298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
92232dcc486SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscInt),&bprocs);CHKERRQ(ierr);
92330dcb7c9SBarry Smith   cnt       = 0;
92430dcb7c9SBarry Smith   for (i=0; i<size; i++) {
92530dcb7c9SBarry Smith     if (nprocs[i] > 0) {
92630dcb7c9SBarry Smith       bprocs[i]        = cnt;
92730dcb7c9SBarry Smith       (*procs)[cnt]    = i;
92830dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
92932dcc486SBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(PetscInt),&(*indices)[cnt]);CHKERRQ(ierr);
93030dcb7c9SBarry Smith       cnt++;
93130dcb7c9SBarry Smith     }
93230dcb7c9SBarry Smith   }
93330dcb7c9SBarry Smith 
93430dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
93532dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
93630dcb7c9SBarry Smith   cnt  = 0;
93730dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
93830dcb7c9SBarry Smith     nt = recvs2[cnt++];
93930dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
940f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
94130dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
94230dcb7c9SBarry Smith     }
94330dcb7c9SBarry Smith   }
94430dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
94507b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
94630dcb7c9SBarry Smith 
94707b52d57SBarry Smith   /* sort the node indexing by their global numbers */
94807b52d57SBarry Smith   nt = *nproc;
94907b52d57SBarry Smith   for (i=0; i<nt; i++) {
95032dcc486SBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(PetscInt),&tmp);CHKERRQ(ierr);
951f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
95207b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
95307b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
95407b52d57SBarry Smith   }
95507b52d57SBarry Smith 
95607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
95730dcb7c9SBarry Smith     nt = *nproc;
95830dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
95930dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
96030dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
96130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
96230dcb7c9SBarry Smith       }
96330dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
96430dcb7c9SBarry Smith     }
96530dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
96607b52d57SBarry Smith   } /* -----------------------------------  */
96730dcb7c9SBarry Smith 
96830dcb7c9SBarry Smith   /* wait on sends */
96930dcb7c9SBarry Smith   if (nsends2) {
970b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
97130dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
97230dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
97330dcb7c9SBarry Smith   }
97430dcb7c9SBarry Smith 
97530dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
97630dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
97730dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
9783677ff5aSBarry Smith 
979bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
980bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
981bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
98230dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
98330dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
98489d82c54SBarry Smith 
98589d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
98697f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
98789d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
9883a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
98930dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
99024cf384cSBarry Smith 
99124cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
99224cf384cSBarry Smith   first_procs    = (*procs)[0];
99324cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
99424cf384cSBarry Smith   first_indices  = (*indices)[0];
99524cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
99624cf384cSBarry Smith     if ((*procs)[i] == rank) {
99724cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
99824cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
99924cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
100024cf384cSBarry Smith       (*procs)[i]    = first_procs;
100124cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
100224cf384cSBarry Smith       (*indices)[i]  = first_indices;
100324cf384cSBarry Smith       break;
100424cf384cSBarry Smith     }
100524cf384cSBarry Smith   }
100689d82c54SBarry Smith   PetscFunctionReturn(0);
100789d82c54SBarry Smith }
100889d82c54SBarry Smith 
10094a2ae208SSatish Balay #undef __FUNCT__
10104a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
101107b52d57SBarry Smith /*@C
101207b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
101389d82c54SBarry Smith 
101407b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
101507b52d57SBarry Smith 
101607b52d57SBarry Smith     Input Parameters:
101707b52d57SBarry Smith .   mapping - the mapping from local to global indexing
101807b52d57SBarry Smith 
101907b52d57SBarry Smith     Output Parameter:
102007b52d57SBarry Smith +   nproc - number of processors that are connected to this one
102107b52d57SBarry Smith .   proc - neighboring processors
102207b52d57SBarry Smith .   numproc - number of indices for each processor
102307b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
102407b52d57SBarry Smith 
102507b52d57SBarry Smith     Level: advanced
102607b52d57SBarry Smith 
102707b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
102807b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
102907b52d57SBarry Smith @*/
10307087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
103107b52d57SBarry Smith {
10326849ba73SBarry Smith   PetscErrorCode ierr;
103332dcc486SBarry Smith   PetscInt       i;
103407b52d57SBarry Smith 
103507b52d57SBarry Smith   PetscFunctionBegin;
103605b42c5fSBarry Smith   ierr = PetscFree(*procs);CHKERRQ(ierr);
103705b42c5fSBarry Smith   ierr = PetscFree(*numprocs);CHKERRQ(ierr);
103800ff320aSBarry Smith   if (*indices) {
103905b42c5fSBarry Smith     ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
104000ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
104105b42c5fSBarry Smith       ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
104207b52d57SBarry Smith     }
104307b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
104424cf384cSBarry Smith   }
104507b52d57SBarry Smith   PetscFunctionReturn(0);
104607b52d57SBarry Smith }
104786994e45SJed Brown 
104886994e45SJed Brown #undef __FUNCT__
104986994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
105086994e45SJed Brown /*@C
105186994e45SJed Brown    ISLocalToGlobalMappingGetIndices - Get global indices for every local point
105286994e45SJed Brown 
105386994e45SJed Brown    Not Collective
105486994e45SJed Brown 
105586994e45SJed Brown    Input Arguments:
105686994e45SJed Brown . ltog - local to global mapping
105786994e45SJed Brown 
105886994e45SJed Brown    Output Arguments:
105986994e45SJed Brown . array - array of indices
106086994e45SJed Brown 
106186994e45SJed Brown    Level: advanced
106286994e45SJed Brown 
106386994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices()
106486994e45SJed Brown @*/
10657087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
106686994e45SJed Brown {
106786994e45SJed Brown   PetscFunctionBegin;
106886994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
106986994e45SJed Brown   PetscValidPointer(array,2);
107086994e45SJed Brown   *array = ltog->indices;
107186994e45SJed Brown   PetscFunctionReturn(0);
107286994e45SJed Brown }
107386994e45SJed Brown 
107486994e45SJed Brown #undef __FUNCT__
107586994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
107686994e45SJed Brown /*@C
107786994e45SJed Brown    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingRestoreIndices()
107886994e45SJed Brown 
107986994e45SJed Brown    Not Collective
108086994e45SJed Brown 
108186994e45SJed Brown    Input Arguments:
108286994e45SJed Brown + ltog - local to global mapping
108386994e45SJed Brown - array - array of indices
108486994e45SJed Brown 
108586994e45SJed Brown    Level: advanced
108686994e45SJed Brown 
108786994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
108886994e45SJed Brown @*/
10897087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
109086994e45SJed Brown {
109186994e45SJed Brown   PetscFunctionBegin;
109286994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
109386994e45SJed Brown   PetscValidPointer(array,2);
109486994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
10950298fd71SBarry Smith   *array = NULL;
109686994e45SJed Brown   PetscFunctionReturn(0);
109786994e45SJed Brown }
1098f7efa3c7SJed Brown 
1099f7efa3c7SJed Brown #undef __FUNCT__
1100f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1101f7efa3c7SJed Brown /*@C
1102f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1103f7efa3c7SJed Brown 
1104f7efa3c7SJed Brown    Not Collective
1105f7efa3c7SJed Brown 
1106f7efa3c7SJed Brown    Input Arguments:
1107f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1108f7efa3c7SJed Brown . n - number of mappings to concatenate
1109f7efa3c7SJed Brown - ltogs - local to global mappings
1110f7efa3c7SJed Brown 
1111f7efa3c7SJed Brown    Output Arguments:
1112f7efa3c7SJed Brown . ltogcat - new mapping
1113f7efa3c7SJed Brown 
1114f7efa3c7SJed Brown    Level: advanced
1115f7efa3c7SJed Brown 
1116f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1117f7efa3c7SJed Brown @*/
1118f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1119f7efa3c7SJed Brown {
1120f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1121f7efa3c7SJed Brown   PetscErrorCode ierr;
1122f7efa3c7SJed Brown 
1123f7efa3c7SJed Brown   PetscFunctionBegin;
1124f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1125f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1126f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1127f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1128f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1129f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1130f7efa3c7SJed Brown     cnt += m;
1131f7efa3c7SJed Brown   }
1132f7efa3c7SJed Brown   ierr = PetscMalloc(cnt*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1133f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1134f7efa3c7SJed Brown     const PetscInt *subidx;
1135f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1136f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1137f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1138f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1139f7efa3c7SJed Brown     cnt += m;
1140f7efa3c7SJed Brown   }
1141f7efa3c7SJed Brown   ierr = ISLocalToGlobalMappingCreate(comm,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1142f7efa3c7SJed Brown   PetscFunctionReturn(0);
1143f7efa3c7SJed Brown }
1144*04a59952SBarry Smith 
1145*04a59952SBarry Smith 
1146