xref: /petsc/src/vec/is/utils/isltog.c (revision 186d4ecdc2f8f3d4a2a0951ddba16cdc5cd22fa1)
12362add9SBarry Smith 
2b45d2f2cSJed Brown #include <petsc-private/isimpl.h>    /*I "petscis.h"  I*/
32362add9SBarry Smith 
47087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID;
58e58c17dSMatthew Knepley 
64a2ae208SSatish Balay #undef __FUNCT__
7*186d4ecdSBarry Smith #define __FUNCT__ "ISL2GMapApply"
8*186d4ecdSBarry Smith PetscErrorCode ISG2LMapApply(ISLocalToGlobalMapping mapping,PetscInt n,const PetscInt in[],PetscInt out[])
9*186d4ecdSBarry Smith {
10*186d4ecdSBarry Smith   PetscErrorCode ierr;
11*186d4ecdSBarry Smith   PetscInt       i,*globals = mapping->globals,start = mapping->globalstart,end = mapping->globalend;
12*186d4ecdSBarry Smith 
13*186d4ecdSBarry Smith   PetscFunctionBegin;
14*186d4ecdSBarry Smith   if (!mapping->globals) {
15*186d4ecdSBarry Smith     ierr = ISGlobalToLocalMappingApply(mapping,IS_GTOLM_MASK,0,0,0,0);CHKERRQ(ierr);
16*186d4ecdSBarry Smith   }
17*186d4ecdSBarry Smith   for (i=0; i<n; i++) {
18*186d4ecdSBarry Smith     if (in[i] < 0)          out[i] = in[i];
19*186d4ecdSBarry Smith     else if (in[i] < start) out[i] = -1;
20*186d4ecdSBarry Smith     else if (in[i] > end)   out[i] = -1;
21*186d4ecdSBarry Smith     else                    out[i] = globals[in[i] - start];
22*186d4ecdSBarry Smith   }
23*186d4ecdSBarry Smith   PetscFunctionReturn(0);
24*186d4ecdSBarry Smith }
25*186d4ecdSBarry Smith 
26*186d4ecdSBarry Smith 
27*186d4ecdSBarry Smith #undef __FUNCT__
284a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
293b9aefa3SBarry Smith /*@C
303b9aefa3SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping.
313b9aefa3SBarry Smith 
323b9aefa3SBarry Smith     Not Collective
333b9aefa3SBarry Smith 
343b9aefa3SBarry Smith     Input Parameter:
353b9aefa3SBarry Smith .   ltog - local to global mapping
363b9aefa3SBarry Smith 
373b9aefa3SBarry Smith     Output Parameter:
383b9aefa3SBarry Smith .   n - the number of entries in the local mapping
393b9aefa3SBarry Smith 
403b9aefa3SBarry Smith     Level: advanced
413b9aefa3SBarry Smith 
42273d9f13SBarry Smith     Concepts: mapping^local to global
433b9aefa3SBarry Smith 
443b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
453b9aefa3SBarry Smith @*/
467087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
473b9aefa3SBarry Smith {
483b9aefa3SBarry Smith   PetscFunctionBegin;
490700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
504482741eSBarry Smith   PetscValidIntPointer(n,2);
513b9aefa3SBarry Smith   *n = mapping->n;
523b9aefa3SBarry Smith   PetscFunctionReturn(0);
533b9aefa3SBarry Smith }
543b9aefa3SBarry Smith 
554a2ae208SSatish Balay #undef __FUNCT__
564a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
575a5d4f66SBarry Smith /*@C
585a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
595a5d4f66SBarry Smith 
60b9cd556bSLois Curfman McInnes     Not Collective
61b9cd556bSLois Curfman McInnes 
625a5d4f66SBarry Smith     Input Parameters:
633b9aefa3SBarry Smith +   ltog - local to global mapping
643b9aefa3SBarry Smith -   viewer - viewer
655a5d4f66SBarry Smith 
66a997ad1aSLois Curfman McInnes     Level: advanced
67a997ad1aSLois Curfman McInnes 
68273d9f13SBarry Smith     Concepts: mapping^local to global
695a5d4f66SBarry Smith 
705a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
715a5d4f66SBarry Smith @*/
727087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
735a5d4f66SBarry Smith {
7432dcc486SBarry Smith   PetscInt       i;
7532dcc486SBarry Smith   PetscMPIInt    rank;
76ace3abfcSBarry Smith   PetscBool      iascii;
776849ba73SBarry Smith   PetscErrorCode ierr;
785a5d4f66SBarry Smith 
795a5d4f66SBarry Smith   PetscFunctionBegin;
800700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
813050cee2SBarry Smith   if (!viewer) {
82ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
833050cee2SBarry Smith   }
840700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
855a5d4f66SBarry Smith 
86ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
87251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
8832077d6dSBarry Smith   if (iascii) {
897b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
905a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
91b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
926831982aSBarry Smith     }
93b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
947b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
957b23a99aSBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
965a5d4f66SBarry Smith   PetscFunctionReturn(0);
975a5d4f66SBarry Smith }
985a5d4f66SBarry Smith 
994a2ae208SSatish Balay #undef __FUNCT__
1004a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1011f428162SBarry Smith /*@
1022bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1032bdab257SBarry Smith     ordering and a global parallel ordering.
1042bdab257SBarry Smith 
1050f5bd95cSBarry Smith     Not collective
106b9cd556bSLois Curfman McInnes 
107a997ad1aSLois Curfman McInnes     Input Parameter:
1088c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1092bdab257SBarry Smith 
110a997ad1aSLois Curfman McInnes     Output Parameter:
1112bdab257SBarry Smith .   mapping - new mapping data structure
1122bdab257SBarry Smith 
113a997ad1aSLois Curfman McInnes     Level: advanced
114a997ad1aSLois Curfman McInnes 
115273d9f13SBarry Smith     Concepts: mapping^local to global
1162bdab257SBarry Smith 
1172bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1182bdab257SBarry Smith @*/
1197087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1202bdab257SBarry Smith {
1216849ba73SBarry Smith   PetscErrorCode ierr;
1225d0c19d7SBarry Smith   PetscInt       n;
1235d0c19d7SBarry Smith   const PetscInt *indices;
1242bdab257SBarry Smith   MPI_Comm       comm;
1253a40ed3dSBarry Smith 
1263a40ed3dSBarry Smith   PetscFunctionBegin;
1270700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1284482741eSBarry Smith   PetscValidPointer(mapping,2);
1292bdab257SBarry Smith 
1302bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1313b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1322bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
133d5ad8652SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1342bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1353a40ed3dSBarry Smith   PetscFunctionReturn(0);
1362bdab257SBarry Smith }
1375a5d4f66SBarry Smith 
138a4d96a55SJed Brown #undef __FUNCT__
139a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
140a4d96a55SJed Brown /*@C
141a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
142a4d96a55SJed Brown     ordering and a global parallel ordering.
143a4d96a55SJed Brown 
144a4d96a55SJed Brown     Collective
145a4d96a55SJed Brown 
146a4d96a55SJed Brown     Input Parameter:
147a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
148a4d96a55SJed Brown -   start - first global index on this process
149a4d96a55SJed Brown 
150a4d96a55SJed Brown     Output Parameter:
151a4d96a55SJed Brown .   mapping - new mapping data structure
152a4d96a55SJed Brown 
153a4d96a55SJed Brown     Level: advanced
154a4d96a55SJed Brown 
155a4d96a55SJed Brown     Concepts: mapping^local to global
156a4d96a55SJed Brown 
157a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
158a4d96a55SJed Brown @*/
159a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
160a4d96a55SJed Brown {
161a4d96a55SJed Brown   PetscErrorCode ierr;
162a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
163a4d96a55SJed Brown   const PetscInt *ilocal;
164a4d96a55SJed Brown   MPI_Comm       comm;
165a4d96a55SJed Brown 
166a4d96a55SJed Brown   PetscFunctionBegin;
167a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
168a4d96a55SJed Brown   PetscValidPointer(mapping,3);
169a4d96a55SJed Brown 
170a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1710298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
172f6e5521dSKarl Rupp   if (ilocal) {
173f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
174f6e5521dSKarl Rupp   }
175a4d96a55SJed Brown   else maxlocal = nleaves;
176a4d96a55SJed Brown   ierr = PetscMalloc(nroots*sizeof(PetscInt),&globals);CHKERRQ(ierr);
177a4d96a55SJed Brown   ierr = PetscMalloc(maxlocal*sizeof(PetscInt),&ltog);CHKERRQ(ierr);
178a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
179a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
180a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
181a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
182a4d96a55SJed Brown   ierr = ISLocalToGlobalMappingCreate(comm,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
183a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
184a4d96a55SJed Brown   PetscFunctionReturn(0);
185a4d96a55SJed Brown }
186b46b645bSBarry Smith 
1874a2ae208SSatish Balay #undef __FUNCT__
1884a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
189ba5bb76aSSatish Balay /*@
19090f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
19190f02eecSBarry Smith     ordering and a global parallel ordering.
1922362add9SBarry Smith 
19389d82c54SBarry Smith     Not Collective, but communicator may have more than one process
194b9cd556bSLois Curfman McInnes 
1952362add9SBarry Smith     Input Parameters:
19689d82c54SBarry Smith +   comm - MPI communicator
19790f02eecSBarry Smith .   n - the number of local elements
1989669e4d8SBarry Smith .   indices - the global index for each local element, these do not need to be in increasing order (sorted)
199d5ad8652SBarry Smith -   mode - see PetscCopyMode
2002362add9SBarry Smith 
201a997ad1aSLois Curfman McInnes     Output Parameter:
20290f02eecSBarry Smith .   mapping - new mapping data structure
2032362add9SBarry Smith 
204a997ad1aSLois Curfman McInnes     Level: advanced
205a997ad1aSLois Curfman McInnes 
206273d9f13SBarry Smith     Concepts: mapping^local to global
2072362add9SBarry Smith 
208d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2092362add9SBarry Smith @*/
2107087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2112362add9SBarry Smith {
2126849ba73SBarry Smith   PetscErrorCode ierr;
21332dcc486SBarry Smith   PetscInt       *in;
214b46b645bSBarry Smith 
215b46b645bSBarry Smith   PetscFunctionBegin;
21673911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2174482741eSBarry Smith   PetscValidPointer(mapping,4);
218b46b645bSBarry Smith 
2190298fd71SBarry Smith   *mapping = NULL;
220519f805aSKarl Rupp #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
2210298fd71SBarry Smith   ierr = ISInitializePackage(NULL);CHKERRQ(ierr);
2228e58c17dSMatthew Knepley #endif
2232362add9SBarry Smith 
22467c2884eSBarry Smith   ierr = PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
22552e6d16bSBarry Smith                            cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
226d4bb536fSBarry Smith   (*mapping)->n = n;
227d4bb536fSBarry Smith   /*
228d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
229d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
230d4bb536fSBarry Smith   */
231d4bb536fSBarry Smith   (*mapping)->globals = 0;
232d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
233d5ad8652SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&in);CHKERRQ(ierr);
234d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
235d5ad8652SBarry Smith     ierr = PetscLogObjectMemory(*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
236d5ad8652SBarry Smith     (*mapping)->indices = in;
237f6e5521dSKarl Rupp   } else if (mode == PETSC_OWN_POINTER) (*mapping)->indices = (PetscInt*)indices;
238f6e5521dSKarl Rupp   else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
2393a40ed3dSBarry Smith   PetscFunctionReturn(0);
2402362add9SBarry Smith }
2412362add9SBarry Smith 
2424a2ae208SSatish Balay #undef __FUNCT__
2434a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
244bce096a4SSatish Balay /*@
245323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
246323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
247323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
248323b833fSBarry Smith 
249323b833fSBarry Smith     Not Collective, but communicator may have more than one process
250323b833fSBarry Smith 
251323b833fSBarry Smith     Input Parameters:
252323b833fSBarry Smith +    inmap - original point-wise mapping
253323b833fSBarry Smith -    bs - block size
254323b833fSBarry Smith 
255323b833fSBarry Smith     Output Parameter:
25669eb54c3SBarry Smith .   outmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
257323b833fSBarry Smith 
258323b833fSBarry Smith     Level: advanced
259323b833fSBarry Smith 
260323b833fSBarry Smith     Concepts: mapping^local to global
261323b833fSBarry Smith 
262323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
263323b833fSBarry Smith @*/
2647087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
265323b833fSBarry Smith {
2666849ba73SBarry Smith   PetscErrorCode ierr;
26732dcc486SBarry Smith   PetscInt       *ii,i,n;
268323b833fSBarry Smith 
269323b833fSBarry Smith   PetscFunctionBegin;
2700700a824SBarry Smith   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
271b2beed0aSJed Brown   PetscValidPointer(outmap,3);
272323b833fSBarry Smith   if (bs > 1) {
273323b833fSBarry Smith     n = inmap->n/bs;
274e32f2f54SBarry Smith     if (n*bs != inmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Pointwise mapping length is not divisible by block size");
27532dcc486SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&ii);CHKERRQ(ierr);
276f6e5521dSKarl Rupp     for (i=0; i<n; i++) ii[i] = inmap->indices[bs*i]/bs;
277ce94432eSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)inmap),n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
278323b833fSBarry Smith   } else {
279323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
280c3122656SLisandro Dalcin     *outmap = inmap;
281323b833fSBarry Smith   }
282323b833fSBarry Smith   PetscFunctionReturn(0);
283323b833fSBarry Smith }
284323b833fSBarry Smith 
2854a2ae208SSatish Balay #undef __FUNCT__
2868ab951edSJed Brown #define __FUNCT__ "ISLocalToGlobalMappingUnBlock"
287b2beed0aSJed Brown /*@
288b2beed0aSJed Brown     ISLocalToGlobalMappingUnBlock - Creates a scalar index version of a blocked
289b2beed0aSJed Brown        ISLocalToGlobalMapping
290b2beed0aSJed Brown 
291b2beed0aSJed Brown     Not Collective, but communicator may have more than one process
292b2beed0aSJed Brown 
293b2beed0aSJed Brown     Input Parameter:
294b2beed0aSJed Brown + inmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
295b2beed0aSJed Brown - bs - block size
296b2beed0aSJed Brown 
297b2beed0aSJed Brown     Output Parameter:
298b2beed0aSJed Brown .   outmap - pointwise mapping
299b2beed0aSJed Brown 
300b2beed0aSJed Brown     Level: advanced
301b2beed0aSJed Brown 
302b2beed0aSJed Brown     Concepts: mapping^local to global
303b2beed0aSJed Brown 
304b2beed0aSJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingBlock()
305b2beed0aSJed Brown @*/
3067087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingUnBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
307b2beed0aSJed Brown {
308b2beed0aSJed Brown   PetscErrorCode ierr;
309b2beed0aSJed Brown   PetscInt       *ii,i,n;
310b2beed0aSJed Brown 
311b2beed0aSJed Brown   PetscFunctionBegin;
312b2beed0aSJed Brown   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
313b2beed0aSJed Brown   PetscValidPointer(outmap,2);
314b2beed0aSJed Brown   if (bs > 1) {
315b2beed0aSJed Brown     n    = inmap->n*bs;
316b2beed0aSJed Brown     ierr = PetscMalloc(n*sizeof(PetscInt),&ii);CHKERRQ(ierr);
317f6e5521dSKarl Rupp     for (i=0; i<n; i++) ii[i] = inmap->indices[i/bs]*bs + (i%bs);
318ce94432eSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)inmap),n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
319b2beed0aSJed Brown   } else {
320b2beed0aSJed Brown     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
321b2beed0aSJed Brown     *outmap = inmap;
322b2beed0aSJed Brown   }
323b2beed0aSJed Brown   PetscFunctionReturn(0);
324b2beed0aSJed Brown }
325b2beed0aSJed Brown 
326b2beed0aSJed Brown #undef __FUNCT__
3274a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
32890f02eecSBarry Smith /*@
32990f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
33090f02eecSBarry Smith    ordering and a global parallel ordering.
33190f02eecSBarry Smith 
3320f5bd95cSBarry Smith    Note Collective
333b9cd556bSLois Curfman McInnes 
33490f02eecSBarry Smith    Input Parameters:
33590f02eecSBarry Smith .  mapping - mapping data structure
33690f02eecSBarry Smith 
337a997ad1aSLois Curfman McInnes    Level: advanced
338a997ad1aSLois Curfman McInnes 
3393acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
34090f02eecSBarry Smith @*/
3416bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
34290f02eecSBarry Smith {
343dfbe8321SBarry Smith   PetscErrorCode ierr;
3445fd66863SKarl Rupp 
3453a40ed3dSBarry Smith   PetscFunctionBegin;
3466bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3476bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
348997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3496bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3506bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->globals);CHKERRQ(ierr);
351d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
352992144d0SBarry Smith   *mapping = 0;
3533a40ed3dSBarry Smith   PetscFunctionReturn(0);
35490f02eecSBarry Smith }
35590f02eecSBarry Smith 
3564a2ae208SSatish Balay #undef __FUNCT__
3574a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
35890f02eecSBarry Smith /*@
3593acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3603acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3613acfe500SLois Curfman McInnes     context.
36290f02eecSBarry Smith 
363b9cd556bSLois Curfman McInnes     Not collective
364b9cd556bSLois Curfman McInnes 
36590f02eecSBarry Smith     Input Parameters:
366b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
367b9cd556bSLois Curfman McInnes -   is - index set in local numbering
36890f02eecSBarry Smith 
36990f02eecSBarry Smith     Output Parameters:
37090f02eecSBarry Smith .   newis - index set in global numbering
37190f02eecSBarry Smith 
372a997ad1aSLois Curfman McInnes     Level: advanced
373a997ad1aSLois Curfman McInnes 
374273d9f13SBarry Smith     Concepts: mapping^local to global
3753acfe500SLois Curfman McInnes 
37690f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
377d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
37890f02eecSBarry Smith @*/
3797087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
38090f02eecSBarry Smith {
3816849ba73SBarry Smith   PetscErrorCode ierr;
3825d0c19d7SBarry Smith   PetscInt       n,i,*idxmap,*idxout,Nmax = mapping->n;
3835d0c19d7SBarry Smith   const PetscInt *idxin;
3843a40ed3dSBarry Smith 
3853a40ed3dSBarry Smith   PetscFunctionBegin;
3860700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3870700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3884482741eSBarry Smith   PetscValidPointer(newis,3);
38990f02eecSBarry Smith 
3903b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
39190f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
39290f02eecSBarry Smith   idxmap = mapping->indices;
39390f02eecSBarry Smith 
3947c334f02SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&idxout);CHKERRQ(ierr);
39590f02eecSBarry Smith   for (i=0; i<n; i++) {
396e32f2f54SBarry 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);
39790f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
39890f02eecSBarry Smith   }
3993b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
40070b3c8c7SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4013a40ed3dSBarry Smith   PetscFunctionReturn(0);
40290f02eecSBarry Smith }
40390f02eecSBarry Smith 
404afcb2eb5SJed Brown #undef __FUNCT__
405afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
406afcb2eb5SJed Brown /*@C
4073acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4083acfe500SLois Curfman McInnes    and converts them to the global numbering.
40990f02eecSBarry Smith 
410b9cd556bSLois Curfman McInnes    Not collective
411b9cd556bSLois Curfman McInnes 
412bb25748dSBarry Smith    Input Parameters:
413b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
414bb25748dSBarry Smith .  N - number of integers
415b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
416bb25748dSBarry Smith 
417bb25748dSBarry Smith    Output Parameter:
418bb25748dSBarry Smith .  out - indices in global numbering
419bb25748dSBarry Smith 
420b9cd556bSLois Curfman McInnes    Notes:
421b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
422d4bb536fSBarry Smith 
423a997ad1aSLois Curfman McInnes    Level: advanced
424a997ad1aSLois Curfman McInnes 
425bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4260752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
427d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
428bb25748dSBarry Smith 
429273d9f13SBarry Smith     Concepts: mapping^local to global
430afcb2eb5SJed Brown @*/
431afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
432afcb2eb5SJed Brown {
433afcb2eb5SJed Brown   PetscInt       i,Nmax = mapping->n;
434afcb2eb5SJed Brown   const PetscInt *idx = mapping->indices;
435d4bb536fSBarry Smith 
436afcb2eb5SJed Brown   PetscFunctionBegin;
437afcb2eb5SJed Brown   for (i=0; i<N; i++) {
438afcb2eb5SJed Brown     if (in[i] < 0) {
439afcb2eb5SJed Brown       out[i] = in[i];
440afcb2eb5SJed Brown       continue;
441afcb2eb5SJed Brown     }
442afcb2eb5SJed 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);
443afcb2eb5SJed Brown     out[i] = idx[in[i]];
444afcb2eb5SJed Brown   }
445afcb2eb5SJed Brown   PetscFunctionReturn(0);
446afcb2eb5SJed Brown }
447d4bb536fSBarry Smith 
448d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
449d4bb536fSBarry Smith 
4504a2ae208SSatish Balay #undef __FUNCT__
4514a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
452d4bb536fSBarry Smith /*
453d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
454d4bb536fSBarry Smith */
4556849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
456d4bb536fSBarry Smith {
4576849ba73SBarry Smith   PetscErrorCode ierr;
45832dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
459d4bb536fSBarry Smith 
4603a40ed3dSBarry Smith   PetscFunctionBegin;
461d4bb536fSBarry Smith   end   = 0;
462ec268f7cSJed Brown   start = PETSC_MAX_INT;
463d4bb536fSBarry Smith 
464d4bb536fSBarry Smith   for (i=0; i<n; i++) {
465d4bb536fSBarry Smith     if (idx[i] < 0) continue;
466d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
467d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
468d4bb536fSBarry Smith   }
469d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
470d4bb536fSBarry Smith   mapping->globalstart = start;
471d4bb536fSBarry Smith   mapping->globalend   = end;
472d4bb536fSBarry Smith 
47332dcc486SBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(PetscInt),&globals);CHKERRQ(ierr);
474b0a32e0cSBarry Smith   mapping->globals = globals;
475f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
476d4bb536fSBarry Smith   for (i=0; i<n; i++) {
477d4bb536fSBarry Smith     if (idx[i] < 0) continue;
478d4bb536fSBarry Smith     globals[idx[i] - start] = i;
479d4bb536fSBarry Smith   }
480d4bb536fSBarry Smith 
48152e6d16bSBarry Smith   ierr = PetscLogObjectMemory(mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
4823a40ed3dSBarry Smith   PetscFunctionReturn(0);
483d4bb536fSBarry Smith }
484d4bb536fSBarry Smith 
4854a2ae208SSatish Balay #undef __FUNCT__
4864a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
487d4bb536fSBarry Smith /*@
488a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
489a997ad1aSLois Curfman McInnes     specified with a global numbering.
490d4bb536fSBarry Smith 
491b9cd556bSLois Curfman McInnes     Not collective
492b9cd556bSLois Curfman McInnes 
493d4bb536fSBarry Smith     Input Parameters:
494b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
495d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
496d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
497d4bb536fSBarry Smith .   n - number of global indices to map
498b9cd556bSLois Curfman McInnes -   idx - global indices to map
499d4bb536fSBarry Smith 
500d4bb536fSBarry Smith     Output Parameters:
501b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
502b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
503e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5040298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
505e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
506e182c471SBarry Smith              a second time to set the values.
507d4bb536fSBarry Smith 
508b9cd556bSLois Curfman McInnes     Notes:
5090298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
510d4bb536fSBarry Smith 
5110f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5120f5bd95cSBarry Smith     array to compute these.
5130f5bd95cSBarry Smith 
514a997ad1aSLois Curfman McInnes     Level: advanced
515a997ad1aSLois Curfman McInnes 
51632fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
51732fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
51832fd6b96SBarry Smith 
519273d9f13SBarry Smith     Concepts: mapping^global to local
520d4bb536fSBarry Smith 
521d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
522d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
523d4bb536fSBarry Smith @*/
5247087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
52532dcc486SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
526d4bb536fSBarry Smith {
52732dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
5286849ba73SBarry Smith   PetscErrorCode ierr;
529d4bb536fSBarry Smith 
5303a40ed3dSBarry Smith   PetscFunctionBegin;
5310700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
532d4bb536fSBarry Smith   if (!mapping->globals) {
533d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
534d4bb536fSBarry Smith   }
535d4bb536fSBarry Smith   globals = mapping->globals;
536d4bb536fSBarry Smith   start   = mapping->globalstart;
537d4bb536fSBarry Smith   end     = mapping->globalend;
538d4bb536fSBarry Smith 
539d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
540d4bb536fSBarry Smith     if (idxout) {
541d4bb536fSBarry Smith       for (i=0; i<n; i++) {
542d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
543d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
544d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
545d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
546d4bb536fSBarry Smith       }
547d4bb536fSBarry Smith     }
548d4bb536fSBarry Smith     if (nout) *nout = n;
549d4bb536fSBarry Smith   } else {
550d4bb536fSBarry Smith     if (idxout) {
551d4bb536fSBarry Smith       for (i=0; i<n; i++) {
552d4bb536fSBarry Smith         if (idx[i] < 0) continue;
553d4bb536fSBarry Smith         if (idx[i] < start) continue;
554d4bb536fSBarry Smith         if (idx[i] > end) continue;
555d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
556d4bb536fSBarry Smith         if (tmp < 0) continue;
557d4bb536fSBarry Smith         idxout[nf++] = tmp;
558d4bb536fSBarry Smith       }
559d4bb536fSBarry Smith     } else {
560d4bb536fSBarry Smith       for (i=0; i<n; i++) {
561d4bb536fSBarry Smith         if (idx[i] < 0) continue;
562d4bb536fSBarry Smith         if (idx[i] < start) continue;
563d4bb536fSBarry Smith         if (idx[i] > end) continue;
564d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
565d4bb536fSBarry Smith         if (tmp < 0) continue;
566d4bb536fSBarry Smith         nf++;
567d4bb536fSBarry Smith       }
568d4bb536fSBarry Smith     }
569d4bb536fSBarry Smith     if (nout) *nout = nf;
570d4bb536fSBarry Smith   }
5713a40ed3dSBarry Smith   PetscFunctionReturn(0);
572d4bb536fSBarry Smith }
57390f02eecSBarry Smith 
5744a2ae208SSatish Balay #undef __FUNCT__
5754a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
57689d82c54SBarry Smith /*@C
57789d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
57889d82c54SBarry Smith      each index shared by more than one processor
57989d82c54SBarry Smith 
58089d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
58189d82c54SBarry Smith 
58289d82c54SBarry Smith     Input Parameters:
58389d82c54SBarry Smith .   mapping - the mapping from local to global indexing
58489d82c54SBarry Smith 
58589d82c54SBarry Smith     Output Parameter:
58689d82c54SBarry Smith +   nproc - number of processors that are connected to this one
58789d82c54SBarry Smith .   proc - neighboring processors
58807b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
5893463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
59089d82c54SBarry Smith 
59189d82c54SBarry Smith     Level: advanced
59289d82c54SBarry Smith 
593273d9f13SBarry Smith     Concepts: mapping^local to global
59489d82c54SBarry Smith 
5952cfcea29SBarry Smith     Fortran Usage:
5962cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
5972cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
5982cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
5992cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
6002cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
6012cfcea29SBarry Smith 
6022cfcea29SBarry Smith 
60307b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
60407b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
60589d82c54SBarry Smith @*/
6067087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
60789d82c54SBarry Smith {
6086849ba73SBarry Smith   PetscErrorCode ierr;
60997f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
61032dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
61132dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
61297f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
61332dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
61432dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
61589d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
61630dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
617ce94432eSBarry Smith   MPI_Comm       comm;
618ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
61989d82c54SBarry Smith 
62089d82c54SBarry Smith   PetscFunctionBegin;
6210700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
622ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
62324cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
62424cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
62524cf384cSBarry Smith   if (size == 1) {
62624cf384cSBarry Smith     *nproc         = 0;
6270298fd71SBarry Smith     *procs         = NULL;
62832dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
6291e2105dcSBarry Smith     (*numprocs)[0] = 0;
63032dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
6310298fd71SBarry Smith     (*indices)[0]  = NULL;
63224cf384cSBarry Smith     PetscFunctionReturn(0);
63324cf384cSBarry Smith   }
63424cf384cSBarry Smith 
6350298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
63607b52d57SBarry Smith 
6373677ff5aSBarry Smith   /*
6383677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
6393677ff5aSBarry Smith 
6403677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
6413677ff5aSBarry Smith            numbering, just for this routine.
6423677ff5aSBarry Smith 
6433677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
6443677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
6453677ff5aSBarry Smith 
6463677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
6473677ff5aSBarry Smith 
6483677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
6493677ff5aSBarry Smith            local subdomain
6503677ff5aSBarry Smith   */
65124cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
65224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
65324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
65489d82c54SBarry Smith 
65589d82c54SBarry Smith   for (i=0; i<n; i++) {
65689d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
65789d82c54SBarry Smith   }
65832dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
65978058e43SBarry Smith   Ng++;
66089d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
66189d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
662bc8ff85bSBarry Smith   scale  = Ng/size + 1;
663a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
664caba0dd0SBarry Smith   rstart = scale*rank;
66589d82c54SBarry Smith 
66689d82c54SBarry Smith   /* determine ownership ranges of global indices */
6677c334f02SBarry Smith   ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
66832dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
66989d82c54SBarry Smith 
67089d82c54SBarry Smith   /* determine owners of each local node  */
6717c334f02SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&owner);CHKERRQ(ierr);
67289d82c54SBarry Smith   for (i=0; i<n; i++) {
6733677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
67427c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
6753677ff5aSBarry Smith     owner[i]         = proc;
67627c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
67789d82c54SBarry Smith   }
67827c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
6791e2582c4SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %d\n",nsends);CHKERRQ(ierr);
68089d82c54SBarry Smith 
68189d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
68227c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
6831e2582c4SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %d\n",nrecvs);CHKERRQ(ierr);
68489d82c54SBarry Smith 
68589d82c54SBarry Smith   /* post receives for owned rows */
68632dcc486SBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(PetscInt),&recvs);CHKERRQ(ierr);
687b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
68889d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
68932dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
69089d82c54SBarry Smith   }
69189d82c54SBarry Smith 
69289d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
69332dcc486SBarry Smith   ierr      = PetscMalloc((2*n+1)*sizeof(PetscInt),&sends);CHKERRQ(ierr);
69432dcc486SBarry Smith   ierr      = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
69589d82c54SBarry Smith   starts[0] = 0;
696f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
69789d82c54SBarry Smith   for (i=0; i<n; i++) {
69889d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
69930dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
70089d82c54SBarry Smith   }
70189d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
70289d82c54SBarry Smith   starts[0] = 0;
703f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
70489d82c54SBarry Smith 
70589d82c54SBarry Smith   /* send the messages */
706b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
70732dcc486SBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(PetscInt),&dest);CHKERRQ(ierr);
70889d82c54SBarry Smith   cnt = 0;
70989d82c54SBarry Smith   for (i=0; i<size; i++) {
71027c402fcSBarry Smith     if (nprocs[2*i]) {
71132dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
71230dcb7c9SBarry Smith       dest[cnt] = i;
71389d82c54SBarry Smith       cnt++;
71489d82c54SBarry Smith     }
71589d82c54SBarry Smith   }
71689d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
71789d82c54SBarry Smith 
71889d82c54SBarry Smith   /* wait on receives */
71997f1f81fSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(PetscMPIInt),&source);CHKERRQ(ierr);
72097f1f81fSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(PetscMPIInt),&len);CHKERRQ(ierr);
72189d82c54SBarry Smith   cnt  = nrecvs;
72232dcc486SBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(PetscInt),&nownedsenders);CHKERRQ(ierr);
72332dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
72489d82c54SBarry Smith   while (cnt) {
72589d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
72689d82c54SBarry Smith     /* unpack receives into our local space */
72732dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
72889d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
72930dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
730caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
73130dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
73289d82c54SBarry Smith     cnt--;
73389d82c54SBarry Smith   }
73489d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
73589d82c54SBarry Smith 
73630dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
737bc8ff85bSBarry Smith   nowned  = 0;
738bc8ff85bSBarry Smith   nownedm = 0;
739bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
740bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
741bc8ff85bSBarry Smith   }
742bc8ff85bSBarry Smith 
743bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
74432dcc486SBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(PetscInt),&ownedsenders);CHKERRQ(ierr);
74532dcc486SBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
746bc8ff85bSBarry Smith   starts[0] = 0;
747bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
748bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
749bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
750bc8ff85bSBarry Smith   }
751bc8ff85bSBarry Smith 
75230dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
753bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
754bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
75530dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
756f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
757bc8ff85bSBarry Smith     }
758bc8ff85bSBarry Smith   }
759bc8ff85bSBarry Smith 
76007b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
76130dcb7c9SBarry Smith     starts[0] = 0;
76230dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
76330dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
76430dcb7c9SBarry Smith       else starts[i] = starts[i-1];
76530dcb7c9SBarry Smith     }
76630dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
76730dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
76830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
76930dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
77030dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
77130dcb7c9SBarry Smith         }
77230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
77330dcb7c9SBarry Smith       }
77430dcb7c9SBarry Smith     }
77530dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
77607b52d57SBarry Smith   } /* -----------------------------------  */
77730dcb7c9SBarry Smith 
7783677ff5aSBarry Smith   /* wait on original sends */
7793a96401aSBarry Smith   if (nsends) {
780b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
7813a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
7823a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
7833a96401aSBarry Smith   }
78489d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
7853a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
7863677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
7873677ff5aSBarry Smith 
7883677ff5aSBarry Smith   /* pack messages to send back to local owners */
78930dcb7c9SBarry Smith   starts[0] = 0;
79030dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
79130dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
79230dcb7c9SBarry Smith     else starts[i] = starts[i-1];
79330dcb7c9SBarry Smith   }
79430dcb7c9SBarry Smith   nsends2 = nrecvs;
79532dcc486SBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(PetscInt),&nprocs);CHKERRQ(ierr); /* length of each message */
79630dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
79730dcb7c9SBarry Smith     nprocs[i] = 1;
79830dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
79930dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
800f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
80130dcb7c9SBarry Smith     }
80230dcb7c9SBarry Smith   }
803f6e5521dSKarl Rupp   nt = 0;
804f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
805f6e5521dSKarl Rupp 
80632dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&sends2);CHKERRQ(ierr);
80732dcc486SBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(PetscInt),&starts2);CHKERRQ(ierr);
808f6e5521dSKarl Rupp 
809f6e5521dSKarl Rupp   starts2[0] = 0;
810f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
81130dcb7c9SBarry Smith   /*
81230dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
81330dcb7c9SBarry Smith        (0) the number of nodes being sent back
81430dcb7c9SBarry Smith        (1) the local node number,
81530dcb7c9SBarry Smith        (2) the number of processors sharing it,
81630dcb7c9SBarry Smith        (3) the processors sharing it
81730dcb7c9SBarry Smith   */
81830dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
81930dcb7c9SBarry Smith     cnt = 1;
82030dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
82130dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
82230dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
82330dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
82430dcb7c9SBarry Smith         sends2[starts2[i]]++;
82530dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
82630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
82732dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
82830dcb7c9SBarry Smith         cnt += nownedsenders[node];
82930dcb7c9SBarry Smith       }
83030dcb7c9SBarry Smith     }
83130dcb7c9SBarry Smith   }
83230dcb7c9SBarry Smith 
83330dcb7c9SBarry Smith   /* receive the message lengths */
83430dcb7c9SBarry Smith   nrecvs2 = nsends;
83532dcc486SBarry Smith   ierr    = PetscMalloc((nrecvs2+1)*sizeof(PetscInt),&lens2);CHKERRQ(ierr);
83632dcc486SBarry Smith   ierr    = PetscMalloc((nrecvs2+1)*sizeof(PetscInt),&starts3);CHKERRQ(ierr);
837d44834fbSBarry Smith   ierr    = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
83830dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
839d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
84030dcb7c9SBarry Smith   }
841d44834fbSBarry Smith 
8428a8e0b3aSBarry Smith   /* send the message lengths */
8438a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
8448a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
8458a8e0b3aSBarry Smith   }
8468a8e0b3aSBarry Smith 
847d44834fbSBarry Smith   /* wait on receives of lens */
8480c468ba9SBarry Smith   if (nrecvs2) {
8490c468ba9SBarry Smith     ierr = PetscMalloc(nrecvs2*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
850d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
851d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
8520c468ba9SBarry Smith   }
853a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
854d44834fbSBarry Smith 
85530dcb7c9SBarry Smith   starts3[0] = 0;
856d44834fbSBarry Smith   nt         = 0;
85730dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
85830dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
859d44834fbSBarry Smith     nt          += lens2[i];
86030dcb7c9SBarry Smith   }
86176466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
862d44834fbSBarry Smith 
86332dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&recvs2);CHKERRQ(ierr);
864b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
86552b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
86632dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
86730dcb7c9SBarry Smith   }
86830dcb7c9SBarry Smith 
86930dcb7c9SBarry Smith   /* send the messages */
870b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
87130dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
87232dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
87330dcb7c9SBarry Smith   }
87430dcb7c9SBarry Smith 
87530dcb7c9SBarry Smith   /* wait on receives */
8760c468ba9SBarry Smith   if (nrecvs2) {
8770c468ba9SBarry Smith     ierr = PetscMalloc(nrecvs2*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
87830dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
87930dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
8800c468ba9SBarry Smith   }
88130dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
88230dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
88330dcb7c9SBarry Smith 
88407b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
88530dcb7c9SBarry Smith     cnt = 0;
88630dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
88730dcb7c9SBarry Smith       nt = recvs2[cnt++];
88830dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
88930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
89030dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
89130dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
89230dcb7c9SBarry Smith         }
89330dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
89430dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
89530dcb7c9SBarry Smith       }
89630dcb7c9SBarry Smith     }
89730dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
89807b52d57SBarry Smith   } /* -----------------------------------  */
89930dcb7c9SBarry Smith 
90030dcb7c9SBarry Smith   /* count number subdomains for each local node */
90132dcc486SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
90232dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
90330dcb7c9SBarry Smith   cnt  = 0;
90430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
90530dcb7c9SBarry Smith     nt = recvs2[cnt++];
90630dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
907f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
90830dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
90930dcb7c9SBarry Smith     }
91030dcb7c9SBarry Smith   }
91130dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
91230dcb7c9SBarry Smith   *nproc    = nt;
91332dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),procs);CHKERRQ(ierr);
91432dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),numprocs);CHKERRQ(ierr);
91532dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt*),indices);CHKERRQ(ierr);
9160298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
91732dcc486SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscInt),&bprocs);CHKERRQ(ierr);
91830dcb7c9SBarry Smith   cnt       = 0;
91930dcb7c9SBarry Smith   for (i=0; i<size; i++) {
92030dcb7c9SBarry Smith     if (nprocs[i] > 0) {
92130dcb7c9SBarry Smith       bprocs[i]        = cnt;
92230dcb7c9SBarry Smith       (*procs)[cnt]    = i;
92330dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
92432dcc486SBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(PetscInt),&(*indices)[cnt]);CHKERRQ(ierr);
92530dcb7c9SBarry Smith       cnt++;
92630dcb7c9SBarry Smith     }
92730dcb7c9SBarry Smith   }
92830dcb7c9SBarry Smith 
92930dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
93032dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
93130dcb7c9SBarry Smith   cnt  = 0;
93230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
93330dcb7c9SBarry Smith     nt = recvs2[cnt++];
93430dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
935f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
93630dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
93730dcb7c9SBarry Smith     }
93830dcb7c9SBarry Smith   }
93930dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
94007b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
94130dcb7c9SBarry Smith 
94207b52d57SBarry Smith   /* sort the node indexing by their global numbers */
94307b52d57SBarry Smith   nt = *nproc;
94407b52d57SBarry Smith   for (i=0; i<nt; i++) {
94532dcc486SBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(PetscInt),&tmp);CHKERRQ(ierr);
946f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
94707b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
94807b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
94907b52d57SBarry Smith   }
95007b52d57SBarry Smith 
95107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
95230dcb7c9SBarry Smith     nt = *nproc;
95330dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
95430dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
95530dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
95630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
95730dcb7c9SBarry Smith       }
95830dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
95930dcb7c9SBarry Smith     }
96030dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
96107b52d57SBarry Smith   } /* -----------------------------------  */
96230dcb7c9SBarry Smith 
96330dcb7c9SBarry Smith   /* wait on sends */
96430dcb7c9SBarry Smith   if (nsends2) {
965b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
96630dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
96730dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
96830dcb7c9SBarry Smith   }
96930dcb7c9SBarry Smith 
97030dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
97130dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
97230dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
9733677ff5aSBarry Smith 
974bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
975bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
976bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
97730dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
97830dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
97989d82c54SBarry Smith 
98089d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
98197f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
98289d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
9833a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
98430dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
98524cf384cSBarry Smith 
98624cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
98724cf384cSBarry Smith   first_procs    = (*procs)[0];
98824cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
98924cf384cSBarry Smith   first_indices  = (*indices)[0];
99024cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
99124cf384cSBarry Smith     if ((*procs)[i] == rank) {
99224cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
99324cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
99424cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
99524cf384cSBarry Smith       (*procs)[i]    = first_procs;
99624cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
99724cf384cSBarry Smith       (*indices)[i]  = first_indices;
99824cf384cSBarry Smith       break;
99924cf384cSBarry Smith     }
100024cf384cSBarry Smith   }
100189d82c54SBarry Smith   PetscFunctionReturn(0);
100289d82c54SBarry Smith }
100389d82c54SBarry Smith 
10044a2ae208SSatish Balay #undef __FUNCT__
10054a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
100607b52d57SBarry Smith /*@C
100707b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
100889d82c54SBarry Smith 
100907b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
101007b52d57SBarry Smith 
101107b52d57SBarry Smith     Input Parameters:
101207b52d57SBarry Smith .   mapping - the mapping from local to global indexing
101307b52d57SBarry Smith 
101407b52d57SBarry Smith     Output Parameter:
101507b52d57SBarry Smith +   nproc - number of processors that are connected to this one
101607b52d57SBarry Smith .   proc - neighboring processors
101707b52d57SBarry Smith .   numproc - number of indices for each processor
101807b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
101907b52d57SBarry Smith 
102007b52d57SBarry Smith     Level: advanced
102107b52d57SBarry Smith 
102207b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
102307b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
102407b52d57SBarry Smith @*/
10257087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
102607b52d57SBarry Smith {
10276849ba73SBarry Smith   PetscErrorCode ierr;
102832dcc486SBarry Smith   PetscInt       i;
102907b52d57SBarry Smith 
103007b52d57SBarry Smith   PetscFunctionBegin;
103105b42c5fSBarry Smith   ierr = PetscFree(*procs);CHKERRQ(ierr);
103205b42c5fSBarry Smith   ierr = PetscFree(*numprocs);CHKERRQ(ierr);
103300ff320aSBarry Smith   if (*indices) {
103405b42c5fSBarry Smith     ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
103500ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
103605b42c5fSBarry Smith       ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
103707b52d57SBarry Smith     }
103807b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
103924cf384cSBarry Smith   }
104007b52d57SBarry Smith   PetscFunctionReturn(0);
104107b52d57SBarry Smith }
104286994e45SJed Brown 
104386994e45SJed Brown #undef __FUNCT__
104486994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
104586994e45SJed Brown /*@C
104686994e45SJed Brown    ISLocalToGlobalMappingGetIndices - Get global indices for every local point
104786994e45SJed Brown 
104886994e45SJed Brown    Not Collective
104986994e45SJed Brown 
105086994e45SJed Brown    Input Arguments:
105186994e45SJed Brown . ltog - local to global mapping
105286994e45SJed Brown 
105386994e45SJed Brown    Output Arguments:
105486994e45SJed Brown . array - array of indices
105586994e45SJed Brown 
105686994e45SJed Brown    Level: advanced
105786994e45SJed Brown 
105886994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices()
105986994e45SJed Brown @*/
10607087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
106186994e45SJed Brown {
106286994e45SJed Brown   PetscFunctionBegin;
106386994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
106486994e45SJed Brown   PetscValidPointer(array,2);
106586994e45SJed Brown   *array = ltog->indices;
106686994e45SJed Brown   PetscFunctionReturn(0);
106786994e45SJed Brown }
106886994e45SJed Brown 
106986994e45SJed Brown #undef __FUNCT__
107086994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
107186994e45SJed Brown /*@C
107286994e45SJed Brown    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingRestoreIndices()
107386994e45SJed Brown 
107486994e45SJed Brown    Not Collective
107586994e45SJed Brown 
107686994e45SJed Brown    Input Arguments:
107786994e45SJed Brown + ltog - local to global mapping
107886994e45SJed Brown - array - array of indices
107986994e45SJed Brown 
108086994e45SJed Brown    Level: advanced
108186994e45SJed Brown 
108286994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
108386994e45SJed Brown @*/
10847087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
108586994e45SJed Brown {
108686994e45SJed Brown   PetscFunctionBegin;
108786994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
108886994e45SJed Brown   PetscValidPointer(array,2);
108986994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
10900298fd71SBarry Smith   *array = NULL;
109186994e45SJed Brown   PetscFunctionReturn(0);
109286994e45SJed Brown }
1093f7efa3c7SJed Brown 
1094f7efa3c7SJed Brown #undef __FUNCT__
1095f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1096f7efa3c7SJed Brown /*@C
1097f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1098f7efa3c7SJed Brown 
1099f7efa3c7SJed Brown    Not Collective
1100f7efa3c7SJed Brown 
1101f7efa3c7SJed Brown    Input Arguments:
1102f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1103f7efa3c7SJed Brown . n - number of mappings to concatenate
1104f7efa3c7SJed Brown - ltogs - local to global mappings
1105f7efa3c7SJed Brown 
1106f7efa3c7SJed Brown    Output Arguments:
1107f7efa3c7SJed Brown . ltogcat - new mapping
1108f7efa3c7SJed Brown 
1109f7efa3c7SJed Brown    Level: advanced
1110f7efa3c7SJed Brown 
1111f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1112f7efa3c7SJed Brown @*/
1113f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1114f7efa3c7SJed Brown {
1115f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1116f7efa3c7SJed Brown   PetscErrorCode ierr;
1117f7efa3c7SJed Brown 
1118f7efa3c7SJed Brown   PetscFunctionBegin;
1119f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1120f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1121f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1122f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1123f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1124f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1125f7efa3c7SJed Brown     cnt += m;
1126f7efa3c7SJed Brown   }
1127f7efa3c7SJed Brown   ierr = PetscMalloc(cnt*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1128f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1129f7efa3c7SJed Brown     const PetscInt *subidx;
1130f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1131f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1132f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1133f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1134f7efa3c7SJed Brown     cnt += m;
1135f7efa3c7SJed Brown   }
1136f7efa3c7SJed Brown   ierr = ISLocalToGlobalMappingCreate(comm,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1137f7efa3c7SJed Brown   PetscFunctionReturn(0);
1138f7efa3c7SJed Brown }
1139