xref: /petsc/src/vec/is/utils/isltog.c (revision 98c3331e5c81c4bfa5036a9b6bc521ec2d439166)
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 
804a59952SBarry 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) {
94*98c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
957b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
965a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
977904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
986831982aSBarry Smith     }
99b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1007b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
1017b23a99aSBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
1025a5d4f66SBarry Smith   PetscFunctionReturn(0);
1035a5d4f66SBarry Smith }
1045a5d4f66SBarry Smith 
1054a2ae208SSatish Balay #undef __FUNCT__
1064a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1071f428162SBarry Smith /*@
1082bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1092bdab257SBarry Smith     ordering and a global parallel ordering.
1102bdab257SBarry Smith 
1110f5bd95cSBarry Smith     Not collective
112b9cd556bSLois Curfman McInnes 
113a997ad1aSLois Curfman McInnes     Input Parameter:
1148c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1152bdab257SBarry Smith 
116a997ad1aSLois Curfman McInnes     Output Parameter:
1172bdab257SBarry Smith .   mapping - new mapping data structure
1182bdab257SBarry Smith 
119a997ad1aSLois Curfman McInnes     Level: advanced
120a997ad1aSLois Curfman McInnes 
121273d9f13SBarry Smith     Concepts: mapping^local to global
1222bdab257SBarry Smith 
1232bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1242bdab257SBarry Smith @*/
1257087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1262bdab257SBarry Smith {
1276849ba73SBarry Smith   PetscErrorCode ierr;
1283bbf0e92SBarry Smith   PetscInt       n,bs;
1295d0c19d7SBarry Smith   const PetscInt *indices;
1302bdab257SBarry Smith   MPI_Comm       comm;
1313bbf0e92SBarry Smith   PetscBool      isblock;
1323a40ed3dSBarry Smith 
1333a40ed3dSBarry Smith   PetscFunctionBegin;
1340700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1354482741eSBarry Smith   PetscValidPointer(mapping,2);
1362bdab257SBarry Smith 
1372bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1383b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1392bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1403bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1413bbf0e92SBarry Smith   ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
1423bbf0e92SBarry Smith   if (!isblock || bs == 1) {
143d5ad8652SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1442bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1453bbf0e92SBarry Smith   } else {
1463bbf0e92SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,n,indices,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
1473bbf0e92SBarry Smith   }
1483a40ed3dSBarry Smith   PetscFunctionReturn(0);
1492bdab257SBarry Smith }
1505a5d4f66SBarry Smith 
151a4d96a55SJed Brown #undef __FUNCT__
152a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
153a4d96a55SJed Brown /*@C
154a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
155a4d96a55SJed Brown     ordering and a global parallel ordering.
156a4d96a55SJed Brown 
157a4d96a55SJed Brown     Collective
158a4d96a55SJed Brown 
159a4d96a55SJed Brown     Input Parameter:
160a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
161a4d96a55SJed Brown -   start - first global index on this process
162a4d96a55SJed Brown 
163a4d96a55SJed Brown     Output Parameter:
164a4d96a55SJed Brown .   mapping - new mapping data structure
165a4d96a55SJed Brown 
166a4d96a55SJed Brown     Level: advanced
167a4d96a55SJed Brown 
168a4d96a55SJed Brown     Concepts: mapping^local to global
169a4d96a55SJed Brown 
170a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
171a4d96a55SJed Brown @*/
172a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
173a4d96a55SJed Brown {
174a4d96a55SJed Brown   PetscErrorCode ierr;
175a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
176a4d96a55SJed Brown   const PetscInt *ilocal;
177a4d96a55SJed Brown   MPI_Comm       comm;
178a4d96a55SJed Brown 
179a4d96a55SJed Brown   PetscFunctionBegin;
180a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
181a4d96a55SJed Brown   PetscValidPointer(mapping,3);
182a4d96a55SJed Brown 
183a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1840298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
185f6e5521dSKarl Rupp   if (ilocal) {
186f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
187f6e5521dSKarl Rupp   }
188a4d96a55SJed Brown   else maxlocal = nleaves;
189785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
190785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
191a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
192a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
193a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
194a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
195a4d96a55SJed Brown   ierr = ISLocalToGlobalMappingCreate(comm,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
196a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
197a4d96a55SJed Brown   PetscFunctionReturn(0);
198a4d96a55SJed Brown }
199b46b645bSBarry Smith 
2004a2ae208SSatish Balay #undef __FUNCT__
2014a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
202ba5bb76aSSatish Balay /*@
20390f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
20490f02eecSBarry Smith     ordering and a global parallel ordering.
2052362add9SBarry Smith 
20689d82c54SBarry Smith     Not Collective, but communicator may have more than one process
207b9cd556bSLois Curfman McInnes 
2082362add9SBarry Smith     Input Parameters:
20989d82c54SBarry Smith +   comm - MPI communicator
21090f02eecSBarry Smith .   n - the number of local elements
2119669e4d8SBarry Smith .   indices - the global index for each local element, these do not need to be in increasing order (sorted)
212d5ad8652SBarry Smith -   mode - see PetscCopyMode
2132362add9SBarry Smith 
214a997ad1aSLois Curfman McInnes     Output Parameter:
21590f02eecSBarry Smith .   mapping - new mapping data structure
2162362add9SBarry Smith 
217a997ad1aSLois Curfman McInnes     Level: advanced
218a997ad1aSLois Curfman McInnes 
219273d9f13SBarry Smith     Concepts: mapping^local to global
2202362add9SBarry Smith 
221d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2222362add9SBarry Smith @*/
2237087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2242362add9SBarry Smith {
2256849ba73SBarry Smith   PetscErrorCode ierr;
22632dcc486SBarry Smith   PetscInt       *in;
227b46b645bSBarry Smith 
228b46b645bSBarry Smith   PetscFunctionBegin;
22973911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2304482741eSBarry Smith   PetscValidPointer(mapping,4);
231b46b645bSBarry Smith 
2320298fd71SBarry Smith   *mapping = NULL;
233607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2342362add9SBarry Smith 
23567c2884eSBarry Smith   ierr = PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
23652e6d16bSBarry Smith                            cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
237d4bb536fSBarry Smith   (*mapping)->n = n;
238d4bb536fSBarry Smith   /*
239d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
240d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
241d4bb536fSBarry Smith   */
242d4bb536fSBarry Smith   (*mapping)->globals = 0;
243d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
244785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
245d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
2463bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
247d5ad8652SBarry Smith     (*mapping)->indices = in;
248f6e5521dSKarl Rupp   } else if (mode == PETSC_OWN_POINTER) (*mapping)->indices = (PetscInt*)indices;
249f6e5521dSKarl Rupp   else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
2503a40ed3dSBarry Smith   PetscFunctionReturn(0);
2512362add9SBarry Smith }
2522362add9SBarry Smith 
2534a2ae208SSatish Balay #undef __FUNCT__
2544a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
255bce096a4SSatish Balay /*@
256323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
257323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
258323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
259323b833fSBarry Smith 
260323b833fSBarry Smith     Not Collective, but communicator may have more than one process
261323b833fSBarry Smith 
262323b833fSBarry Smith     Input Parameters:
263323b833fSBarry Smith +    inmap - original point-wise mapping
264323b833fSBarry Smith -    bs - block size
265323b833fSBarry Smith 
266323b833fSBarry Smith     Output Parameter:
26769eb54c3SBarry Smith .   outmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
268323b833fSBarry Smith 
269323b833fSBarry Smith     Level: advanced
270323b833fSBarry Smith 
271323b833fSBarry Smith     Concepts: mapping^local to global
272323b833fSBarry Smith 
273323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
274323b833fSBarry Smith @*/
2757087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
276323b833fSBarry Smith {
2776849ba73SBarry Smith   PetscErrorCode ierr;
27832dcc486SBarry Smith   PetscInt       *ii,i,n;
279323b833fSBarry Smith 
280323b833fSBarry Smith   PetscFunctionBegin;
2810700a824SBarry Smith   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
282b2beed0aSJed Brown   PetscValidPointer(outmap,3);
283323b833fSBarry Smith   if (bs > 1) {
284323b833fSBarry Smith     n = inmap->n/bs;
285e32f2f54SBarry Smith     if (n*bs != inmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Pointwise mapping length is not divisible by block size");
286785e854fSJed Brown     ierr = PetscMalloc1(n,&ii);CHKERRQ(ierr);
287f6e5521dSKarl Rupp     for (i=0; i<n; i++) ii[i] = inmap->indices[bs*i]/bs;
288ce94432eSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)inmap),n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
289323b833fSBarry Smith   } else {
290323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
291c3122656SLisandro Dalcin     *outmap = inmap;
292323b833fSBarry Smith   }
293323b833fSBarry Smith   PetscFunctionReturn(0);
294323b833fSBarry Smith }
295323b833fSBarry Smith 
2964a2ae208SSatish Balay #undef __FUNCT__
2978ab951edSJed Brown #define __FUNCT__ "ISLocalToGlobalMappingUnBlock"
298b2beed0aSJed Brown /*@
299b2beed0aSJed Brown     ISLocalToGlobalMappingUnBlock - Creates a scalar index version of a blocked
300b2beed0aSJed Brown        ISLocalToGlobalMapping
301b2beed0aSJed Brown 
302b2beed0aSJed Brown     Not Collective, but communicator may have more than one process
303b2beed0aSJed Brown 
304b2beed0aSJed Brown     Input Parameter:
305b2beed0aSJed Brown + inmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
306b2beed0aSJed Brown - bs - block size
307b2beed0aSJed Brown 
308b2beed0aSJed Brown     Output Parameter:
309b2beed0aSJed Brown .   outmap - pointwise mapping
310b2beed0aSJed Brown 
311b2beed0aSJed Brown     Level: advanced
312b2beed0aSJed Brown 
313b2beed0aSJed Brown     Concepts: mapping^local to global
314b2beed0aSJed Brown 
315b2beed0aSJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingBlock()
316b2beed0aSJed Brown @*/
3177087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingUnBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
318b2beed0aSJed Brown {
319b2beed0aSJed Brown   PetscErrorCode ierr;
320b2beed0aSJed Brown   PetscInt       *ii,i,n;
321b2beed0aSJed Brown 
322b2beed0aSJed Brown   PetscFunctionBegin;
323b2beed0aSJed Brown   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
324b2beed0aSJed Brown   PetscValidPointer(outmap,2);
325b2beed0aSJed Brown   if (bs > 1) {
326b2beed0aSJed Brown     n    = inmap->n*bs;
327785e854fSJed Brown     ierr = PetscMalloc1(n,&ii);CHKERRQ(ierr);
328f6e5521dSKarl Rupp     for (i=0; i<n; i++) ii[i] = inmap->indices[i/bs]*bs + (i%bs);
329ce94432eSBarry Smith     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)inmap),n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
330b2beed0aSJed Brown   } else {
331b2beed0aSJed Brown     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
332b2beed0aSJed Brown     *outmap = inmap;
333b2beed0aSJed Brown   }
334b2beed0aSJed Brown   PetscFunctionReturn(0);
335b2beed0aSJed Brown }
336b2beed0aSJed Brown 
337b2beed0aSJed Brown #undef __FUNCT__
3384a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
33990f02eecSBarry Smith /*@
34090f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
34190f02eecSBarry Smith    ordering and a global parallel ordering.
34290f02eecSBarry Smith 
3430f5bd95cSBarry Smith    Note Collective
344b9cd556bSLois Curfman McInnes 
34590f02eecSBarry Smith    Input Parameters:
34690f02eecSBarry Smith .  mapping - mapping data structure
34790f02eecSBarry Smith 
348a997ad1aSLois Curfman McInnes    Level: advanced
349a997ad1aSLois Curfman McInnes 
3503acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
35190f02eecSBarry Smith @*/
3526bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
35390f02eecSBarry Smith {
354dfbe8321SBarry Smith   PetscErrorCode ierr;
3555fd66863SKarl Rupp 
3563a40ed3dSBarry Smith   PetscFunctionBegin;
3576bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3586bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
359997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3606bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3616bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->globals);CHKERRQ(ierr);
362d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
363992144d0SBarry Smith   *mapping = 0;
3643a40ed3dSBarry Smith   PetscFunctionReturn(0);
36590f02eecSBarry Smith }
36690f02eecSBarry Smith 
3674a2ae208SSatish Balay #undef __FUNCT__
3684a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
36990f02eecSBarry Smith /*@
3703acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3713acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3723acfe500SLois Curfman McInnes     context.
37390f02eecSBarry Smith 
374b9cd556bSLois Curfman McInnes     Not collective
375b9cd556bSLois Curfman McInnes 
37690f02eecSBarry Smith     Input Parameters:
377b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
378b9cd556bSLois Curfman McInnes -   is - index set in local numbering
37990f02eecSBarry Smith 
38090f02eecSBarry Smith     Output Parameters:
38190f02eecSBarry Smith .   newis - index set in global numbering
38290f02eecSBarry Smith 
383a997ad1aSLois Curfman McInnes     Level: advanced
384a997ad1aSLois Curfman McInnes 
385273d9f13SBarry Smith     Concepts: mapping^local to global
3863acfe500SLois Curfman McInnes 
38790f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
388d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
38990f02eecSBarry Smith @*/
3907087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
39190f02eecSBarry Smith {
3926849ba73SBarry Smith   PetscErrorCode ierr;
3935d0c19d7SBarry Smith   PetscInt       n,i,*idxmap,*idxout,Nmax = mapping->n;
3945d0c19d7SBarry Smith   const PetscInt *idxin;
3953a40ed3dSBarry Smith 
3963a40ed3dSBarry Smith   PetscFunctionBegin;
3970700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3980700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3994482741eSBarry Smith   PetscValidPointer(newis,3);
40090f02eecSBarry Smith 
4013b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
40290f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
40390f02eecSBarry Smith   idxmap = mapping->indices;
40490f02eecSBarry Smith 
405785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
40690f02eecSBarry Smith   for (i=0; i<n; i++) {
4077904a332SBarry 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);
40890f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
40990f02eecSBarry Smith   }
4103b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
411543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4123a40ed3dSBarry Smith   PetscFunctionReturn(0);
41390f02eecSBarry Smith }
41490f02eecSBarry Smith 
415afcb2eb5SJed Brown #undef __FUNCT__
416afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
417b89cb25eSSatish Balay /*@
4183acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4193acfe500SLois Curfman McInnes    and converts them to the global numbering.
42090f02eecSBarry Smith 
421b9cd556bSLois Curfman McInnes    Not collective
422b9cd556bSLois Curfman McInnes 
423bb25748dSBarry Smith    Input Parameters:
424b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
425bb25748dSBarry Smith .  N - number of integers
426b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
427bb25748dSBarry Smith 
428bb25748dSBarry Smith    Output Parameter:
429bb25748dSBarry Smith .  out - indices in global numbering
430bb25748dSBarry Smith 
431b9cd556bSLois Curfman McInnes    Notes:
432b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
433d4bb536fSBarry Smith 
434a997ad1aSLois Curfman McInnes    Level: advanced
435a997ad1aSLois Curfman McInnes 
436bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4370752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
438d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
439bb25748dSBarry Smith 
440273d9f13SBarry Smith     Concepts: mapping^local to global
441afcb2eb5SJed Brown @*/
442afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
443afcb2eb5SJed Brown {
444afcb2eb5SJed Brown   PetscInt       i,Nmax = mapping->n;
445afcb2eb5SJed Brown   const PetscInt *idx = mapping->indices;
446d4bb536fSBarry Smith 
447afcb2eb5SJed Brown   PetscFunctionBegin;
448afcb2eb5SJed Brown   for (i=0; i<N; i++) {
449afcb2eb5SJed Brown     if (in[i] < 0) {
450afcb2eb5SJed Brown       out[i] = in[i];
451afcb2eb5SJed Brown       continue;
452afcb2eb5SJed Brown     }
453afcb2eb5SJed 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);
454afcb2eb5SJed Brown     out[i] = idx[in[i]];
455afcb2eb5SJed Brown   }
456afcb2eb5SJed Brown   PetscFunctionReturn(0);
457afcb2eb5SJed Brown }
458d4bb536fSBarry Smith 
459d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
460d4bb536fSBarry Smith 
4614a2ae208SSatish Balay #undef __FUNCT__
4624a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
463d4bb536fSBarry Smith /*
464d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
465d4bb536fSBarry Smith */
4666849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
467d4bb536fSBarry Smith {
4686849ba73SBarry Smith   PetscErrorCode ierr;
46932dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
470d4bb536fSBarry Smith 
4713a40ed3dSBarry Smith   PetscFunctionBegin;
472d4bb536fSBarry Smith   end   = 0;
473ec268f7cSJed Brown   start = PETSC_MAX_INT;
474d4bb536fSBarry Smith 
475d4bb536fSBarry Smith   for (i=0; i<n; i++) {
476d4bb536fSBarry Smith     if (idx[i] < 0) continue;
477d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
478d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
479d4bb536fSBarry Smith   }
480d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
481d4bb536fSBarry Smith   mapping->globalstart = start;
482d4bb536fSBarry Smith   mapping->globalend   = end;
483d4bb536fSBarry Smith 
484785e854fSJed Brown   ierr             = PetscMalloc1((end-start+2),&globals);CHKERRQ(ierr);
485b0a32e0cSBarry Smith   mapping->globals = globals;
486f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
487d4bb536fSBarry Smith   for (i=0; i<n; i++) {
488d4bb536fSBarry Smith     if (idx[i] < 0) continue;
489d4bb536fSBarry Smith     globals[idx[i] - start] = i;
490d4bb536fSBarry Smith   }
491d4bb536fSBarry Smith 
4923bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
4933a40ed3dSBarry Smith   PetscFunctionReturn(0);
494d4bb536fSBarry Smith }
495d4bb536fSBarry Smith 
4964a2ae208SSatish Balay #undef __FUNCT__
4974a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
498d4bb536fSBarry Smith /*@
499a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
500a997ad1aSLois Curfman McInnes     specified with a global numbering.
501d4bb536fSBarry Smith 
502b9cd556bSLois Curfman McInnes     Not collective
503b9cd556bSLois Curfman McInnes 
504d4bb536fSBarry Smith     Input Parameters:
505b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
506d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
507d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
508d4bb536fSBarry Smith .   n - number of global indices to map
509b9cd556bSLois Curfman McInnes -   idx - global indices to map
510d4bb536fSBarry Smith 
511d4bb536fSBarry Smith     Output Parameters:
512b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
513b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
514e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5150298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
516e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
517e182c471SBarry Smith              a second time to set the values.
518d4bb536fSBarry Smith 
519b9cd556bSLois Curfman McInnes     Notes:
5200298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
521d4bb536fSBarry Smith 
5220f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5230f5bd95cSBarry Smith     array to compute these.
5240f5bd95cSBarry Smith 
525a997ad1aSLois Curfman McInnes     Level: advanced
526a997ad1aSLois Curfman McInnes 
52732fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
52832fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
52932fd6b96SBarry Smith 
530273d9f13SBarry Smith     Concepts: mapping^global to local
531d4bb536fSBarry Smith 
532d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
533d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
534d4bb536fSBarry Smith @*/
5357087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
53632dcc486SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
537d4bb536fSBarry Smith {
53832dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
5396849ba73SBarry Smith   PetscErrorCode ierr;
540d4bb536fSBarry Smith 
5413a40ed3dSBarry Smith   PetscFunctionBegin;
5420700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
543d4bb536fSBarry Smith   if (!mapping->globals) {
544d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
545d4bb536fSBarry Smith   }
546d4bb536fSBarry Smith   globals = mapping->globals;
547d4bb536fSBarry Smith   start   = mapping->globalstart;
548d4bb536fSBarry Smith   end     = mapping->globalend;
549d4bb536fSBarry Smith 
550d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
551d4bb536fSBarry Smith     if (idxout) {
552d4bb536fSBarry Smith       for (i=0; i<n; i++) {
553d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
554d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
555d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
556d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
557d4bb536fSBarry Smith       }
558d4bb536fSBarry Smith     }
559d4bb536fSBarry Smith     if (nout) *nout = n;
560d4bb536fSBarry Smith   } else {
561d4bb536fSBarry Smith     if (idxout) {
562d4bb536fSBarry Smith       for (i=0; i<n; i++) {
563d4bb536fSBarry Smith         if (idx[i] < 0) continue;
564d4bb536fSBarry Smith         if (idx[i] < start) continue;
565d4bb536fSBarry Smith         if (idx[i] > end) continue;
566d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
567d4bb536fSBarry Smith         if (tmp < 0) continue;
568d4bb536fSBarry Smith         idxout[nf++] = tmp;
569d4bb536fSBarry Smith       }
570d4bb536fSBarry Smith     } else {
571d4bb536fSBarry Smith       for (i=0; i<n; i++) {
572d4bb536fSBarry Smith         if (idx[i] < 0) continue;
573d4bb536fSBarry Smith         if (idx[i] < start) continue;
574d4bb536fSBarry Smith         if (idx[i] > end) continue;
575d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
576d4bb536fSBarry Smith         if (tmp < 0) continue;
577d4bb536fSBarry Smith         nf++;
578d4bb536fSBarry Smith       }
579d4bb536fSBarry Smith     }
580d4bb536fSBarry Smith     if (nout) *nout = nf;
581d4bb536fSBarry Smith   }
5823a40ed3dSBarry Smith   PetscFunctionReturn(0);
583d4bb536fSBarry Smith }
58490f02eecSBarry Smith 
5854a2ae208SSatish Balay #undef __FUNCT__
5864a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
58789d82c54SBarry Smith /*@C
58889d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
58989d82c54SBarry Smith      each index shared by more than one processor
59089d82c54SBarry Smith 
59189d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
59289d82c54SBarry Smith 
59389d82c54SBarry Smith     Input Parameters:
59489d82c54SBarry Smith .   mapping - the mapping from local to global indexing
59589d82c54SBarry Smith 
59689d82c54SBarry Smith     Output Parameter:
59789d82c54SBarry Smith +   nproc - number of processors that are connected to this one
59889d82c54SBarry Smith .   proc - neighboring processors
59907b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
6003463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
60189d82c54SBarry Smith 
60289d82c54SBarry Smith     Level: advanced
60389d82c54SBarry Smith 
604273d9f13SBarry Smith     Concepts: mapping^local to global
60589d82c54SBarry Smith 
6062cfcea29SBarry Smith     Fortran Usage:
6072cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
6082cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
6092cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
6102cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
6112cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
6122cfcea29SBarry Smith 
6132cfcea29SBarry Smith 
61407b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
61507b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
61689d82c54SBarry Smith @*/
6177087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
61889d82c54SBarry Smith {
6196849ba73SBarry Smith   PetscErrorCode ierr;
62097f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
62132dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
62232dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
62397f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
62432dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
62532dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
62689d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
62730dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
628ce94432eSBarry Smith   MPI_Comm       comm;
629ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
63089d82c54SBarry Smith 
63189d82c54SBarry Smith   PetscFunctionBegin;
6320700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
633ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
63424cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
63524cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
63624cf384cSBarry Smith   if (size == 1) {
63724cf384cSBarry Smith     *nproc         = 0;
6380298fd71SBarry Smith     *procs         = NULL;
63932dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
6401e2105dcSBarry Smith     (*numprocs)[0] = 0;
64132dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
6420298fd71SBarry Smith     (*indices)[0]  = NULL;
64324cf384cSBarry Smith     PetscFunctionReturn(0);
64424cf384cSBarry Smith   }
64524cf384cSBarry Smith 
6460298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
64707b52d57SBarry Smith 
6483677ff5aSBarry Smith   /*
6493677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
6503677ff5aSBarry Smith 
6513677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
6523677ff5aSBarry Smith            numbering, just for this routine.
6533677ff5aSBarry Smith 
6543677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
6553677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
6563677ff5aSBarry Smith 
6573677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
6583677ff5aSBarry Smith 
6593677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
6603677ff5aSBarry Smith            local subdomain
6613677ff5aSBarry Smith   */
66224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
66324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
66424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
66589d82c54SBarry Smith 
66689d82c54SBarry Smith   for (i=0; i<n; i++) {
66789d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
66889d82c54SBarry Smith   }
66932dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
67078058e43SBarry Smith   Ng++;
67189d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
67289d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
673bc8ff85bSBarry Smith   scale  = Ng/size + 1;
674a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
675caba0dd0SBarry Smith   rstart = scale*rank;
67689d82c54SBarry Smith 
67789d82c54SBarry Smith   /* determine ownership ranges of global indices */
678785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
67932dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
68089d82c54SBarry Smith 
68189d82c54SBarry Smith   /* determine owners of each local node  */
682785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
68389d82c54SBarry Smith   for (i=0; i<n; i++) {
6843677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
68527c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
6863677ff5aSBarry Smith     owner[i]         = proc;
68727c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
68889d82c54SBarry Smith   }
68927c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
6907904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
69189d82c54SBarry Smith 
69289d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
69327c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
6947904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
69589d82c54SBarry Smith 
69689d82c54SBarry Smith   /* post receives for owned rows */
697785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
698785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1),&recv_waits);CHKERRQ(ierr);
69989d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
70032dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
70189d82c54SBarry Smith   }
70289d82c54SBarry Smith 
70389d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
704785e854fSJed Brown   ierr      = PetscMalloc1((2*n+1),&sends);CHKERRQ(ierr);
705785e854fSJed Brown   ierr      = PetscMalloc1((size+1),&starts);CHKERRQ(ierr);
70689d82c54SBarry Smith   starts[0] = 0;
707f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
70889d82c54SBarry Smith   for (i=0; i<n; i++) {
70989d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
71030dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
71189d82c54SBarry Smith   }
71289d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
71389d82c54SBarry Smith   starts[0] = 0;
714f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
71589d82c54SBarry Smith 
71689d82c54SBarry Smith   /* send the messages */
717785e854fSJed Brown   ierr = PetscMalloc1((nsends+1),&send_waits);CHKERRQ(ierr);
718785e854fSJed Brown   ierr = PetscMalloc1((nsends+1),&dest);CHKERRQ(ierr);
71989d82c54SBarry Smith   cnt = 0;
72089d82c54SBarry Smith   for (i=0; i<size; i++) {
72127c402fcSBarry Smith     if (nprocs[2*i]) {
72232dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
72330dcb7c9SBarry Smith       dest[cnt] = i;
72489d82c54SBarry Smith       cnt++;
72589d82c54SBarry Smith     }
72689d82c54SBarry Smith   }
72789d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
72889d82c54SBarry Smith 
72989d82c54SBarry Smith   /* wait on receives */
730785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1),&source);CHKERRQ(ierr);
731785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1),&len);CHKERRQ(ierr);
73289d82c54SBarry Smith   cnt  = nrecvs;
733785e854fSJed Brown   ierr = PetscMalloc1((ng+1),&nownedsenders);CHKERRQ(ierr);
73432dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
73589d82c54SBarry Smith   while (cnt) {
73689d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
73789d82c54SBarry Smith     /* unpack receives into our local space */
73832dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
73989d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
74030dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
741caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
74230dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
74389d82c54SBarry Smith     cnt--;
74489d82c54SBarry Smith   }
74589d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
74689d82c54SBarry Smith 
74730dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
748bc8ff85bSBarry Smith   nowned  = 0;
749bc8ff85bSBarry Smith   nownedm = 0;
750bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
751bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
752bc8ff85bSBarry Smith   }
753bc8ff85bSBarry Smith 
754bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
755785e854fSJed Brown   ierr      = PetscMalloc1((nownedm+1),&ownedsenders);CHKERRQ(ierr);
756785e854fSJed Brown   ierr      = PetscMalloc1((ng+1),&starts);CHKERRQ(ierr);
757bc8ff85bSBarry Smith   starts[0] = 0;
758bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
759bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
760bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
761bc8ff85bSBarry Smith   }
762bc8ff85bSBarry Smith 
76330dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
764bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
765bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
76630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
767f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
768bc8ff85bSBarry Smith     }
769bc8ff85bSBarry Smith   }
770bc8ff85bSBarry Smith 
77107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
77230dcb7c9SBarry Smith     starts[0] = 0;
77330dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
77430dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
77530dcb7c9SBarry Smith       else starts[i] = starts[i-1];
77630dcb7c9SBarry Smith     }
77730dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
77830dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
7797904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
78030dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
7817904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
78230dcb7c9SBarry Smith         }
78330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
78430dcb7c9SBarry Smith       }
78530dcb7c9SBarry Smith     }
7860ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
78707b52d57SBarry Smith   } /* -----------------------------------  */
78830dcb7c9SBarry Smith 
7893677ff5aSBarry Smith   /* wait on original sends */
7903a96401aSBarry Smith   if (nsends) {
791785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
7923a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
7933a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
7943a96401aSBarry Smith   }
79589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
7963a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
7973677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
7983677ff5aSBarry Smith 
7993677ff5aSBarry Smith   /* pack messages to send back to local owners */
80030dcb7c9SBarry Smith   starts[0] = 0;
80130dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
80230dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
80330dcb7c9SBarry Smith     else starts[i] = starts[i-1];
80430dcb7c9SBarry Smith   }
80530dcb7c9SBarry Smith   nsends2 = nrecvs;
806785e854fSJed Brown   ierr    = PetscMalloc1((nsends2+1),&nprocs);CHKERRQ(ierr); /* length of each message */
80730dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
80830dcb7c9SBarry Smith     nprocs[i] = 1;
80930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
81030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
811f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
81230dcb7c9SBarry Smith     }
81330dcb7c9SBarry Smith   }
814f6e5521dSKarl Rupp   nt = 0;
815f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
816f6e5521dSKarl Rupp 
817785e854fSJed Brown   ierr = PetscMalloc1((nt+1),&sends2);CHKERRQ(ierr);
818785e854fSJed Brown   ierr = PetscMalloc1((nsends2+1),&starts2);CHKERRQ(ierr);
819f6e5521dSKarl Rupp 
820f6e5521dSKarl Rupp   starts2[0] = 0;
821f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
82230dcb7c9SBarry Smith   /*
82330dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
82430dcb7c9SBarry Smith        (0) the number of nodes being sent back
82530dcb7c9SBarry Smith        (1) the local node number,
82630dcb7c9SBarry Smith        (2) the number of processors sharing it,
82730dcb7c9SBarry Smith        (3) the processors sharing it
82830dcb7c9SBarry Smith   */
82930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
83030dcb7c9SBarry Smith     cnt = 1;
83130dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
83230dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
83330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
83430dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
83530dcb7c9SBarry Smith         sends2[starts2[i]]++;
83630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
83730dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
83832dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
83930dcb7c9SBarry Smith         cnt += nownedsenders[node];
84030dcb7c9SBarry Smith       }
84130dcb7c9SBarry Smith     }
84230dcb7c9SBarry Smith   }
84330dcb7c9SBarry Smith 
84430dcb7c9SBarry Smith   /* receive the message lengths */
84530dcb7c9SBarry Smith   nrecvs2 = nsends;
846785e854fSJed Brown   ierr    = PetscMalloc1((nrecvs2+1),&lens2);CHKERRQ(ierr);
847785e854fSJed Brown   ierr    = PetscMalloc1((nrecvs2+1),&starts3);CHKERRQ(ierr);
848785e854fSJed Brown   ierr    = PetscMalloc1((nrecvs2+1),&recv_waits);CHKERRQ(ierr);
84930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
850d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
85130dcb7c9SBarry Smith   }
852d44834fbSBarry Smith 
8538a8e0b3aSBarry Smith   /* send the message lengths */
8548a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
8558a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
8568a8e0b3aSBarry Smith   }
8578a8e0b3aSBarry Smith 
858d44834fbSBarry Smith   /* wait on receives of lens */
8590c468ba9SBarry Smith   if (nrecvs2) {
860785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
861d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
862d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
8630c468ba9SBarry Smith   }
864a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
865d44834fbSBarry Smith 
86630dcb7c9SBarry Smith   starts3[0] = 0;
867d44834fbSBarry Smith   nt         = 0;
86830dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
86930dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
870d44834fbSBarry Smith     nt          += lens2[i];
87130dcb7c9SBarry Smith   }
87276466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
873d44834fbSBarry Smith 
874785e854fSJed Brown   ierr = PetscMalloc1((nt+1),&recvs2);CHKERRQ(ierr);
875785e854fSJed Brown   ierr = PetscMalloc1((nrecvs2+1),&recv_waits);CHKERRQ(ierr);
87652b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
87732dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
87830dcb7c9SBarry Smith   }
87930dcb7c9SBarry Smith 
88030dcb7c9SBarry Smith   /* send the messages */
881785e854fSJed Brown   ierr = PetscMalloc1((nsends2+1),&send_waits);CHKERRQ(ierr);
88230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
88332dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
88430dcb7c9SBarry Smith   }
88530dcb7c9SBarry Smith 
88630dcb7c9SBarry Smith   /* wait on receives */
8870c468ba9SBarry Smith   if (nrecvs2) {
888785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
88930dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
89030dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
8910c468ba9SBarry Smith   }
89230dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
89330dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
89430dcb7c9SBarry Smith 
89507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
89630dcb7c9SBarry Smith     cnt = 0;
89730dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
89830dcb7c9SBarry Smith       nt = recvs2[cnt++];
89930dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
9007904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
90130dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
9027904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
90330dcb7c9SBarry Smith         }
90430dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
90530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
90630dcb7c9SBarry Smith       }
90730dcb7c9SBarry Smith     }
9080ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
90907b52d57SBarry Smith   } /* -----------------------------------  */
91030dcb7c9SBarry Smith 
91130dcb7c9SBarry Smith   /* count number subdomains for each local node */
912785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
91332dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
91430dcb7c9SBarry Smith   cnt  = 0;
91530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
91630dcb7c9SBarry Smith     nt = recvs2[cnt++];
91730dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
918f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
91930dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
92030dcb7c9SBarry Smith     }
92130dcb7c9SBarry Smith   }
92230dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
92330dcb7c9SBarry Smith   *nproc    = nt;
924785e854fSJed Brown   ierr = PetscMalloc1((nt+1),procs);CHKERRQ(ierr);
925785e854fSJed Brown   ierr = PetscMalloc1((nt+1),numprocs);CHKERRQ(ierr);
926785e854fSJed Brown   ierr = PetscMalloc1((nt+1),indices);CHKERRQ(ierr);
9270298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
928785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
92930dcb7c9SBarry Smith   cnt       = 0;
93030dcb7c9SBarry Smith   for (i=0; i<size; i++) {
93130dcb7c9SBarry Smith     if (nprocs[i] > 0) {
93230dcb7c9SBarry Smith       bprocs[i]        = cnt;
93330dcb7c9SBarry Smith       (*procs)[cnt]    = i;
93430dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
935785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
93630dcb7c9SBarry Smith       cnt++;
93730dcb7c9SBarry Smith     }
93830dcb7c9SBarry Smith   }
93930dcb7c9SBarry Smith 
94030dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
94132dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
94230dcb7c9SBarry Smith   cnt  = 0;
94330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
94430dcb7c9SBarry Smith     nt = recvs2[cnt++];
94530dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
946f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
94730dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
94830dcb7c9SBarry Smith     }
94930dcb7c9SBarry Smith   }
95030dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
95107b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
95230dcb7c9SBarry Smith 
95307b52d57SBarry Smith   /* sort the node indexing by their global numbers */
95407b52d57SBarry Smith   nt = *nproc;
95507b52d57SBarry Smith   for (i=0; i<nt; i++) {
956785e854fSJed Brown     ierr = PetscMalloc1(((*numprocs)[i]),&tmp);CHKERRQ(ierr);
957f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
95807b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
95907b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
96007b52d57SBarry Smith   }
96107b52d57SBarry Smith 
96207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
96330dcb7c9SBarry Smith     nt = *nproc;
96430dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
9657904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
96630dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
9677904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
96830dcb7c9SBarry Smith       }
96930dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
97030dcb7c9SBarry Smith     }
9710ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
97207b52d57SBarry Smith   } /* -----------------------------------  */
97330dcb7c9SBarry Smith 
97430dcb7c9SBarry Smith   /* wait on sends */
97530dcb7c9SBarry Smith   if (nsends2) {
976785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
97730dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
97830dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
97930dcb7c9SBarry Smith   }
98030dcb7c9SBarry Smith 
98130dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
98230dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
98330dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
9843677ff5aSBarry Smith 
985bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
986bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
987bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
98830dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
98930dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
99089d82c54SBarry Smith 
99189d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
99297f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
99389d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
9943a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
99530dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
99624cf384cSBarry Smith 
99724cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
99824cf384cSBarry Smith   first_procs    = (*procs)[0];
99924cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
100024cf384cSBarry Smith   first_indices  = (*indices)[0];
100124cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
100224cf384cSBarry Smith     if ((*procs)[i] == rank) {
100324cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
100424cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
100524cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
100624cf384cSBarry Smith       (*procs)[i]    = first_procs;
100724cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
100824cf384cSBarry Smith       (*indices)[i]  = first_indices;
100924cf384cSBarry Smith       break;
101024cf384cSBarry Smith     }
101124cf384cSBarry Smith   }
101289d82c54SBarry Smith   PetscFunctionReturn(0);
101389d82c54SBarry Smith }
101489d82c54SBarry Smith 
10154a2ae208SSatish Balay #undef __FUNCT__
10164a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
101707b52d57SBarry Smith /*@C
101807b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
101989d82c54SBarry Smith 
102007b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
102107b52d57SBarry Smith 
102207b52d57SBarry Smith     Input Parameters:
102307b52d57SBarry Smith .   mapping - the mapping from local to global indexing
102407b52d57SBarry Smith 
102507b52d57SBarry Smith     Output Parameter:
102607b52d57SBarry Smith +   nproc - number of processors that are connected to this one
102707b52d57SBarry Smith .   proc - neighboring processors
102807b52d57SBarry Smith .   numproc - number of indices for each processor
102907b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
103007b52d57SBarry Smith 
103107b52d57SBarry Smith     Level: advanced
103207b52d57SBarry Smith 
103307b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
103407b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
103507b52d57SBarry Smith @*/
10367087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
103707b52d57SBarry Smith {
10386849ba73SBarry Smith   PetscErrorCode ierr;
103932dcc486SBarry Smith   PetscInt       i;
104007b52d57SBarry Smith 
104107b52d57SBarry Smith   PetscFunctionBegin;
104205b42c5fSBarry Smith   ierr = PetscFree(*procs);CHKERRQ(ierr);
104305b42c5fSBarry Smith   ierr = PetscFree(*numprocs);CHKERRQ(ierr);
104400ff320aSBarry Smith   if (*indices) {
104505b42c5fSBarry Smith     ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
104600ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
104705b42c5fSBarry Smith       ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
104807b52d57SBarry Smith     }
104907b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
105024cf384cSBarry Smith   }
105107b52d57SBarry Smith   PetscFunctionReturn(0);
105207b52d57SBarry Smith }
105386994e45SJed Brown 
105486994e45SJed Brown #undef __FUNCT__
105586994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
105686994e45SJed Brown /*@C
105786994e45SJed Brown    ISLocalToGlobalMappingGetIndices - Get global indices for every local point
105886994e45SJed Brown 
105986994e45SJed Brown    Not Collective
106086994e45SJed Brown 
106186994e45SJed Brown    Input Arguments:
106286994e45SJed Brown . ltog - local to global mapping
106386994e45SJed Brown 
106486994e45SJed Brown    Output Arguments:
106586994e45SJed Brown . array - array of indices
106686994e45SJed Brown 
106786994e45SJed Brown    Level: advanced
106886994e45SJed Brown 
106986994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices()
107086994e45SJed Brown @*/
10717087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
107286994e45SJed Brown {
107386994e45SJed Brown   PetscFunctionBegin;
107486994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
107586994e45SJed Brown   PetscValidPointer(array,2);
107686994e45SJed Brown   *array = ltog->indices;
107786994e45SJed Brown   PetscFunctionReturn(0);
107886994e45SJed Brown }
107986994e45SJed Brown 
108086994e45SJed Brown #undef __FUNCT__
108186994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
108286994e45SJed Brown /*@C
108386994e45SJed Brown    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingRestoreIndices()
108486994e45SJed Brown 
108586994e45SJed Brown    Not Collective
108686994e45SJed Brown 
108786994e45SJed Brown    Input Arguments:
108886994e45SJed Brown + ltog - local to global mapping
108986994e45SJed Brown - array - array of indices
109086994e45SJed Brown 
109186994e45SJed Brown    Level: advanced
109286994e45SJed Brown 
109386994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
109486994e45SJed Brown @*/
10957087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
109686994e45SJed Brown {
109786994e45SJed Brown   PetscFunctionBegin;
109886994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
109986994e45SJed Brown   PetscValidPointer(array,2);
110086994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
11010298fd71SBarry Smith   *array = NULL;
110286994e45SJed Brown   PetscFunctionReturn(0);
110386994e45SJed Brown }
1104f7efa3c7SJed Brown 
1105f7efa3c7SJed Brown #undef __FUNCT__
1106f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1107f7efa3c7SJed Brown /*@C
1108f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1109f7efa3c7SJed Brown 
1110f7efa3c7SJed Brown    Not Collective
1111f7efa3c7SJed Brown 
1112f7efa3c7SJed Brown    Input Arguments:
1113f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1114f7efa3c7SJed Brown . n - number of mappings to concatenate
1115f7efa3c7SJed Brown - ltogs - local to global mappings
1116f7efa3c7SJed Brown 
1117f7efa3c7SJed Brown    Output Arguments:
1118f7efa3c7SJed Brown . ltogcat - new mapping
1119f7efa3c7SJed Brown 
1120f7efa3c7SJed Brown    Level: advanced
1121f7efa3c7SJed Brown 
1122f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1123f7efa3c7SJed Brown @*/
1124f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1125f7efa3c7SJed Brown {
1126f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1127f7efa3c7SJed Brown   PetscErrorCode ierr;
1128f7efa3c7SJed Brown 
1129f7efa3c7SJed Brown   PetscFunctionBegin;
1130f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1131f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1132f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1133f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1134f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1135f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1136f7efa3c7SJed Brown     cnt += m;
1137f7efa3c7SJed Brown   }
1138785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1139f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1140f7efa3c7SJed Brown     const PetscInt *subidx;
1141f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1142f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1143f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1144f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1145f7efa3c7SJed Brown     cnt += m;
1146f7efa3c7SJed Brown   }
1147f7efa3c7SJed Brown   ierr = ISLocalToGlobalMappingCreate(comm,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1148f7efa3c7SJed Brown   PetscFunctionReturn(0);
1149f7efa3c7SJed Brown }
115004a59952SBarry Smith 
115104a59952SBarry Smith 
1152