xref: /petsc/src/vec/is/utils/isltog.c (revision cd5a51df59a27f6d1f21820231b52f6dcc92535a)
12362add9SBarry Smith 
2af0996ceSBarry Smith #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;
7268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***);
88e58c17dSMatthew Knepley 
96658fb44Sstefano_zampini /*@
106658fb44Sstefano_zampini     ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
116658fb44Sstefano_zampini 
126658fb44Sstefano_zampini     Not Collective
136658fb44Sstefano_zampini 
146658fb44Sstefano_zampini     Input Parameter:
156658fb44Sstefano_zampini .   ltog - local to global mapping
166658fb44Sstefano_zampini 
176658fb44Sstefano_zampini     Output Parameter:
186658fb44Sstefano_zampini .   nltog - the duplicated local to global mapping
196658fb44Sstefano_zampini 
206658fb44Sstefano_zampini     Level: advanced
216658fb44Sstefano_zampini 
226658fb44Sstefano_zampini     Concepts: mapping^local to global
236658fb44Sstefano_zampini 
246658fb44Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
256658fb44Sstefano_zampini @*/
266658fb44Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping* nltog)
276658fb44Sstefano_zampini {
286658fb44Sstefano_zampini   PetscErrorCode ierr;
296658fb44Sstefano_zampini 
306658fb44Sstefano_zampini   PetscFunctionBegin;
316658fb44Sstefano_zampini   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
326658fb44Sstefano_zampini   ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog),ltog->bs,ltog->n,ltog->indices,PETSC_COPY_VALUES,nltog);CHKERRQ(ierr);
336658fb44Sstefano_zampini   PetscFunctionReturn(0);
346658fb44Sstefano_zampini }
356658fb44Sstefano_zampini 
36565245c5SBarry Smith /*@
37107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
383b9aefa3SBarry Smith 
393b9aefa3SBarry Smith     Not Collective
403b9aefa3SBarry Smith 
413b9aefa3SBarry Smith     Input Parameter:
423b9aefa3SBarry Smith .   ltog - local to global mapping
433b9aefa3SBarry Smith 
443b9aefa3SBarry Smith     Output Parameter:
45107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
463b9aefa3SBarry Smith 
473b9aefa3SBarry Smith     Level: advanced
483b9aefa3SBarry Smith 
49273d9f13SBarry Smith     Concepts: mapping^local to global
503b9aefa3SBarry Smith 
513b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
523b9aefa3SBarry Smith @*/
537087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
543b9aefa3SBarry Smith {
553b9aefa3SBarry Smith   PetscFunctionBegin;
560700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
574482741eSBarry Smith   PetscValidIntPointer(n,2);
58107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
593b9aefa3SBarry Smith   PetscFunctionReturn(0);
603b9aefa3SBarry Smith }
613b9aefa3SBarry Smith 
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) {
9498c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
951575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);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);
1001575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
1011575c14dSBarry Smith   }
1025a5d4f66SBarry Smith   PetscFunctionReturn(0);
1035a5d4f66SBarry Smith }
1045a5d4f66SBarry Smith 
1051f428162SBarry Smith /*@
1062bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1072bdab257SBarry Smith     ordering and a global parallel ordering.
1082bdab257SBarry Smith 
1090f5bd95cSBarry Smith     Not collective
110b9cd556bSLois Curfman McInnes 
111a997ad1aSLois Curfman McInnes     Input Parameter:
1128c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1132bdab257SBarry Smith 
114a997ad1aSLois Curfman McInnes     Output Parameter:
1152bdab257SBarry Smith .   mapping - new mapping data structure
1162bdab257SBarry Smith 
117f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
118a997ad1aSLois Curfman McInnes     Level: advanced
119a997ad1aSLois Curfman McInnes 
120273d9f13SBarry Smith     Concepts: mapping^local to global
1212bdab257SBarry Smith 
1222bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1232bdab257SBarry Smith @*/
1247087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1252bdab257SBarry Smith {
1266849ba73SBarry Smith   PetscErrorCode ierr;
1273bbf0e92SBarry Smith   PetscInt       n,bs;
1285d0c19d7SBarry Smith   const PetscInt *indices;
1292bdab257SBarry Smith   MPI_Comm       comm;
1303bbf0e92SBarry Smith   PetscBool      isblock;
1313a40ed3dSBarry Smith 
1323a40ed3dSBarry Smith   PetscFunctionBegin;
1330700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1344482741eSBarry Smith   PetscValidPointer(mapping,2);
1352bdab257SBarry Smith 
1362bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1373b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1383bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1396006e8d2SBarry Smith   if (!isblock) {
140f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
141f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1422bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1436006e8d2SBarry Smith   } else {
1446006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
145f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
14628bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
147f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1486006e8d2SBarry Smith   }
1493a40ed3dSBarry Smith   PetscFunctionReturn(0);
1502bdab257SBarry Smith }
1515a5d4f66SBarry Smith 
152a4d96a55SJed Brown /*@C
153a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
154a4d96a55SJed Brown     ordering and a global parallel ordering.
155a4d96a55SJed Brown 
156a4d96a55SJed Brown     Collective
157a4d96a55SJed Brown 
158a4d96a55SJed Brown     Input Parameter:
159a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
160a4d96a55SJed Brown -   start - first global index on this process
161a4d96a55SJed Brown 
162a4d96a55SJed Brown     Output Parameter:
163a4d96a55SJed Brown .   mapping - new mapping data structure
164a4d96a55SJed Brown 
165a4d96a55SJed Brown     Level: advanced
166a4d96a55SJed Brown 
167a4d96a55SJed Brown     Concepts: mapping^local to global
168a4d96a55SJed Brown 
169a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
170a4d96a55SJed Brown @*/
171a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
172a4d96a55SJed Brown {
173a4d96a55SJed Brown   PetscErrorCode ierr;
174a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
175a4d96a55SJed Brown   const PetscInt *ilocal;
176a4d96a55SJed Brown   MPI_Comm       comm;
177a4d96a55SJed Brown 
178a4d96a55SJed Brown   PetscFunctionBegin;
179a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
180a4d96a55SJed Brown   PetscValidPointer(mapping,3);
181a4d96a55SJed Brown 
182a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1830298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
184f6e5521dSKarl Rupp   if (ilocal) {
185f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
186f6e5521dSKarl Rupp   }
187a4d96a55SJed Brown   else maxlocal = nleaves;
188785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
189785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
190a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
191a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
192a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
193a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
194f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
195a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
196a4d96a55SJed Brown   PetscFunctionReturn(0);
197a4d96a55SJed Brown }
198b46b645bSBarry Smith 
19963fa5c83Sstefano_zampini /*@
20063fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
20163fa5c83Sstefano_zampini 
20263fa5c83Sstefano_zampini     Not collective
20363fa5c83Sstefano_zampini 
20463fa5c83Sstefano_zampini     Input Parameters:
20563fa5c83Sstefano_zampini .   mapping - mapping data structure
20663fa5c83Sstefano_zampini .   bs - the blocksize
20763fa5c83Sstefano_zampini 
20863fa5c83Sstefano_zampini     Level: advanced
20963fa5c83Sstefano_zampini 
21063fa5c83Sstefano_zampini     Concepts: mapping^local to global
21163fa5c83Sstefano_zampini 
21263fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
21363fa5c83Sstefano_zampini @*/
21463fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
21563fa5c83Sstefano_zampini {
216a59f3c4dSstefano_zampini   PetscInt       *nid;
217a59f3c4dSstefano_zampini   const PetscInt *oid;
218a59f3c4dSstefano_zampini   PetscInt       i,cn,on,obs,nn;
21963fa5c83Sstefano_zampini   PetscErrorCode ierr;
22063fa5c83Sstefano_zampini 
22163fa5c83Sstefano_zampini   PetscFunctionBegin;
22263fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
22363fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
22463fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
22563fa5c83Sstefano_zampini   on  = mapping->n;
22663fa5c83Sstefano_zampini   obs = mapping->bs;
22763fa5c83Sstefano_zampini   oid = mapping->indices;
22863fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
22963fa5c83Sstefano_zampini   if ((on*obs)%bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D and number of block indices %D",bs,obs,on);
230a59f3c4dSstefano_zampini 
23163fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
232a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingGetIndices(mapping,&oid);CHKERRQ(ierr);
233a59f3c4dSstefano_zampini   for (i=0;i<nn;i++) {
234a59f3c4dSstefano_zampini     PetscInt j;
235a59f3c4dSstefano_zampini     for (j=0,cn=0;j<bs-1;j++) {
236a59f3c4dSstefano_zampini       if (oid[i*bs+j] < 0) { cn++; continue; }
237a59f3c4dSstefano_zampini       if (oid[i*bs+j] != oid[i*bs+j+1]-1) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices %D %D",bs,obs,oid[i*bs+j],oid[i*bs+j+1]);
238a59f3c4dSstefano_zampini     }
239a59f3c4dSstefano_zampini     if (oid[i*bs+j] < 0) cn++;
2408b7cb0e6Sstefano_zampini     if (cn) {
241a59f3c4dSstefano_zampini       if (cn != bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: invalid number of negative entries in block %D",bs,obs,cn);
242a59f3c4dSstefano_zampini       nid[i] = -1;
2438b7cb0e6Sstefano_zampini     } else {
244a59f3c4dSstefano_zampini       nid[i] = oid[i*bs]/bs;
24563fa5c83Sstefano_zampini     }
24663fa5c83Sstefano_zampini   }
247a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(mapping,&oid);CHKERRQ(ierr);
248a59f3c4dSstefano_zampini 
24963fa5c83Sstefano_zampini   mapping->n           = nn;
25063fa5c83Sstefano_zampini   mapping->bs          = bs;
25163fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
25263fa5c83Sstefano_zampini   mapping->indices     = nid;
253c9345713Sstefano_zampini   ierr                 = PetscFree(mapping->globals);CHKERRQ(ierr);
254c9345713Sstefano_zampini   mapping->globalstart = 0;
255c9345713Sstefano_zampini   mapping->globalend   = 0;
25663fa5c83Sstefano_zampini   PetscFunctionReturn(0);
25763fa5c83Sstefano_zampini }
25863fa5c83Sstefano_zampini 
25945b6f7e9SBarry Smith /*@
26045b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
26145b6f7e9SBarry Smith     ordering and a global parallel ordering.
26245b6f7e9SBarry Smith 
26345b6f7e9SBarry Smith     Not Collective
26445b6f7e9SBarry Smith 
26545b6f7e9SBarry Smith     Input Parameters:
26645b6f7e9SBarry Smith .   mapping - mapping data structure
26745b6f7e9SBarry Smith 
26845b6f7e9SBarry Smith     Output Parameter:
26945b6f7e9SBarry Smith .   bs - the blocksize
27045b6f7e9SBarry Smith 
27145b6f7e9SBarry Smith     Level: advanced
27245b6f7e9SBarry Smith 
27345b6f7e9SBarry Smith     Concepts: mapping^local to global
27445b6f7e9SBarry Smith 
27545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
27645b6f7e9SBarry Smith @*/
27745b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
27845b6f7e9SBarry Smith {
27945b6f7e9SBarry Smith   PetscFunctionBegin;
280cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
28145b6f7e9SBarry Smith   *bs = mapping->bs;
28245b6f7e9SBarry Smith   PetscFunctionReturn(0);
28345b6f7e9SBarry Smith }
28445b6f7e9SBarry Smith 
285ba5bb76aSSatish Balay /*@
28690f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
28790f02eecSBarry Smith     ordering and a global parallel ordering.
2882362add9SBarry Smith 
28989d82c54SBarry Smith     Not Collective, but communicator may have more than one process
290b9cd556bSLois Curfman McInnes 
2912362add9SBarry Smith     Input Parameters:
29289d82c54SBarry Smith +   comm - MPI communicator
293f0413b6fSBarry Smith .   bs - the block size
29428bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
29528bc9809SBarry Smith .   indices - the global index for each local element, these do not need to be in increasing order (sorted), these values should not be scaled (i.e. multiplied) by the blocksize bs
296d5ad8652SBarry Smith -   mode - see PetscCopyMode
2972362add9SBarry Smith 
298a997ad1aSLois Curfman McInnes     Output Parameter:
29990f02eecSBarry Smith .   mapping - new mapping data structure
3002362add9SBarry Smith 
301f0413b6fSBarry Smith     Notes: There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
302a997ad1aSLois Curfman McInnes     Level: advanced
303a997ad1aSLois Curfman McInnes 
304273d9f13SBarry Smith     Concepts: mapping^local to global
3052362add9SBarry Smith 
306d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
3072362add9SBarry Smith @*/
30860c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
3092362add9SBarry Smith {
3106849ba73SBarry Smith   PetscErrorCode ierr;
31132dcc486SBarry Smith   PetscInt       *in;
312b46b645bSBarry Smith 
313b46b645bSBarry Smith   PetscFunctionBegin;
31473911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
3154482741eSBarry Smith   PetscValidPointer(mapping,4);
316b46b645bSBarry Smith 
3170298fd71SBarry Smith   *mapping = NULL;
318607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
3192362add9SBarry Smith 
32073107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
32160c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
322d4bb536fSBarry Smith   (*mapping)->n             = n;
323f0413b6fSBarry Smith   (*mapping)->bs            = bs;
324268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
325268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
326268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
327268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
328268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
329d4bb536fSBarry Smith   /*
330d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
331d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
332d4bb536fSBarry Smith   */
333d4bb536fSBarry Smith   (*mapping)->globals = 0;
334*cd5a51dfSLawrence Mitchell   (*mapping)->globalht = 0;
335*cd5a51dfSLawrence Mitchell   (*mapping)->use_hash_table = PETSC_TRUE;
336d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
337785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
338d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
339d5ad8652SBarry Smith     (*mapping)->indices = in;
3406389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3416389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
3426389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
3436389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3446389a1a1SBarry Smith   }
34560c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
346d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
3473a40ed3dSBarry Smith   PetscFunctionReturn(0);
3482362add9SBarry Smith }
3492362add9SBarry Smith 
35090f02eecSBarry Smith /*@
35190f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
35290f02eecSBarry Smith    ordering and a global parallel ordering.
35390f02eecSBarry Smith 
3540f5bd95cSBarry Smith    Note Collective
355b9cd556bSLois Curfman McInnes 
35690f02eecSBarry Smith    Input Parameters:
35790f02eecSBarry Smith .  mapping - mapping data structure
35890f02eecSBarry Smith 
359a997ad1aSLois Curfman McInnes    Level: advanced
360a997ad1aSLois Curfman McInnes 
3613acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
36290f02eecSBarry Smith @*/
3636bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
36490f02eecSBarry Smith {
365dfbe8321SBarry Smith   PetscErrorCode ierr;
3665fd66863SKarl Rupp 
3673a40ed3dSBarry Smith   PetscFunctionBegin;
3686bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3696bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
370997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3716bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3726bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
373268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
374268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
375*cd5a51dfSLawrence Mitchell   PetscHashIDestroy((*mapping)->globalht);
376268a049cSStefano Zampini   if ((*mapping)->info_indices) {
377268a049cSStefano Zampini     PetscInt i;
378268a049cSStefano Zampini 
379268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
380268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
381268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
382268a049cSStefano Zampini     }
383268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
384268a049cSStefano Zampini   }
385d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
386992144d0SBarry Smith   *mapping = 0;
3873a40ed3dSBarry Smith   PetscFunctionReturn(0);
38890f02eecSBarry Smith }
38990f02eecSBarry Smith 
39090f02eecSBarry Smith /*@
3913acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3923acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3933acfe500SLois Curfman McInnes     context.
39490f02eecSBarry Smith 
395b9cd556bSLois Curfman McInnes     Not collective
396b9cd556bSLois Curfman McInnes 
39790f02eecSBarry Smith     Input Parameters:
398b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
399b9cd556bSLois Curfman McInnes -   is - index set in local numbering
40090f02eecSBarry Smith 
40190f02eecSBarry Smith     Output Parameters:
40290f02eecSBarry Smith .   newis - index set in global numbering
40390f02eecSBarry Smith 
404a997ad1aSLois Curfman McInnes     Level: advanced
405a997ad1aSLois Curfman McInnes 
406273d9f13SBarry Smith     Concepts: mapping^local to global
4073acfe500SLois Curfman McInnes 
40890f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
409d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
41090f02eecSBarry Smith @*/
4117087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
41290f02eecSBarry Smith {
4136849ba73SBarry Smith   PetscErrorCode ierr;
414e24637baSBarry Smith   PetscInt       n,*idxout;
4155d0c19d7SBarry Smith   const PetscInt *idxin;
4163a40ed3dSBarry Smith 
4173a40ed3dSBarry Smith   PetscFunctionBegin;
4180700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
4190700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
4204482741eSBarry Smith   PetscValidPointer(newis,3);
42190f02eecSBarry Smith 
4223b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
42390f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
424785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
425e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
4263b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
427543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4283a40ed3dSBarry Smith   PetscFunctionReturn(0);
42990f02eecSBarry Smith }
43090f02eecSBarry Smith 
431b89cb25eSSatish Balay /*@
4323acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4333acfe500SLois Curfman McInnes    and converts them to the global numbering.
43490f02eecSBarry Smith 
435b9cd556bSLois Curfman McInnes    Not collective
436b9cd556bSLois Curfman McInnes 
437bb25748dSBarry Smith    Input Parameters:
438b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
439bb25748dSBarry Smith .  N - number of integers
440b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
441bb25748dSBarry Smith 
442bb25748dSBarry Smith    Output Parameter:
443bb25748dSBarry Smith .  out - indices in global numbering
444bb25748dSBarry Smith 
445b9cd556bSLois Curfman McInnes    Notes:
446b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
447d4bb536fSBarry Smith 
448a997ad1aSLois Curfman McInnes    Level: advanced
449a997ad1aSLois Curfman McInnes 
45045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4510752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
452d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
453bb25748dSBarry Smith 
454273d9f13SBarry Smith     Concepts: mapping^local to global
455afcb2eb5SJed Brown @*/
456afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
457afcb2eb5SJed Brown {
458cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
45945b6f7e9SBarry Smith 
46045b6f7e9SBarry Smith   PetscFunctionBegin;
461cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
462cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
463cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
46445b6f7e9SBarry Smith   if (bs == 1) {
465cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
46645b6f7e9SBarry Smith     for (i=0; i<N; i++) {
46745b6f7e9SBarry Smith       if (in[i] < 0) {
46845b6f7e9SBarry Smith         out[i] = in[i];
46945b6f7e9SBarry Smith         continue;
47045b6f7e9SBarry Smith       }
471e24637baSBarry Smith       if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i);
47245b6f7e9SBarry Smith       out[i] = idx[in[i]];
47345b6f7e9SBarry Smith     }
47445b6f7e9SBarry Smith   } else {
475cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
47645b6f7e9SBarry Smith     for (i=0; i<N; i++) {
47745b6f7e9SBarry Smith       if (in[i] < 0) {
47845b6f7e9SBarry Smith         out[i] = in[i];
47945b6f7e9SBarry Smith         continue;
48045b6f7e9SBarry Smith       }
481e24637baSBarry Smith       if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i);
48245b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
48345b6f7e9SBarry Smith     }
48445b6f7e9SBarry Smith   }
48545b6f7e9SBarry Smith   PetscFunctionReturn(0);
48645b6f7e9SBarry Smith }
48745b6f7e9SBarry Smith 
48845b6f7e9SBarry Smith /*@
4896006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
49045b6f7e9SBarry Smith 
49145b6f7e9SBarry Smith    Not collective
49245b6f7e9SBarry Smith 
49345b6f7e9SBarry Smith    Input Parameters:
49445b6f7e9SBarry Smith +  mapping - the local to global mapping context
49545b6f7e9SBarry Smith .  N - number of integers
4966006e8d2SBarry Smith -  in - input indices in local block numbering
49745b6f7e9SBarry Smith 
49845b6f7e9SBarry Smith    Output Parameter:
4996006e8d2SBarry Smith .  out - indices in global block numbering
50045b6f7e9SBarry Smith 
50145b6f7e9SBarry Smith    Notes:
50245b6f7e9SBarry Smith    The in and out array parameters may be identical.
50345b6f7e9SBarry Smith 
5046006e8d2SBarry Smith    Example:
5056006e8d2SBarry Smith      If the index values are {0,1,6,7} set with a call to ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,2,2,{0,3}) then the mapping applied to 0
5066006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
5076006e8d2SBarry Smith 
50845b6f7e9SBarry Smith    Level: advanced
50945b6f7e9SBarry Smith 
51045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
51145b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
51245b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
51345b6f7e9SBarry Smith 
51445b6f7e9SBarry Smith     Concepts: mapping^local to global
51545b6f7e9SBarry Smith @*/
51645b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
51745b6f7e9SBarry Smith {
518cbc1caf0SMatthew G. Knepley 
519cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
520cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
521cbc1caf0SMatthew G. Knepley   {
522afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
523afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
524d4bb536fSBarry Smith 
525afcb2eb5SJed Brown     for (i=0; i<N; i++) {
526afcb2eb5SJed Brown       if (in[i] < 0) {
527afcb2eb5SJed Brown         out[i] = in[i];
528afcb2eb5SJed Brown         continue;
529afcb2eb5SJed Brown       }
530e24637baSBarry Smith       if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local block index %D too large %D (max) at %D",in[i],Nmax-1,i);
531afcb2eb5SJed Brown       out[i] = idx[in[i]];
532afcb2eb5SJed Brown     }
533cbc1caf0SMatthew G. Knepley   }
534afcb2eb5SJed Brown   PetscFunctionReturn(0);
535afcb2eb5SJed Brown }
536d4bb536fSBarry Smith 
537d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
538d4bb536fSBarry Smith 
539d4bb536fSBarry Smith /*
540d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
541d4bb536fSBarry Smith */
5426849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
543d4bb536fSBarry Smith {
5446849ba73SBarry Smith   PetscErrorCode ierr;
54532dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
546d4bb536fSBarry Smith 
5473a40ed3dSBarry Smith   PetscFunctionBegin;
548*cd5a51dfSLawrence Mitchell   if (mapping->use_hash_table && mapping->globalht) PetscFunctionReturn(0);
549*cd5a51dfSLawrence Mitchell   else if (mapping->globals) PetscFunctionReturn(0);
550d4bb536fSBarry Smith   end   = 0;
551ec268f7cSJed Brown   start = PETSC_MAX_INT;
552d4bb536fSBarry Smith 
553d4bb536fSBarry Smith   for (i=0; i<n; i++) {
554d4bb536fSBarry Smith     if (idx[i] < 0) continue;
555d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
556d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
557d4bb536fSBarry Smith   }
558d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
559d4bb536fSBarry Smith   mapping->globalstart = start;
560d4bb536fSBarry Smith   mapping->globalend   = end;
561d4bb536fSBarry Smith 
562*cd5a51dfSLawrence Mitchell   if (mapping->use_hash_table) {
563*cd5a51dfSLawrence Mitchell     PetscHashICreate(mapping->globalht);
564*cd5a51dfSLawrence Mitchell     for (i=0; i<n; i++ ) {
565*cd5a51dfSLawrence Mitchell       if (idx[i] < 0) continue;
566*cd5a51dfSLawrence Mitchell       PetscHashIAdd(mapping->globalht, idx[i], i);
567*cd5a51dfSLawrence Mitchell     }
568*cd5a51dfSLawrence Mitchell     ierr = PetscLogObjectMemory((PetscObject)mapping,2*n*sizeof(PetscInt));CHKERRQ(ierr);
569*cd5a51dfSLawrence Mitchell   } else {
570854ce69bSBarry Smith     ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
571b0a32e0cSBarry Smith     mapping->globals = globals;
572f6e5521dSKarl Rupp     for (i=0; i<end-start+1; i++) globals[i] = -1;
573d4bb536fSBarry Smith     for (i=0; i<n; i++) {
574d4bb536fSBarry Smith       if (idx[i] < 0) continue;
575d4bb536fSBarry Smith       globals[idx[i] - start] = i;
576d4bb536fSBarry Smith     }
577d4bb536fSBarry Smith 
5783bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
579*cd5a51dfSLawrence Mitchell   }
5803a40ed3dSBarry Smith   PetscFunctionReturn(0);
581d4bb536fSBarry Smith }
582d4bb536fSBarry Smith 
583d4bb536fSBarry Smith /*@
584a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
585a997ad1aSLois Curfman McInnes     specified with a global numbering.
586d4bb536fSBarry Smith 
587b9cd556bSLois Curfman McInnes     Not collective
588b9cd556bSLois Curfman McInnes 
589d4bb536fSBarry Smith     Input Parameters:
590b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
591d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
592d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
593d4bb536fSBarry Smith .   n - number of global indices to map
594b9cd556bSLois Curfman McInnes -   idx - global indices to map
595d4bb536fSBarry Smith 
596d4bb536fSBarry Smith     Output Parameters:
597b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
598b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
599e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
6000298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
601e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
602e182c471SBarry Smith              a second time to set the values.
603d4bb536fSBarry Smith 
604b9cd556bSLois Curfman McInnes     Notes:
6050298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
606d4bb536fSBarry Smith 
6070f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6080f5bd95cSBarry Smith     array to compute these.
6090f5bd95cSBarry Smith 
610a997ad1aSLois Curfman McInnes     Level: advanced
611a997ad1aSLois Curfman McInnes 
61232fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
61332fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
61432fd6b96SBarry Smith 
615273d9f13SBarry Smith     Concepts: mapping^global to local
616d4bb536fSBarry Smith 
6179d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
618d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
619d4bb536fSBarry Smith @*/
6207087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
62132dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
622d4bb536fSBarry Smith {
623*cd5a51dfSLawrence Mitchell   PetscInt       i,*globals,nf = 0,tmp,start,end,bs,local;
624*cd5a51dfSLawrence Mitchell   const PetscBool use_hash_table = mapping->use_hash_table;
6259d90f715SBarry Smith   PetscErrorCode ierr;
6269d90f715SBarry Smith 
6279d90f715SBarry Smith   PetscFunctionBegin;
6289d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6299d90f715SBarry Smith   ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
6309d90f715SBarry Smith   globals = mapping->globals;
6319d90f715SBarry Smith   start   = mapping->globalstart;
6329d90f715SBarry Smith   end     = mapping->globalend;
6339d90f715SBarry Smith   bs      = mapping->bs;
6349d90f715SBarry Smith 
635*cd5a51dfSLawrence Mitchell #define GTOL(g, local) do {                        \
636*cd5a51dfSLawrence Mitchell     if (use_hash_table) {                          \
637*cd5a51dfSLawrence Mitchell       PetscHashIMap(mapping->globalht,g/bs,local); \
638*cd5a51dfSLawrence Mitchell     } else {                                       \
639*cd5a51dfSLawrence Mitchell       local = globals[g/bs - start];               \
640*cd5a51dfSLawrence Mitchell     }                                              \
641*cd5a51dfSLawrence Mitchell     local = bs*local + (g % bs);                   \
642*cd5a51dfSLawrence Mitchell   } while (0)
643*cd5a51dfSLawrence Mitchell 
6449d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
6459d90f715SBarry Smith     if (idxout) {
6469d90f715SBarry Smith       for (i=0; i<n; i++) {
6479d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
6489d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
649663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
650*cd5a51dfSLawrence Mitchell         else                              GTOL(idx[i], local);
6519d90f715SBarry Smith       }
6529d90f715SBarry Smith     }
6539d90f715SBarry Smith     if (nout) *nout = n;
6549d90f715SBarry Smith   } else {
6559d90f715SBarry Smith     if (idxout) {
6569d90f715SBarry Smith       for (i=0; i<n; i++) {
6579d90f715SBarry Smith         if (idx[i] < 0) continue;
6589d90f715SBarry Smith         if (idx[i] < bs*start) continue;
659663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
660*cd5a51dfSLawrence Mitchell         GTOL(idx[i], tmp);
6619d90f715SBarry Smith         if (tmp < 0) continue;
6629d90f715SBarry Smith         idxout[nf++] = tmp;
6639d90f715SBarry Smith       }
6649d90f715SBarry Smith     } else {
6659d90f715SBarry Smith       for (i=0; i<n; i++) {
6669d90f715SBarry Smith         if (idx[i] < 0) continue;
6679d90f715SBarry Smith         if (idx[i] < bs*start) continue;
668663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
669*cd5a51dfSLawrence Mitchell         GTOL(idx[i], tmp);
6709d90f715SBarry Smith         if (tmp < 0) continue;
6719d90f715SBarry Smith         nf++;
6729d90f715SBarry Smith       }
6739d90f715SBarry Smith     }
6749d90f715SBarry Smith     if (nout) *nout = nf;
6759d90f715SBarry Smith   }
676*cd5a51dfSLawrence Mitchell #undef GTOL
6779d90f715SBarry Smith   PetscFunctionReturn(0);
6789d90f715SBarry Smith }
6799d90f715SBarry Smith 
680d4fe737eSStefano Zampini /*@
681d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
682d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
683d4fe737eSStefano Zampini     context.
684d4fe737eSStefano Zampini 
685d4fe737eSStefano Zampini     Not collective
686d4fe737eSStefano Zampini 
687d4fe737eSStefano Zampini     Input Parameters:
688d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
689d4fe737eSStefano Zampini -   is - index set in global numbering
690d4fe737eSStefano Zampini 
691d4fe737eSStefano Zampini     Output Parameters:
692d4fe737eSStefano Zampini .   newis - index set in local numbering
693d4fe737eSStefano Zampini 
694d4fe737eSStefano Zampini     Level: advanced
695d4fe737eSStefano Zampini 
696d4fe737eSStefano Zampini     Concepts: mapping^local to global
697d4fe737eSStefano Zampini 
698d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
699d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
700d4fe737eSStefano Zampini @*/
701d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
702d4fe737eSStefano Zampini {
703d4fe737eSStefano Zampini   PetscErrorCode ierr;
704d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
705d4fe737eSStefano Zampini   const PetscInt *idxin;
706d4fe737eSStefano Zampini 
707d4fe737eSStefano Zampini   PetscFunctionBegin;
708d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
709d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
710d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
711d4fe737eSStefano Zampini 
712d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
713d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
714d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
715d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
716d4fe737eSStefano Zampini   } else {
717d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
718d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
719d4fe737eSStefano Zampini   }
720d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
721d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
722d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
723d4fe737eSStefano Zampini   PetscFunctionReturn(0);
724d4fe737eSStefano Zampini }
725d4fe737eSStefano Zampini 
7269d90f715SBarry Smith /*@
7279d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
7289d90f715SBarry Smith     specified with a block global numbering.
7299d90f715SBarry Smith 
7309d90f715SBarry Smith     Not collective
7319d90f715SBarry Smith 
7329d90f715SBarry Smith     Input Parameters:
7339d90f715SBarry Smith +   mapping - mapping between local and global numbering
7349d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
7359d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
7369d90f715SBarry Smith .   n - number of global indices to map
7379d90f715SBarry Smith -   idx - global indices to map
7389d90f715SBarry Smith 
7399d90f715SBarry Smith     Output Parameters:
7409d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
7419d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
7429d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
7439d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
7449d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
7459d90f715SBarry Smith              a second time to set the values.
7469d90f715SBarry Smith 
7479d90f715SBarry Smith     Notes:
7489d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
7499d90f715SBarry Smith 
7509d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
7519d90f715SBarry Smith     array to compute these.
7529d90f715SBarry Smith 
7539d90f715SBarry Smith     Level: advanced
7549d90f715SBarry Smith 
7559d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
7569d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
7579d90f715SBarry Smith 
7589d90f715SBarry Smith     Concepts: mapping^global to local
7599d90f715SBarry Smith 
7609d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7619d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7629d90f715SBarry Smith @*/
7639d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7649d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7659d90f715SBarry Smith {
76632dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
767*cd5a51dfSLawrence Mitchell   const PetscBool use_hash_table = mapping->use_hash_table;
7686849ba73SBarry Smith   PetscErrorCode ierr;
769d4bb536fSBarry Smith 
7703a40ed3dSBarry Smith   PetscFunctionBegin;
7710700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
772d4bb536fSBarry Smith   ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
773d4bb536fSBarry Smith   globals = mapping->globals;
774d4bb536fSBarry Smith   start   = mapping->globalstart;
775d4bb536fSBarry Smith   end     = mapping->globalend;
776d4bb536fSBarry Smith 
777*cd5a51dfSLawrence Mitchell #define GTOL(g, local) do {                     \
778*cd5a51dfSLawrence Mitchell     if (use_hash_table) {                       \
779*cd5a51dfSLawrence Mitchell       PetscHashIMap(mapping->globalht,g,local); \
780*cd5a51dfSLawrence Mitchell     } else {                                    \
781*cd5a51dfSLawrence Mitchell       local = globals[g - start];               \
782*cd5a51dfSLawrence Mitchell     }                                           \
783*cd5a51dfSLawrence Mitchell   } while (0)
784*cd5a51dfSLawrence Mitchell 
785d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
786d4bb536fSBarry Smith     if (idxout) {
787d4bb536fSBarry Smith       for (i=0; i<n; i++) {
788d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
789d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
790d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
791*cd5a51dfSLawrence Mitchell         else                     GTOL(idx[i], idxout[i]);
792d4bb536fSBarry Smith       }
793d4bb536fSBarry Smith     }
794d4bb536fSBarry Smith     if (nout) *nout = n;
795d4bb536fSBarry Smith   } else {
796d4bb536fSBarry Smith     if (idxout) {
797d4bb536fSBarry Smith       for (i=0; i<n; i++) {
798d4bb536fSBarry Smith         if (idx[i] < 0) continue;
799d4bb536fSBarry Smith         if (idx[i] < start) continue;
800d4bb536fSBarry Smith         if (idx[i] > end) continue;
801*cd5a51dfSLawrence Mitchell         GTOL(idx[i], tmp);
802d4bb536fSBarry Smith         if (tmp < 0) continue;
803d4bb536fSBarry Smith         idxout[nf++] = tmp;
804d4bb536fSBarry Smith       }
805d4bb536fSBarry Smith     } else {
806d4bb536fSBarry Smith       for (i=0; i<n; i++) {
807d4bb536fSBarry Smith         if (idx[i] < 0) continue;
808d4bb536fSBarry Smith         if (idx[i] < start) continue;
809d4bb536fSBarry Smith         if (idx[i] > end) continue;
810*cd5a51dfSLawrence Mitchell         GTOL(idx[i], tmp);
811d4bb536fSBarry Smith         if (tmp < 0) continue;
812d4bb536fSBarry Smith         nf++;
813d4bb536fSBarry Smith       }
814d4bb536fSBarry Smith     }
815d4bb536fSBarry Smith     if (nout) *nout = nf;
816d4bb536fSBarry Smith   }
817*cd5a51dfSLawrence Mitchell #undef GTOL
8183a40ed3dSBarry Smith   PetscFunctionReturn(0);
819d4bb536fSBarry Smith }
82090f02eecSBarry Smith 
82189d82c54SBarry Smith /*@C
8226a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
82389d82c54SBarry Smith      each index shared by more than one processor
82489d82c54SBarry Smith 
82589d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
82689d82c54SBarry Smith 
82789d82c54SBarry Smith     Input Parameters:
82889d82c54SBarry Smith .   mapping - the mapping from local to global indexing
82989d82c54SBarry Smith 
83089d82c54SBarry Smith     Output Parameter:
83189d82c54SBarry Smith +   nproc - number of processors that are connected to this one
83289d82c54SBarry Smith .   proc - neighboring processors
83307b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
8343463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
83589d82c54SBarry Smith 
83689d82c54SBarry Smith     Level: advanced
83789d82c54SBarry Smith 
838273d9f13SBarry Smith     Concepts: mapping^local to global
83989d82c54SBarry Smith 
8402cfcea29SBarry Smith     Fortran Usage:
8412cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
8422cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
8432cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
8442cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
8452cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
8462cfcea29SBarry Smith 
8472cfcea29SBarry Smith 
84807b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
84907b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
85089d82c54SBarry Smith @*/
8516a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
85289d82c54SBarry Smith {
8536849ba73SBarry Smith   PetscErrorCode ierr;
854268a049cSStefano Zampini 
855268a049cSStefano Zampini   PetscFunctionBegin;
856268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
857268a049cSStefano Zampini   if (mapping->info_cached) {
858268a049cSStefano Zampini     *nproc = mapping->info_nproc;
859268a049cSStefano Zampini     *procs = mapping->info_procs;
860268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
861268a049cSStefano Zampini     *indices = mapping->info_indices;
862268a049cSStefano Zampini   } else {
863268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
864268a049cSStefano Zampini   }
865268a049cSStefano Zampini   PetscFunctionReturn(0);
866268a049cSStefano Zampini }
867268a049cSStefano Zampini 
868268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
869268a049cSStefano Zampini {
870268a049cSStefano Zampini   PetscErrorCode ierr;
87197f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
87232dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
87332dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
87497f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
87532dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
87632dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
87789d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
87830dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
879ce94432eSBarry Smith   MPI_Comm       comm;
880ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
88189d82c54SBarry Smith 
88289d82c54SBarry Smith   PetscFunctionBegin;
883ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
88424cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
88524cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
88624cf384cSBarry Smith   if (size == 1) {
88724cf384cSBarry Smith     *nproc         = 0;
8880298fd71SBarry Smith     *procs         = NULL;
88995dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
8901e2105dcSBarry Smith     (*numprocs)[0] = 0;
89195dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
8920298fd71SBarry Smith     (*indices)[0]  = NULL;
893268a049cSStefano Zampini     /* save info for reuse */
894268a049cSStefano Zampini     mapping->info_nproc = *nproc;
895268a049cSStefano Zampini     mapping->info_procs = *procs;
896268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
897268a049cSStefano Zampini     mapping->info_indices = *indices;
898268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
89924cf384cSBarry Smith     PetscFunctionReturn(0);
90024cf384cSBarry Smith   }
90124cf384cSBarry Smith 
902c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
90307b52d57SBarry Smith 
9043677ff5aSBarry Smith   /*
9056a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
9063677ff5aSBarry Smith 
9073677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
9083677ff5aSBarry Smith            numbering, just for this routine.
9093677ff5aSBarry Smith 
9103677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
9113677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
9123677ff5aSBarry Smith 
9133677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
9143677ff5aSBarry Smith 
9153677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
9163677ff5aSBarry Smith            local subdomain
9173677ff5aSBarry Smith   */
91824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
91924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
92024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
92189d82c54SBarry Smith 
92289d82c54SBarry Smith   for (i=0; i<n; i++) {
92389d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
92489d82c54SBarry Smith   }
925b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
92678058e43SBarry Smith   Ng++;
92789d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
92889d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
929bc8ff85bSBarry Smith   scale  = Ng/size + 1;
930a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
931caba0dd0SBarry Smith   rstart = scale*rank;
93289d82c54SBarry Smith 
93389d82c54SBarry Smith   /* determine ownership ranges of global indices */
934785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
93532dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
93689d82c54SBarry Smith 
93789d82c54SBarry Smith   /* determine owners of each local node  */
938785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
93989d82c54SBarry Smith   for (i=0; i<n; i++) {
9403677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
94127c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
9423677ff5aSBarry Smith     owner[i]         = proc;
94327c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
94489d82c54SBarry Smith   }
94527c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
9467904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
94789d82c54SBarry Smith 
94889d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
94927c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9507904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
95189d82c54SBarry Smith 
95289d82c54SBarry Smith   /* post receives for owned rows */
953785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
954854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
95589d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
95632dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
95789d82c54SBarry Smith   }
95889d82c54SBarry Smith 
95989d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
960854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
961854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
96289d82c54SBarry Smith   starts[0] = 0;
963f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
96489d82c54SBarry Smith   for (i=0; i<n; i++) {
96589d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
96630dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
96789d82c54SBarry Smith   }
96889d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
96989d82c54SBarry Smith   starts[0] = 0;
970f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
97189d82c54SBarry Smith 
97289d82c54SBarry Smith   /* send the messages */
973854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
974854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
97589d82c54SBarry Smith   cnt = 0;
97689d82c54SBarry Smith   for (i=0; i<size; i++) {
97727c402fcSBarry Smith     if (nprocs[2*i]) {
97832dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
97930dcb7c9SBarry Smith       dest[cnt] = i;
98089d82c54SBarry Smith       cnt++;
98189d82c54SBarry Smith     }
98289d82c54SBarry Smith   }
98389d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
98489d82c54SBarry Smith 
98589d82c54SBarry Smith   /* wait on receives */
986854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
987854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
98889d82c54SBarry Smith   cnt  = nrecvs;
989854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
99032dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
99189d82c54SBarry Smith   while (cnt) {
99289d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
99389d82c54SBarry Smith     /* unpack receives into our local space */
99432dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
99589d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
99630dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
997caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
99830dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
99989d82c54SBarry Smith     cnt--;
100089d82c54SBarry Smith   }
100189d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
100289d82c54SBarry Smith 
100330dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1004bc8ff85bSBarry Smith   nowned  = 0;
1005bc8ff85bSBarry Smith   nownedm = 0;
1006bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
1007bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
1008bc8ff85bSBarry Smith   }
1009bc8ff85bSBarry Smith 
1010bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1011854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1012854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1013bc8ff85bSBarry Smith   starts[0] = 0;
1014bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1015bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1016bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1017bc8ff85bSBarry Smith   }
1018bc8ff85bSBarry Smith 
101930dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1020bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1021bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
102230dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1023f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1024bc8ff85bSBarry Smith     }
1025bc8ff85bSBarry Smith   }
1026bc8ff85bSBarry Smith 
102707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
102830dcb7c9SBarry Smith     starts[0] = 0;
102930dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
103030dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
103130dcb7c9SBarry Smith       else starts[i] = starts[i-1];
103230dcb7c9SBarry Smith     }
103330dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
103430dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
10357904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
103630dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
10377904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
103830dcb7c9SBarry Smith         }
103930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
104030dcb7c9SBarry Smith       }
104130dcb7c9SBarry Smith     }
10420ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
104307b52d57SBarry Smith   } /* -----------------------------------  */
104430dcb7c9SBarry Smith 
10453677ff5aSBarry Smith   /* wait on original sends */
10463a96401aSBarry Smith   if (nsends) {
1047785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
10483a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10493a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10503a96401aSBarry Smith   }
105189d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10523a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
10533677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
10543677ff5aSBarry Smith 
10553677ff5aSBarry Smith   /* pack messages to send back to local owners */
105630dcb7c9SBarry Smith   starts[0] = 0;
105730dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
105830dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
105930dcb7c9SBarry Smith     else starts[i] = starts[i-1];
106030dcb7c9SBarry Smith   }
106130dcb7c9SBarry Smith   nsends2 = nrecvs;
1062854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
106330dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
106430dcb7c9SBarry Smith     nprocs[i] = 1;
106530dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
106630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1067f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
106830dcb7c9SBarry Smith     }
106930dcb7c9SBarry Smith   }
1070f6e5521dSKarl Rupp   nt = 0;
1071f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1072f6e5521dSKarl Rupp 
1073854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1074854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1075f6e5521dSKarl Rupp 
1076f6e5521dSKarl Rupp   starts2[0] = 0;
1077f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
107830dcb7c9SBarry Smith   /*
107930dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
108030dcb7c9SBarry Smith        (0) the number of nodes being sent back
108130dcb7c9SBarry Smith        (1) the local node number,
108230dcb7c9SBarry Smith        (2) the number of processors sharing it,
108330dcb7c9SBarry Smith        (3) the processors sharing it
108430dcb7c9SBarry Smith   */
108530dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
108630dcb7c9SBarry Smith     cnt = 1;
108730dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
108830dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
108930dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
109030dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
109130dcb7c9SBarry Smith         sends2[starts2[i]]++;
109230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
109330dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
109432dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
109530dcb7c9SBarry Smith         cnt += nownedsenders[node];
109630dcb7c9SBarry Smith       }
109730dcb7c9SBarry Smith     }
109830dcb7c9SBarry Smith   }
109930dcb7c9SBarry Smith 
110030dcb7c9SBarry Smith   /* receive the message lengths */
110130dcb7c9SBarry Smith   nrecvs2 = nsends;
1102854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1103854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1104854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
110530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1106d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
110730dcb7c9SBarry Smith   }
1108d44834fbSBarry Smith 
11098a8e0b3aSBarry Smith   /* send the message lengths */
11108a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
11118a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
11128a8e0b3aSBarry Smith   }
11138a8e0b3aSBarry Smith 
1114d44834fbSBarry Smith   /* wait on receives of lens */
11150c468ba9SBarry Smith   if (nrecvs2) {
1116785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1117d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1118d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11190c468ba9SBarry Smith   }
1120a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1121d44834fbSBarry Smith 
112230dcb7c9SBarry Smith   starts3[0] = 0;
1123d44834fbSBarry Smith   nt         = 0;
112430dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
112530dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1126d44834fbSBarry Smith     nt          += lens2[i];
112730dcb7c9SBarry Smith   }
112876466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1129d44834fbSBarry Smith 
1130854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1131854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
113252b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
113332dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
113430dcb7c9SBarry Smith   }
113530dcb7c9SBarry Smith 
113630dcb7c9SBarry Smith   /* send the messages */
1137854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
113830dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
113932dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
114030dcb7c9SBarry Smith   }
114130dcb7c9SBarry Smith 
114230dcb7c9SBarry Smith   /* wait on receives */
11430c468ba9SBarry Smith   if (nrecvs2) {
1144785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
114530dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
114630dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11470c468ba9SBarry Smith   }
114830dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
114930dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
115030dcb7c9SBarry Smith 
115107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
115230dcb7c9SBarry Smith     cnt = 0;
115330dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
115430dcb7c9SBarry Smith       nt = recvs2[cnt++];
115530dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
11567904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
115730dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
11587904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
115930dcb7c9SBarry Smith         }
116030dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
116130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
116230dcb7c9SBarry Smith       }
116330dcb7c9SBarry Smith     }
11640ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
116507b52d57SBarry Smith   } /* -----------------------------------  */
116630dcb7c9SBarry Smith 
116730dcb7c9SBarry Smith   /* count number subdomains for each local node */
1168785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
116932dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
117030dcb7c9SBarry Smith   cnt  = 0;
117130dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
117230dcb7c9SBarry Smith     nt = recvs2[cnt++];
117330dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1174f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
117530dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
117630dcb7c9SBarry Smith     }
117730dcb7c9SBarry Smith   }
117830dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
117930dcb7c9SBarry Smith   *nproc    = nt;
1180854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1181854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1182854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
11830298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1184785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
118530dcb7c9SBarry Smith   cnt  = 0;
118630dcb7c9SBarry Smith   for (i=0; i<size; i++) {
118730dcb7c9SBarry Smith     if (nprocs[i] > 0) {
118830dcb7c9SBarry Smith       bprocs[i]        = cnt;
118930dcb7c9SBarry Smith       (*procs)[cnt]    = i;
119030dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1191785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
119230dcb7c9SBarry Smith       cnt++;
119330dcb7c9SBarry Smith     }
119430dcb7c9SBarry Smith   }
119530dcb7c9SBarry Smith 
119630dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
119732dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
119830dcb7c9SBarry Smith   cnt  = 0;
119930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
120030dcb7c9SBarry Smith     nt = recvs2[cnt++];
120130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1202f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
120330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
120430dcb7c9SBarry Smith     }
120530dcb7c9SBarry Smith   }
120630dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
120707b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
120830dcb7c9SBarry Smith 
120907b52d57SBarry Smith   /* sort the node indexing by their global numbers */
121007b52d57SBarry Smith   nt = *nproc;
121107b52d57SBarry Smith   for (i=0; i<nt; i++) {
1212854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1213f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
121407b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
121507b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
121607b52d57SBarry Smith   }
121707b52d57SBarry Smith 
121807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
121930dcb7c9SBarry Smith     nt = *nproc;
122030dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
12217904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
122230dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
12237904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
122430dcb7c9SBarry Smith       }
122530dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
122630dcb7c9SBarry Smith     }
12270ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
122807b52d57SBarry Smith   } /* -----------------------------------  */
122930dcb7c9SBarry Smith 
123030dcb7c9SBarry Smith   /* wait on sends */
123130dcb7c9SBarry Smith   if (nsends2) {
1232785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
123330dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
123430dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
123530dcb7c9SBarry Smith   }
123630dcb7c9SBarry Smith 
123730dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
123830dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
123930dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12403677ff5aSBarry Smith 
1241bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1242bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1243bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
124430dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
124530dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
124689d82c54SBarry Smith 
124789d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
124897f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
124989d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
12503a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
125130dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
125224cf384cSBarry Smith 
125324cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
125424cf384cSBarry Smith   first_procs    = (*procs)[0];
125524cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
125624cf384cSBarry Smith   first_indices  = (*indices)[0];
125724cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
125824cf384cSBarry Smith     if ((*procs)[i] == rank) {
125924cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
126024cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
126124cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
126224cf384cSBarry Smith       (*procs)[i]    = first_procs;
126324cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
126424cf384cSBarry Smith       (*indices)[i]  = first_indices;
126524cf384cSBarry Smith       break;
126624cf384cSBarry Smith     }
126724cf384cSBarry Smith   }
1268268a049cSStefano Zampini 
1269268a049cSStefano Zampini   /* save info for reuse */
1270268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1271268a049cSStefano Zampini   mapping->info_procs = *procs;
1272268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1273268a049cSStefano Zampini   mapping->info_indices = *indices;
1274268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
127589d82c54SBarry Smith   PetscFunctionReturn(0);
127689d82c54SBarry Smith }
127789d82c54SBarry Smith 
12786a818285SBarry Smith /*@C
12796a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
12806a818285SBarry Smith 
12816a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12826a818285SBarry Smith 
12836a818285SBarry Smith     Input Parameters:
12846a818285SBarry Smith .   mapping - the mapping from local to global indexing
12856a818285SBarry Smith 
12866a818285SBarry Smith     Output Parameter:
12876a818285SBarry Smith +   nproc - number of processors that are connected to this one
12886a818285SBarry Smith .   proc - neighboring processors
12896a818285SBarry Smith .   numproc - number of indices for each processor
12906a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12916a818285SBarry Smith 
12926a818285SBarry Smith     Level: advanced
12936a818285SBarry Smith 
12946a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12956a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
12966a818285SBarry Smith @*/
12976a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12986a818285SBarry Smith {
12996a818285SBarry Smith   PetscErrorCode ierr;
13006a818285SBarry Smith 
13016a818285SBarry Smith   PetscFunctionBegin;
1302cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1303268a049cSStefano Zampini   if (mapping->info_free) {
13046a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
13056a818285SBarry Smith     if (*indices) {
1306268a049cSStefano Zampini       PetscInt i;
1307268a049cSStefano Zampini 
13086a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
13096a818285SBarry Smith       for (i=1; i<*nproc; i++) {
13106a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
13116a818285SBarry Smith       }
13126a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
13136a818285SBarry Smith     }
1314268a049cSStefano Zampini   }
1315268a049cSStefano Zampini   *nproc = 0;
1316268a049cSStefano Zampini   *procs = NULL;
1317268a049cSStefano Zampini   *numprocs = NULL;
1318268a049cSStefano Zampini   *indices = NULL;
13196a818285SBarry Smith   PetscFunctionReturn(0);
13206a818285SBarry Smith }
13216a818285SBarry Smith 
13226a818285SBarry Smith /*@C
13236a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
13246a818285SBarry Smith      each index shared by more than one processor
13256a818285SBarry Smith 
13266a818285SBarry Smith     Collective on ISLocalToGlobalMapping
13276a818285SBarry Smith 
13286a818285SBarry Smith     Input Parameters:
13296a818285SBarry Smith .   mapping - the mapping from local to global indexing
13306a818285SBarry Smith 
13316a818285SBarry Smith     Output Parameter:
13326a818285SBarry Smith +   nproc - number of processors that are connected to this one
13336a818285SBarry Smith .   proc - neighboring processors
13346a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
13356a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
13366a818285SBarry Smith 
13376a818285SBarry Smith     Level: advanced
13386a818285SBarry Smith 
13396a818285SBarry Smith     Concepts: mapping^local to global
13406a818285SBarry Smith 
13416a818285SBarry Smith     Fortran Usage:
13426a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
13436a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
13446a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
13456a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
13466a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
13476a818285SBarry Smith 
13486a818285SBarry Smith 
13496a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13506a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
13516a818285SBarry Smith @*/
13526a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13536a818285SBarry Smith {
13546a818285SBarry Smith   PetscErrorCode ierr;
1355268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
13566a818285SBarry Smith 
13576a818285SBarry Smith   PetscFunctionBegin;
13586a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1359268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1360268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1361732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1362268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13636a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1364268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1365268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13666a818285SBarry Smith         for (k=0; k<bs; k++) {
13676a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13686a818285SBarry Smith         }
13696a818285SBarry Smith       }
1370268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13716a818285SBarry Smith     }
1372268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1373268a049cSStefano Zampini   } else {
1374268a049cSStefano Zampini     *numprocs = bnumprocs;
1375268a049cSStefano Zampini     *indices  = bindices;
13766a818285SBarry Smith   }
13776a818285SBarry Smith   PetscFunctionReturn(0);
13786a818285SBarry Smith }
13796a818285SBarry Smith 
138007b52d57SBarry Smith /*@C
138107b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
138289d82c54SBarry Smith 
138307b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
138407b52d57SBarry Smith 
138507b52d57SBarry Smith     Input Parameters:
138607b52d57SBarry Smith .   mapping - the mapping from local to global indexing
138707b52d57SBarry Smith 
138807b52d57SBarry Smith     Output Parameter:
138907b52d57SBarry Smith +   nproc - number of processors that are connected to this one
139007b52d57SBarry Smith .   proc - neighboring processors
139107b52d57SBarry Smith .   numproc - number of indices for each processor
139207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
139307b52d57SBarry Smith 
139407b52d57SBarry Smith     Level: advanced
139507b52d57SBarry Smith 
139607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
139707b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
139807b52d57SBarry Smith @*/
13997087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
140007b52d57SBarry Smith {
14016849ba73SBarry Smith   PetscErrorCode ierr;
140207b52d57SBarry Smith 
140307b52d57SBarry Smith   PetscFunctionBegin;
14046a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
140507b52d57SBarry Smith   PetscFunctionReturn(0);
140607b52d57SBarry Smith }
140786994e45SJed Brown 
140886994e45SJed Brown /*@C
1409107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
141086994e45SJed Brown 
141186994e45SJed Brown    Not Collective
141286994e45SJed Brown 
141386994e45SJed Brown    Input Arguments:
141486994e45SJed Brown . ltog - local to global mapping
141586994e45SJed Brown 
141686994e45SJed Brown    Output Arguments:
1417565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
141886994e45SJed Brown 
141986994e45SJed Brown    Level: advanced
142086994e45SJed Brown 
1421107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1422107e9a97SBarry Smith 
1423107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
142486994e45SJed Brown @*/
14257087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
142686994e45SJed Brown {
142786994e45SJed Brown   PetscFunctionBegin;
142886994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
142986994e45SJed Brown   PetscValidPointer(array,2);
143045b6f7e9SBarry Smith   if (ltog->bs == 1) {
143186994e45SJed Brown     *array = ltog->indices;
143245b6f7e9SBarry Smith   } else {
143345b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
143445b6f7e9SBarry Smith     const PetscInt *ii;
143545b6f7e9SBarry Smith     PetscErrorCode ierr;
143645b6f7e9SBarry Smith 
143745b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
143845b6f7e9SBarry Smith     *array = jj;
143945b6f7e9SBarry Smith     k    = 0;
144045b6f7e9SBarry Smith     ii   = ltog->indices;
144145b6f7e9SBarry Smith     for (i=0; i<n; i++)
144245b6f7e9SBarry Smith       for (j=0; j<bs; j++)
144345b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
144445b6f7e9SBarry Smith   }
144586994e45SJed Brown   PetscFunctionReturn(0);
144686994e45SJed Brown }
144786994e45SJed Brown 
144886994e45SJed Brown /*@C
1449193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
145086994e45SJed Brown 
145186994e45SJed Brown    Not Collective
145286994e45SJed Brown 
145386994e45SJed Brown    Input Arguments:
145486994e45SJed Brown + ltog - local to global mapping
145586994e45SJed Brown - array - array of indices
145686994e45SJed Brown 
145786994e45SJed Brown    Level: advanced
145886994e45SJed Brown 
145986994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
146086994e45SJed Brown @*/
14617087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
146286994e45SJed Brown {
146386994e45SJed Brown   PetscFunctionBegin;
146486994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
146586994e45SJed Brown   PetscValidPointer(array,2);
146645b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
146745b6f7e9SBarry Smith 
146845b6f7e9SBarry Smith   if (ltog->bs > 1) {
146945b6f7e9SBarry Smith     PetscErrorCode ierr;
147045b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
147145b6f7e9SBarry Smith   }
147245b6f7e9SBarry Smith   PetscFunctionReturn(0);
147345b6f7e9SBarry Smith }
147445b6f7e9SBarry Smith 
147545b6f7e9SBarry Smith /*@C
147645b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
147745b6f7e9SBarry Smith 
147845b6f7e9SBarry Smith    Not Collective
147945b6f7e9SBarry Smith 
148045b6f7e9SBarry Smith    Input Arguments:
148145b6f7e9SBarry Smith . ltog - local to global mapping
148245b6f7e9SBarry Smith 
148345b6f7e9SBarry Smith    Output Arguments:
148445b6f7e9SBarry Smith . array - array of indices
148545b6f7e9SBarry Smith 
148645b6f7e9SBarry Smith    Level: advanced
148745b6f7e9SBarry Smith 
148845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
148945b6f7e9SBarry Smith @*/
149045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
149145b6f7e9SBarry Smith {
149245b6f7e9SBarry Smith   PetscFunctionBegin;
149345b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
149445b6f7e9SBarry Smith   PetscValidPointer(array,2);
149545b6f7e9SBarry Smith   *array = ltog->indices;
149645b6f7e9SBarry Smith   PetscFunctionReturn(0);
149745b6f7e9SBarry Smith }
149845b6f7e9SBarry Smith 
149945b6f7e9SBarry Smith /*@C
150045b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
150145b6f7e9SBarry Smith 
150245b6f7e9SBarry Smith    Not Collective
150345b6f7e9SBarry Smith 
150445b6f7e9SBarry Smith    Input Arguments:
150545b6f7e9SBarry Smith + ltog - local to global mapping
150645b6f7e9SBarry Smith - array - array of indices
150745b6f7e9SBarry Smith 
150845b6f7e9SBarry Smith    Level: advanced
150945b6f7e9SBarry Smith 
151045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
151145b6f7e9SBarry Smith @*/
151245b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
151345b6f7e9SBarry Smith {
151445b6f7e9SBarry Smith   PetscFunctionBegin;
151545b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
151645b6f7e9SBarry Smith   PetscValidPointer(array,2);
151786994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
15180298fd71SBarry Smith   *array = NULL;
151986994e45SJed Brown   PetscFunctionReturn(0);
152086994e45SJed Brown }
1521f7efa3c7SJed Brown 
1522f7efa3c7SJed Brown /*@C
1523f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1524f7efa3c7SJed Brown 
1525f7efa3c7SJed Brown    Not Collective
1526f7efa3c7SJed Brown 
1527f7efa3c7SJed Brown    Input Arguments:
1528f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1529f7efa3c7SJed Brown . n - number of mappings to concatenate
1530f7efa3c7SJed Brown - ltogs - local to global mappings
1531f7efa3c7SJed Brown 
1532f7efa3c7SJed Brown    Output Arguments:
1533f7efa3c7SJed Brown . ltogcat - new mapping
1534f7efa3c7SJed Brown 
15359d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
15369d90f715SBarry Smith 
15379d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
15389d90f715SBarry Smith 
1539f7efa3c7SJed Brown    Level: advanced
1540f7efa3c7SJed Brown 
1541f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1542f7efa3c7SJed Brown @*/
1543f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1544f7efa3c7SJed Brown {
1545f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1546f7efa3c7SJed Brown   PetscErrorCode ierr;
1547f7efa3c7SJed Brown 
1548f7efa3c7SJed Brown   PetscFunctionBegin;
1549f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1550f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1551f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1552f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1553f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1554f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1555f7efa3c7SJed Brown     cnt += m;
1556f7efa3c7SJed Brown   }
1557785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1558f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1559f7efa3c7SJed Brown     const PetscInt *subidx;
1560f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1561f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1562f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1563f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1564f7efa3c7SJed Brown     cnt += m;
1565f7efa3c7SJed Brown   }
1566f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1567f7efa3c7SJed Brown   PetscFunctionReturn(0);
1568f7efa3c7SJed Brown }
156904a59952SBarry Smith 
157004a59952SBarry Smith 
1571