xref: /petsc/src/vec/is/utils/isltog.c (revision a59f3c4d27c22d3066d4e1e75cd7e7fb6a39509c)
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 
9186d4ecdSBarry Smith #undef __FUNCT__
106658fb44Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingDuplicate"
116658fb44Sstefano_zampini /*@
126658fb44Sstefano_zampini     ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
136658fb44Sstefano_zampini 
146658fb44Sstefano_zampini     Not Collective
156658fb44Sstefano_zampini 
166658fb44Sstefano_zampini     Input Parameter:
176658fb44Sstefano_zampini .   ltog - local to global mapping
186658fb44Sstefano_zampini 
196658fb44Sstefano_zampini     Output Parameter:
206658fb44Sstefano_zampini .   nltog - the duplicated local to global mapping
216658fb44Sstefano_zampini 
226658fb44Sstefano_zampini     Level: advanced
236658fb44Sstefano_zampini 
246658fb44Sstefano_zampini     Concepts: mapping^local to global
256658fb44Sstefano_zampini 
266658fb44Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
276658fb44Sstefano_zampini @*/
286658fb44Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping* nltog)
296658fb44Sstefano_zampini {
306658fb44Sstefano_zampini   PetscErrorCode ierr;
316658fb44Sstefano_zampini 
326658fb44Sstefano_zampini   PetscFunctionBegin;
336658fb44Sstefano_zampini   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
346658fb44Sstefano_zampini   ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog),ltog->bs,ltog->n,ltog->indices,PETSC_COPY_VALUES,nltog);CHKERRQ(ierr);
356658fb44Sstefano_zampini   PetscFunctionReturn(0);
366658fb44Sstefano_zampini }
376658fb44Sstefano_zampini 
386658fb44Sstefano_zampini #undef __FUNCT__
394a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
40565245c5SBarry Smith /*@
41107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
423b9aefa3SBarry Smith 
433b9aefa3SBarry Smith     Not Collective
443b9aefa3SBarry Smith 
453b9aefa3SBarry Smith     Input Parameter:
463b9aefa3SBarry Smith .   ltog - local to global mapping
473b9aefa3SBarry Smith 
483b9aefa3SBarry Smith     Output Parameter:
49107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
503b9aefa3SBarry Smith 
513b9aefa3SBarry Smith     Level: advanced
523b9aefa3SBarry Smith 
53273d9f13SBarry Smith     Concepts: mapping^local to global
543b9aefa3SBarry Smith 
553b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
563b9aefa3SBarry Smith @*/
577087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
583b9aefa3SBarry Smith {
593b9aefa3SBarry Smith   PetscFunctionBegin;
600700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
614482741eSBarry Smith   PetscValidIntPointer(n,2);
62107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
633b9aefa3SBarry Smith   PetscFunctionReturn(0);
643b9aefa3SBarry Smith }
653b9aefa3SBarry Smith 
664a2ae208SSatish Balay #undef __FUNCT__
674a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
685a5d4f66SBarry Smith /*@C
695a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
705a5d4f66SBarry Smith 
71b9cd556bSLois Curfman McInnes     Not Collective
72b9cd556bSLois Curfman McInnes 
735a5d4f66SBarry Smith     Input Parameters:
743b9aefa3SBarry Smith +   ltog - local to global mapping
753b9aefa3SBarry Smith -   viewer - viewer
765a5d4f66SBarry Smith 
77a997ad1aSLois Curfman McInnes     Level: advanced
78a997ad1aSLois Curfman McInnes 
79273d9f13SBarry Smith     Concepts: mapping^local to global
805a5d4f66SBarry Smith 
815a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
825a5d4f66SBarry Smith @*/
837087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
845a5d4f66SBarry Smith {
8532dcc486SBarry Smith   PetscInt       i;
8632dcc486SBarry Smith   PetscMPIInt    rank;
87ace3abfcSBarry Smith   PetscBool      iascii;
886849ba73SBarry Smith   PetscErrorCode ierr;
895a5d4f66SBarry Smith 
905a5d4f66SBarry Smith   PetscFunctionBegin;
910700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
923050cee2SBarry Smith   if (!viewer) {
93ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
943050cee2SBarry Smith   }
950700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
965a5d4f66SBarry Smith 
97ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
98251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
9932077d6dSBarry Smith   if (iascii) {
10098c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
1011575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
1025a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
1037904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
1046831982aSBarry Smith     }
105b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1061575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
1071575c14dSBarry Smith   }
1085a5d4f66SBarry Smith   PetscFunctionReturn(0);
1095a5d4f66SBarry Smith }
1105a5d4f66SBarry Smith 
1114a2ae208SSatish Balay #undef __FUNCT__
1124a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1131f428162SBarry Smith /*@
1142bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1152bdab257SBarry Smith     ordering and a global parallel ordering.
1162bdab257SBarry Smith 
1170f5bd95cSBarry Smith     Not collective
118b9cd556bSLois Curfman McInnes 
119a997ad1aSLois Curfman McInnes     Input Parameter:
1208c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1212bdab257SBarry Smith 
122a997ad1aSLois Curfman McInnes     Output Parameter:
1232bdab257SBarry Smith .   mapping - new mapping data structure
1242bdab257SBarry Smith 
125f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
126a997ad1aSLois Curfman McInnes     Level: advanced
127a997ad1aSLois Curfman McInnes 
128273d9f13SBarry Smith     Concepts: mapping^local to global
1292bdab257SBarry Smith 
1302bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1312bdab257SBarry Smith @*/
1327087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1332bdab257SBarry Smith {
1346849ba73SBarry Smith   PetscErrorCode ierr;
1353bbf0e92SBarry Smith   PetscInt       n,bs;
1365d0c19d7SBarry Smith   const PetscInt *indices;
1372bdab257SBarry Smith   MPI_Comm       comm;
1383bbf0e92SBarry Smith   PetscBool      isblock;
1393a40ed3dSBarry Smith 
1403a40ed3dSBarry Smith   PetscFunctionBegin;
1410700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1424482741eSBarry Smith   PetscValidPointer(mapping,2);
1432bdab257SBarry Smith 
1442bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1453b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1463bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1476006e8d2SBarry Smith   if (!isblock) {
148f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
149f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1502bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1516006e8d2SBarry Smith   } else {
1526006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
153f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
15428bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
155f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1566006e8d2SBarry Smith   }
1573a40ed3dSBarry Smith   PetscFunctionReturn(0);
1582bdab257SBarry Smith }
1595a5d4f66SBarry Smith 
160a4d96a55SJed Brown #undef __FUNCT__
161a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
162a4d96a55SJed Brown /*@C
163a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
164a4d96a55SJed Brown     ordering and a global parallel ordering.
165a4d96a55SJed Brown 
166a4d96a55SJed Brown     Collective
167a4d96a55SJed Brown 
168a4d96a55SJed Brown     Input Parameter:
169a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
170a4d96a55SJed Brown -   start - first global index on this process
171a4d96a55SJed Brown 
172a4d96a55SJed Brown     Output Parameter:
173a4d96a55SJed Brown .   mapping - new mapping data structure
174a4d96a55SJed Brown 
175a4d96a55SJed Brown     Level: advanced
176a4d96a55SJed Brown 
177a4d96a55SJed Brown     Concepts: mapping^local to global
178a4d96a55SJed Brown 
179a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
180a4d96a55SJed Brown @*/
181a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
182a4d96a55SJed Brown {
183a4d96a55SJed Brown   PetscErrorCode ierr;
184a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
185a4d96a55SJed Brown   const PetscInt *ilocal;
186a4d96a55SJed Brown   MPI_Comm       comm;
187a4d96a55SJed Brown 
188a4d96a55SJed Brown   PetscFunctionBegin;
189a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
190a4d96a55SJed Brown   PetscValidPointer(mapping,3);
191a4d96a55SJed Brown 
192a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1930298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
194f6e5521dSKarl Rupp   if (ilocal) {
195f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
196f6e5521dSKarl Rupp   }
197a4d96a55SJed Brown   else maxlocal = nleaves;
198785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
199785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
200a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
201a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
202a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
203a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
204f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
205a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
206a4d96a55SJed Brown   PetscFunctionReturn(0);
207a4d96a55SJed Brown }
208b46b645bSBarry Smith 
2094a2ae208SSatish Balay #undef __FUNCT__
21063fa5c83Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingSetBlockSize"
21163fa5c83Sstefano_zampini /*@
21263fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
21363fa5c83Sstefano_zampini 
21463fa5c83Sstefano_zampini     Not collective
21563fa5c83Sstefano_zampini 
21663fa5c83Sstefano_zampini     Input Parameters:
21763fa5c83Sstefano_zampini .   mapping - mapping data structure
21863fa5c83Sstefano_zampini .   bs - the blocksize
21963fa5c83Sstefano_zampini 
22063fa5c83Sstefano_zampini     Level: advanced
22163fa5c83Sstefano_zampini 
22263fa5c83Sstefano_zampini     Concepts: mapping^local to global
22363fa5c83Sstefano_zampini 
22463fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
22563fa5c83Sstefano_zampini @*/
22663fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
22763fa5c83Sstefano_zampini {
228*a59f3c4dSstefano_zampini   PetscInt       *nid;
229*a59f3c4dSstefano_zampini   const PetscInt *oid;
230*a59f3c4dSstefano_zampini   PetscInt       i,cn,on,obs,nn;
23163fa5c83Sstefano_zampini   PetscErrorCode ierr;
23263fa5c83Sstefano_zampini 
23363fa5c83Sstefano_zampini   PetscFunctionBegin;
23463fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
23563fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
23663fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
23763fa5c83Sstefano_zampini   on  = mapping->n;
23863fa5c83Sstefano_zampini   obs = mapping->bs;
23963fa5c83Sstefano_zampini   oid = mapping->indices;
24063fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
24163fa5c83Sstefano_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);
242*a59f3c4dSstefano_zampini 
24363fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
244*a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingGetIndices(mapping,&oid);CHKERRQ(ierr);
245*a59f3c4dSstefano_zampini   for (i=0;i<nn;i++) {
246*a59f3c4dSstefano_zampini     PetscInt j;
247*a59f3c4dSstefano_zampini     for (j=0,cn=0;j<bs-1;j++) {
248*a59f3c4dSstefano_zampini       if (oid[i*bs+j] < 0) { cn++; continue; }
249*a59f3c4dSstefano_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]);
250*a59f3c4dSstefano_zampini     }
251*a59f3c4dSstefano_zampini     if (oid[i*bs+j] < 0) cn++;
2528b7cb0e6Sstefano_zampini     if (cn) {
253*a59f3c4dSstefano_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);
254*a59f3c4dSstefano_zampini       nid[i] = -1;
2558b7cb0e6Sstefano_zampini     } else {
256*a59f3c4dSstefano_zampini       nid[i] = oid[i*bs]/bs;
25763fa5c83Sstefano_zampini     }
25863fa5c83Sstefano_zampini   }
259*a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(mapping,&oid);CHKERRQ(ierr);
260*a59f3c4dSstefano_zampini 
26163fa5c83Sstefano_zampini   mapping->n           = nn;
26263fa5c83Sstefano_zampini   mapping->bs          = bs;
26363fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
26463fa5c83Sstefano_zampini   mapping->indices     = nid;
265c9345713Sstefano_zampini   ierr                 = PetscFree(mapping->globals);CHKERRQ(ierr);
266c9345713Sstefano_zampini   mapping->globalstart = 0;
267c9345713Sstefano_zampini   mapping->globalend   = 0;
26863fa5c83Sstefano_zampini   PetscFunctionReturn(0);
26963fa5c83Sstefano_zampini }
27063fa5c83Sstefano_zampini 
27163fa5c83Sstefano_zampini #undef __FUNCT__
27245b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
27345b6f7e9SBarry Smith /*@
27445b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
27545b6f7e9SBarry Smith     ordering and a global parallel ordering.
27645b6f7e9SBarry Smith 
27745b6f7e9SBarry Smith     Not Collective
27845b6f7e9SBarry Smith 
27945b6f7e9SBarry Smith     Input Parameters:
28045b6f7e9SBarry Smith .   mapping - mapping data structure
28145b6f7e9SBarry Smith 
28245b6f7e9SBarry Smith     Output Parameter:
28345b6f7e9SBarry Smith .   bs - the blocksize
28445b6f7e9SBarry Smith 
28545b6f7e9SBarry Smith     Level: advanced
28645b6f7e9SBarry Smith 
28745b6f7e9SBarry Smith     Concepts: mapping^local to global
28845b6f7e9SBarry Smith 
28945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
29045b6f7e9SBarry Smith @*/
29145b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
29245b6f7e9SBarry Smith {
29345b6f7e9SBarry Smith   PetscFunctionBegin;
294cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
29545b6f7e9SBarry Smith   *bs = mapping->bs;
29645b6f7e9SBarry Smith   PetscFunctionReturn(0);
29745b6f7e9SBarry Smith }
29845b6f7e9SBarry Smith 
29945b6f7e9SBarry Smith #undef __FUNCT__
3004a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
301ba5bb76aSSatish Balay /*@
30290f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
30390f02eecSBarry Smith     ordering and a global parallel ordering.
3042362add9SBarry Smith 
30589d82c54SBarry Smith     Not Collective, but communicator may have more than one process
306b9cd556bSLois Curfman McInnes 
3072362add9SBarry Smith     Input Parameters:
30889d82c54SBarry Smith +   comm - MPI communicator
309f0413b6fSBarry Smith .   bs - the block size
31028bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
31128bc9809SBarry 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
312d5ad8652SBarry Smith -   mode - see PetscCopyMode
3132362add9SBarry Smith 
314a997ad1aSLois Curfman McInnes     Output Parameter:
31590f02eecSBarry Smith .   mapping - new mapping data structure
3162362add9SBarry Smith 
317f0413b6fSBarry 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
318a997ad1aSLois Curfman McInnes     Level: advanced
319a997ad1aSLois Curfman McInnes 
320273d9f13SBarry Smith     Concepts: mapping^local to global
3212362add9SBarry Smith 
322d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
3232362add9SBarry Smith @*/
32460c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
3252362add9SBarry Smith {
3266849ba73SBarry Smith   PetscErrorCode ierr;
32732dcc486SBarry Smith   PetscInt       *in;
328b46b645bSBarry Smith 
329b46b645bSBarry Smith   PetscFunctionBegin;
33073911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
3314482741eSBarry Smith   PetscValidPointer(mapping,4);
332b46b645bSBarry Smith 
3330298fd71SBarry Smith   *mapping = NULL;
334607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
3352362add9SBarry Smith 
33673107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
33760c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
338d4bb536fSBarry Smith   (*mapping)->n             = n;
339f0413b6fSBarry Smith   (*mapping)->bs            = bs;
340268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
341268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
342268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
343268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
344268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
345d4bb536fSBarry Smith   /*
346d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
347d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
348d4bb536fSBarry Smith   */
349d4bb536fSBarry Smith   (*mapping)->globals = 0;
350d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
351785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
352d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
353d5ad8652SBarry Smith     (*mapping)->indices = in;
3546389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3556389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
3566389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
3576389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3586389a1a1SBarry Smith   }
35960c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
360d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
3613a40ed3dSBarry Smith   PetscFunctionReturn(0);
3622362add9SBarry Smith }
3632362add9SBarry Smith 
3644a2ae208SSatish Balay #undef __FUNCT__
3654a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
36690f02eecSBarry Smith /*@
36790f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
36890f02eecSBarry Smith    ordering and a global parallel ordering.
36990f02eecSBarry Smith 
3700f5bd95cSBarry Smith    Note Collective
371b9cd556bSLois Curfman McInnes 
37290f02eecSBarry Smith    Input Parameters:
37390f02eecSBarry Smith .  mapping - mapping data structure
37490f02eecSBarry Smith 
375a997ad1aSLois Curfman McInnes    Level: advanced
376a997ad1aSLois Curfman McInnes 
3773acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
37890f02eecSBarry Smith @*/
3796bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
38090f02eecSBarry Smith {
381dfbe8321SBarry Smith   PetscErrorCode ierr;
3825fd66863SKarl Rupp 
3833a40ed3dSBarry Smith   PetscFunctionBegin;
3846bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3856bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
386997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3876bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3886bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
389268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
390268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
391268a049cSStefano Zampini   if ((*mapping)->info_indices) {
392268a049cSStefano Zampini     PetscInt i;
393268a049cSStefano Zampini 
394268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
395268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
396268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
397268a049cSStefano Zampini     }
398268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
399268a049cSStefano Zampini   }
400d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
401992144d0SBarry Smith   *mapping = 0;
4023a40ed3dSBarry Smith   PetscFunctionReturn(0);
40390f02eecSBarry Smith }
40490f02eecSBarry Smith 
4054a2ae208SSatish Balay #undef __FUNCT__
4064a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
40790f02eecSBarry Smith /*@
4083acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
4093acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
4103acfe500SLois Curfman McInnes     context.
41190f02eecSBarry Smith 
412b9cd556bSLois Curfman McInnes     Not collective
413b9cd556bSLois Curfman McInnes 
41490f02eecSBarry Smith     Input Parameters:
415b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
416b9cd556bSLois Curfman McInnes -   is - index set in local numbering
41790f02eecSBarry Smith 
41890f02eecSBarry Smith     Output Parameters:
41990f02eecSBarry Smith .   newis - index set in global numbering
42090f02eecSBarry Smith 
421a997ad1aSLois Curfman McInnes     Level: advanced
422a997ad1aSLois Curfman McInnes 
423273d9f13SBarry Smith     Concepts: mapping^local to global
4243acfe500SLois Curfman McInnes 
42590f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
426d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
42790f02eecSBarry Smith @*/
4287087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
42990f02eecSBarry Smith {
4306849ba73SBarry Smith   PetscErrorCode ierr;
431e24637baSBarry Smith   PetscInt       n,*idxout;
4325d0c19d7SBarry Smith   const PetscInt *idxin;
4333a40ed3dSBarry Smith 
4343a40ed3dSBarry Smith   PetscFunctionBegin;
4350700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
4360700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
4374482741eSBarry Smith   PetscValidPointer(newis,3);
43890f02eecSBarry Smith 
4393b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
44090f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
441785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
442e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
4433b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
444543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4453a40ed3dSBarry Smith   PetscFunctionReturn(0);
44690f02eecSBarry Smith }
44790f02eecSBarry Smith 
448afcb2eb5SJed Brown #undef __FUNCT__
449afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
450b89cb25eSSatish Balay /*@
4513acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4523acfe500SLois Curfman McInnes    and converts them to the global numbering.
45390f02eecSBarry Smith 
454b9cd556bSLois Curfman McInnes    Not collective
455b9cd556bSLois Curfman McInnes 
456bb25748dSBarry Smith    Input Parameters:
457b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
458bb25748dSBarry Smith .  N - number of integers
459b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
460bb25748dSBarry Smith 
461bb25748dSBarry Smith    Output Parameter:
462bb25748dSBarry Smith .  out - indices in global numbering
463bb25748dSBarry Smith 
464b9cd556bSLois Curfman McInnes    Notes:
465b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
466d4bb536fSBarry Smith 
467a997ad1aSLois Curfman McInnes    Level: advanced
468a997ad1aSLois Curfman McInnes 
46945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4700752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
471d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
472bb25748dSBarry Smith 
473273d9f13SBarry Smith     Concepts: mapping^local to global
474afcb2eb5SJed Brown @*/
475afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
476afcb2eb5SJed Brown {
477cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
47845b6f7e9SBarry Smith 
47945b6f7e9SBarry Smith   PetscFunctionBegin;
480cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
481cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
482cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
48345b6f7e9SBarry Smith   if (bs == 1) {
484cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
48545b6f7e9SBarry Smith     for (i=0; i<N; i++) {
48645b6f7e9SBarry Smith       if (in[i] < 0) {
48745b6f7e9SBarry Smith         out[i] = in[i];
48845b6f7e9SBarry Smith         continue;
48945b6f7e9SBarry Smith       }
490e24637baSBarry 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);
49145b6f7e9SBarry Smith       out[i] = idx[in[i]];
49245b6f7e9SBarry Smith     }
49345b6f7e9SBarry Smith   } else {
494cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
49545b6f7e9SBarry Smith     for (i=0; i<N; i++) {
49645b6f7e9SBarry Smith       if (in[i] < 0) {
49745b6f7e9SBarry Smith         out[i] = in[i];
49845b6f7e9SBarry Smith         continue;
49945b6f7e9SBarry Smith       }
500e24637baSBarry 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);
50145b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
50245b6f7e9SBarry Smith     }
50345b6f7e9SBarry Smith   }
50445b6f7e9SBarry Smith   PetscFunctionReturn(0);
50545b6f7e9SBarry Smith }
50645b6f7e9SBarry Smith 
50745b6f7e9SBarry Smith #undef __FUNCT__
50845b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
50945b6f7e9SBarry Smith /*@
5106006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
51145b6f7e9SBarry Smith 
51245b6f7e9SBarry Smith    Not collective
51345b6f7e9SBarry Smith 
51445b6f7e9SBarry Smith    Input Parameters:
51545b6f7e9SBarry Smith +  mapping - the local to global mapping context
51645b6f7e9SBarry Smith .  N - number of integers
5176006e8d2SBarry Smith -  in - input indices in local block numbering
51845b6f7e9SBarry Smith 
51945b6f7e9SBarry Smith    Output Parameter:
5206006e8d2SBarry Smith .  out - indices in global block numbering
52145b6f7e9SBarry Smith 
52245b6f7e9SBarry Smith    Notes:
52345b6f7e9SBarry Smith    The in and out array parameters may be identical.
52445b6f7e9SBarry Smith 
5256006e8d2SBarry Smith    Example:
5266006e8d2SBarry 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
5276006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
5286006e8d2SBarry Smith 
52945b6f7e9SBarry Smith    Level: advanced
53045b6f7e9SBarry Smith 
53145b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
53245b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
53345b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
53445b6f7e9SBarry Smith 
53545b6f7e9SBarry Smith     Concepts: mapping^local to global
53645b6f7e9SBarry Smith @*/
53745b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
53845b6f7e9SBarry Smith {
539cbc1caf0SMatthew G. Knepley 
540cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
541cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
542cbc1caf0SMatthew G. Knepley   {
543afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
544afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
545d4bb536fSBarry Smith 
546afcb2eb5SJed Brown     for (i=0; i<N; i++) {
547afcb2eb5SJed Brown       if (in[i] < 0) {
548afcb2eb5SJed Brown         out[i] = in[i];
549afcb2eb5SJed Brown         continue;
550afcb2eb5SJed Brown       }
551e24637baSBarry 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);
552afcb2eb5SJed Brown       out[i] = idx[in[i]];
553afcb2eb5SJed Brown     }
554cbc1caf0SMatthew G. Knepley   }
555afcb2eb5SJed Brown   PetscFunctionReturn(0);
556afcb2eb5SJed Brown }
557d4bb536fSBarry Smith 
558d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
559d4bb536fSBarry Smith 
5604a2ae208SSatish Balay #undef __FUNCT__
5614a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
562d4bb536fSBarry Smith /*
563d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
564d4bb536fSBarry Smith */
5656849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
566d4bb536fSBarry Smith {
5676849ba73SBarry Smith   PetscErrorCode ierr;
56832dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
569d4bb536fSBarry Smith 
5703a40ed3dSBarry Smith   PetscFunctionBegin;
571d4bb536fSBarry Smith   end   = 0;
572ec268f7cSJed Brown   start = PETSC_MAX_INT;
573d4bb536fSBarry Smith 
574d4bb536fSBarry Smith   for (i=0; i<n; i++) {
575d4bb536fSBarry Smith     if (idx[i] < 0) continue;
576d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
577d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
578d4bb536fSBarry Smith   }
579d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
580d4bb536fSBarry Smith   mapping->globalstart = start;
581d4bb536fSBarry Smith   mapping->globalend   = end;
582d4bb536fSBarry Smith 
583854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
584b0a32e0cSBarry Smith   mapping->globals = globals;
585f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
586d4bb536fSBarry Smith   for (i=0; i<n; i++) {
587d4bb536fSBarry Smith     if (idx[i] < 0) continue;
588d4bb536fSBarry Smith     globals[idx[i] - start] = i;
589d4bb536fSBarry Smith   }
590d4bb536fSBarry Smith 
5913bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5923a40ed3dSBarry Smith   PetscFunctionReturn(0);
593d4bb536fSBarry Smith }
594d4bb536fSBarry Smith 
5954a2ae208SSatish Balay #undef __FUNCT__
5964a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
597d4bb536fSBarry Smith /*@
598a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
599a997ad1aSLois Curfman McInnes     specified with a global numbering.
600d4bb536fSBarry Smith 
601b9cd556bSLois Curfman McInnes     Not collective
602b9cd556bSLois Curfman McInnes 
603d4bb536fSBarry Smith     Input Parameters:
604b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
605d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
606d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
607d4bb536fSBarry Smith .   n - number of global indices to map
608b9cd556bSLois Curfman McInnes -   idx - global indices to map
609d4bb536fSBarry Smith 
610d4bb536fSBarry Smith     Output Parameters:
611b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
612b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
613e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
6140298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
615e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
616e182c471SBarry Smith              a second time to set the values.
617d4bb536fSBarry Smith 
618b9cd556bSLois Curfman McInnes     Notes:
6190298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
620d4bb536fSBarry Smith 
6210f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6220f5bd95cSBarry Smith     array to compute these.
6230f5bd95cSBarry Smith 
624a997ad1aSLois Curfman McInnes     Level: advanced
625a997ad1aSLois Curfman McInnes 
62632fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
62732fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
62832fd6b96SBarry Smith 
629273d9f13SBarry Smith     Concepts: mapping^global to local
630d4bb536fSBarry Smith 
6319d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
632d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
633d4bb536fSBarry Smith @*/
6347087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
63532dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
636d4bb536fSBarry Smith {
6379d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
6389d90f715SBarry Smith   PetscErrorCode ierr;
6399d90f715SBarry Smith 
6409d90f715SBarry Smith   PetscFunctionBegin;
6419d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6429d90f715SBarry Smith   if (!mapping->globals) {
6439d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
6449d90f715SBarry Smith   }
6459d90f715SBarry Smith   globals = mapping->globals;
6469d90f715SBarry Smith   start   = mapping->globalstart;
6479d90f715SBarry Smith   end     = mapping->globalend;
6489d90f715SBarry Smith   bs      = mapping->bs;
6499d90f715SBarry Smith 
6509d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
6519d90f715SBarry Smith     if (idxout) {
6529d90f715SBarry Smith       for (i=0; i<n; i++) {
6539d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
6549d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
655663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
6569d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6579d90f715SBarry Smith       }
6589d90f715SBarry Smith     }
6599d90f715SBarry Smith     if (nout) *nout = n;
6609d90f715SBarry Smith   } else {
6619d90f715SBarry Smith     if (idxout) {
6629d90f715SBarry Smith       for (i=0; i<n; i++) {
6639d90f715SBarry Smith         if (idx[i] < 0) continue;
6649d90f715SBarry Smith         if (idx[i] < bs*start) continue;
665663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6669d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6679d90f715SBarry Smith         if (tmp < 0) continue;
6689d90f715SBarry Smith         idxout[nf++] = tmp;
6699d90f715SBarry Smith       }
6709d90f715SBarry Smith     } else {
6719d90f715SBarry Smith       for (i=0; i<n; i++) {
6729d90f715SBarry Smith         if (idx[i] < 0) continue;
6739d90f715SBarry Smith         if (idx[i] < bs*start) continue;
674663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6759d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6769d90f715SBarry Smith         if (tmp < 0) continue;
6779d90f715SBarry Smith         nf++;
6789d90f715SBarry Smith       }
6799d90f715SBarry Smith     }
6809d90f715SBarry Smith     if (nout) *nout = nf;
6819d90f715SBarry Smith   }
6829d90f715SBarry Smith   PetscFunctionReturn(0);
6839d90f715SBarry Smith }
6849d90f715SBarry Smith 
6859d90f715SBarry Smith #undef __FUNCT__
686d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
687d4fe737eSStefano Zampini /*@
688d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
689d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
690d4fe737eSStefano Zampini     context.
691d4fe737eSStefano Zampini 
692d4fe737eSStefano Zampini     Not collective
693d4fe737eSStefano Zampini 
694d4fe737eSStefano Zampini     Input Parameters:
695d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
696d4fe737eSStefano Zampini -   is - index set in global numbering
697d4fe737eSStefano Zampini 
698d4fe737eSStefano Zampini     Output Parameters:
699d4fe737eSStefano Zampini .   newis - index set in local numbering
700d4fe737eSStefano Zampini 
701d4fe737eSStefano Zampini     Level: advanced
702d4fe737eSStefano Zampini 
703d4fe737eSStefano Zampini     Concepts: mapping^local to global
704d4fe737eSStefano Zampini 
705d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
706d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
707d4fe737eSStefano Zampini @*/
708d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
709d4fe737eSStefano Zampini {
710d4fe737eSStefano Zampini   PetscErrorCode ierr;
711d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
712d4fe737eSStefano Zampini   const PetscInt *idxin;
713d4fe737eSStefano Zampini 
714d4fe737eSStefano Zampini   PetscFunctionBegin;
715d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
716d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
717d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
718d4fe737eSStefano Zampini 
719d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
720d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
721d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
722d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
723d4fe737eSStefano Zampini   } else {
724d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
725d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
726d4fe737eSStefano Zampini   }
727d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
728d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
729d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
730d4fe737eSStefano Zampini   PetscFunctionReturn(0);
731d4fe737eSStefano Zampini }
732d4fe737eSStefano Zampini 
733d4fe737eSStefano Zampini #undef __FUNCT__
7349d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
7359d90f715SBarry Smith /*@
7369d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
7379d90f715SBarry Smith     specified with a block global numbering.
7389d90f715SBarry Smith 
7399d90f715SBarry Smith     Not collective
7409d90f715SBarry Smith 
7419d90f715SBarry Smith     Input Parameters:
7429d90f715SBarry Smith +   mapping - mapping between local and global numbering
7439d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
7449d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
7459d90f715SBarry Smith .   n - number of global indices to map
7469d90f715SBarry Smith -   idx - global indices to map
7479d90f715SBarry Smith 
7489d90f715SBarry Smith     Output Parameters:
7499d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
7509d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
7519d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
7529d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
7539d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
7549d90f715SBarry Smith              a second time to set the values.
7559d90f715SBarry Smith 
7569d90f715SBarry Smith     Notes:
7579d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
7589d90f715SBarry Smith 
7599d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
7609d90f715SBarry Smith     array to compute these.
7619d90f715SBarry Smith 
7629d90f715SBarry Smith     Level: advanced
7639d90f715SBarry Smith 
7649d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
7659d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
7669d90f715SBarry Smith 
7679d90f715SBarry Smith     Concepts: mapping^global to local
7689d90f715SBarry Smith 
7699d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7709d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7719d90f715SBarry Smith @*/
7729d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7739d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7749d90f715SBarry Smith {
77532dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
7766849ba73SBarry Smith   PetscErrorCode ierr;
777d4bb536fSBarry Smith 
7783a40ed3dSBarry Smith   PetscFunctionBegin;
7790700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
780d4bb536fSBarry Smith   if (!mapping->globals) {
781d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
782d4bb536fSBarry Smith   }
783d4bb536fSBarry Smith   globals = mapping->globals;
784d4bb536fSBarry Smith   start   = mapping->globalstart;
785d4bb536fSBarry Smith   end     = mapping->globalend;
786d4bb536fSBarry Smith 
787d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
788d4bb536fSBarry Smith     if (idxout) {
789d4bb536fSBarry Smith       for (i=0; i<n; i++) {
790d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
791d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
792d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
793d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
794d4bb536fSBarry Smith       }
795d4bb536fSBarry Smith     }
796d4bb536fSBarry Smith     if (nout) *nout = n;
797d4bb536fSBarry Smith   } else {
798d4bb536fSBarry Smith     if (idxout) {
799d4bb536fSBarry Smith       for (i=0; i<n; i++) {
800d4bb536fSBarry Smith         if (idx[i] < 0) continue;
801d4bb536fSBarry Smith         if (idx[i] < start) continue;
802d4bb536fSBarry Smith         if (idx[i] > end) continue;
803d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
804d4bb536fSBarry Smith         if (tmp < 0) continue;
805d4bb536fSBarry Smith         idxout[nf++] = tmp;
806d4bb536fSBarry Smith       }
807d4bb536fSBarry Smith     } else {
808d4bb536fSBarry Smith       for (i=0; i<n; i++) {
809d4bb536fSBarry Smith         if (idx[i] < 0) continue;
810d4bb536fSBarry Smith         if (idx[i] < start) continue;
811d4bb536fSBarry Smith         if (idx[i] > end) continue;
812d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
813d4bb536fSBarry Smith         if (tmp < 0) continue;
814d4bb536fSBarry Smith         nf++;
815d4bb536fSBarry Smith       }
816d4bb536fSBarry Smith     }
817d4bb536fSBarry Smith     if (nout) *nout = nf;
818d4bb536fSBarry Smith   }
8193a40ed3dSBarry Smith   PetscFunctionReturn(0);
820d4bb536fSBarry Smith }
82190f02eecSBarry Smith 
8224a2ae208SSatish Balay #undef __FUNCT__
8236a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
82489d82c54SBarry Smith /*@C
8256a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
82689d82c54SBarry Smith      each index shared by more than one processor
82789d82c54SBarry Smith 
82889d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
82989d82c54SBarry Smith 
83089d82c54SBarry Smith     Input Parameters:
83189d82c54SBarry Smith .   mapping - the mapping from local to global indexing
83289d82c54SBarry Smith 
83389d82c54SBarry Smith     Output Parameter:
83489d82c54SBarry Smith +   nproc - number of processors that are connected to this one
83589d82c54SBarry Smith .   proc - neighboring processors
83607b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
8373463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
83889d82c54SBarry Smith 
83989d82c54SBarry Smith     Level: advanced
84089d82c54SBarry Smith 
841273d9f13SBarry Smith     Concepts: mapping^local to global
84289d82c54SBarry Smith 
8432cfcea29SBarry Smith     Fortran Usage:
8442cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
8452cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
8462cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
8472cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
8482cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
8492cfcea29SBarry Smith 
8502cfcea29SBarry Smith 
85107b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
85207b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
85389d82c54SBarry Smith @*/
8546a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
85589d82c54SBarry Smith {
8566849ba73SBarry Smith   PetscErrorCode ierr;
857268a049cSStefano Zampini 
858268a049cSStefano Zampini   PetscFunctionBegin;
859268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
860268a049cSStefano Zampini   if (mapping->info_cached) {
861268a049cSStefano Zampini     *nproc = mapping->info_nproc;
862268a049cSStefano Zampini     *procs = mapping->info_procs;
863268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
864268a049cSStefano Zampini     *indices = mapping->info_indices;
865268a049cSStefano Zampini   } else {
866268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
867268a049cSStefano Zampini   }
868268a049cSStefano Zampini   PetscFunctionReturn(0);
869268a049cSStefano Zampini }
870268a049cSStefano Zampini 
871268a049cSStefano Zampini #undef __FUNCT__
872268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
873268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
874268a049cSStefano Zampini {
875268a049cSStefano Zampini   PetscErrorCode ierr;
87697f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
87732dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
87832dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
87997f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
88032dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
88132dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
88289d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
88330dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
884ce94432eSBarry Smith   MPI_Comm       comm;
885ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
88689d82c54SBarry Smith 
88789d82c54SBarry Smith   PetscFunctionBegin;
888ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
88924cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
89024cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
89124cf384cSBarry Smith   if (size == 1) {
89224cf384cSBarry Smith     *nproc         = 0;
8930298fd71SBarry Smith     *procs         = NULL;
89495dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
8951e2105dcSBarry Smith     (*numprocs)[0] = 0;
89695dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
8970298fd71SBarry Smith     (*indices)[0]  = NULL;
898268a049cSStefano Zampini     /* save info for reuse */
899268a049cSStefano Zampini     mapping->info_nproc = *nproc;
900268a049cSStefano Zampini     mapping->info_procs = *procs;
901268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
902268a049cSStefano Zampini     mapping->info_indices = *indices;
903268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
90424cf384cSBarry Smith     PetscFunctionReturn(0);
90524cf384cSBarry Smith   }
90624cf384cSBarry Smith 
907c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
90807b52d57SBarry Smith 
9093677ff5aSBarry Smith   /*
9106a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
9113677ff5aSBarry Smith 
9123677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
9133677ff5aSBarry Smith            numbering, just for this routine.
9143677ff5aSBarry Smith 
9153677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
9163677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
9173677ff5aSBarry Smith 
9183677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
9193677ff5aSBarry Smith 
9203677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
9213677ff5aSBarry Smith            local subdomain
9223677ff5aSBarry Smith   */
92324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
92424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
92524cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
92689d82c54SBarry Smith 
92789d82c54SBarry Smith   for (i=0; i<n; i++) {
92889d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
92989d82c54SBarry Smith   }
930b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
93178058e43SBarry Smith   Ng++;
93289d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
93389d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
934bc8ff85bSBarry Smith   scale  = Ng/size + 1;
935a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
936caba0dd0SBarry Smith   rstart = scale*rank;
93789d82c54SBarry Smith 
93889d82c54SBarry Smith   /* determine ownership ranges of global indices */
939785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
94032dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
94189d82c54SBarry Smith 
94289d82c54SBarry Smith   /* determine owners of each local node  */
943785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
94489d82c54SBarry Smith   for (i=0; i<n; i++) {
9453677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
94627c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
9473677ff5aSBarry Smith     owner[i]         = proc;
94827c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
94989d82c54SBarry Smith   }
95027c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
9517904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
95289d82c54SBarry Smith 
95389d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
95427c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9557904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
95689d82c54SBarry Smith 
95789d82c54SBarry Smith   /* post receives for owned rows */
958785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
959854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
96089d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
96132dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
96289d82c54SBarry Smith   }
96389d82c54SBarry Smith 
96489d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
965854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
966854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
96789d82c54SBarry Smith   starts[0] = 0;
968f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
96989d82c54SBarry Smith   for (i=0; i<n; i++) {
97089d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
97130dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
97289d82c54SBarry Smith   }
97389d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
97489d82c54SBarry Smith   starts[0] = 0;
975f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
97689d82c54SBarry Smith 
97789d82c54SBarry Smith   /* send the messages */
978854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
979854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
98089d82c54SBarry Smith   cnt = 0;
98189d82c54SBarry Smith   for (i=0; i<size; i++) {
98227c402fcSBarry Smith     if (nprocs[2*i]) {
98332dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
98430dcb7c9SBarry Smith       dest[cnt] = i;
98589d82c54SBarry Smith       cnt++;
98689d82c54SBarry Smith     }
98789d82c54SBarry Smith   }
98889d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
98989d82c54SBarry Smith 
99089d82c54SBarry Smith   /* wait on receives */
991854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
992854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
99389d82c54SBarry Smith   cnt  = nrecvs;
994854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
99532dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
99689d82c54SBarry Smith   while (cnt) {
99789d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
99889d82c54SBarry Smith     /* unpack receives into our local space */
99932dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
100089d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
100130dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
1002caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
100330dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
100489d82c54SBarry Smith     cnt--;
100589d82c54SBarry Smith   }
100689d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
100789d82c54SBarry Smith 
100830dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1009bc8ff85bSBarry Smith   nowned  = 0;
1010bc8ff85bSBarry Smith   nownedm = 0;
1011bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
1012bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
1013bc8ff85bSBarry Smith   }
1014bc8ff85bSBarry Smith 
1015bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1016854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1017854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1018bc8ff85bSBarry Smith   starts[0] = 0;
1019bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1020bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1021bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1022bc8ff85bSBarry Smith   }
1023bc8ff85bSBarry Smith 
102430dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1025bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1026bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
102730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1028f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1029bc8ff85bSBarry Smith     }
1030bc8ff85bSBarry Smith   }
1031bc8ff85bSBarry Smith 
103207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
103330dcb7c9SBarry Smith     starts[0] = 0;
103430dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
103530dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
103630dcb7c9SBarry Smith       else starts[i] = starts[i-1];
103730dcb7c9SBarry Smith     }
103830dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
103930dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
10407904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
104130dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
10427904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
104330dcb7c9SBarry Smith         }
104430dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
104530dcb7c9SBarry Smith       }
104630dcb7c9SBarry Smith     }
10470ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
104807b52d57SBarry Smith   } /* -----------------------------------  */
104930dcb7c9SBarry Smith 
10503677ff5aSBarry Smith   /* wait on original sends */
10513a96401aSBarry Smith   if (nsends) {
1052785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
10533a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10543a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10553a96401aSBarry Smith   }
105689d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10573a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
10583677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
10593677ff5aSBarry Smith 
10603677ff5aSBarry Smith   /* pack messages to send back to local owners */
106130dcb7c9SBarry Smith   starts[0] = 0;
106230dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
106330dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
106430dcb7c9SBarry Smith     else starts[i] = starts[i-1];
106530dcb7c9SBarry Smith   }
106630dcb7c9SBarry Smith   nsends2 = nrecvs;
1067854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
106830dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
106930dcb7c9SBarry Smith     nprocs[i] = 1;
107030dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
107130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1072f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
107330dcb7c9SBarry Smith     }
107430dcb7c9SBarry Smith   }
1075f6e5521dSKarl Rupp   nt = 0;
1076f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1077f6e5521dSKarl Rupp 
1078854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1079854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1080f6e5521dSKarl Rupp 
1081f6e5521dSKarl Rupp   starts2[0] = 0;
1082f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
108330dcb7c9SBarry Smith   /*
108430dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
108530dcb7c9SBarry Smith        (0) the number of nodes being sent back
108630dcb7c9SBarry Smith        (1) the local node number,
108730dcb7c9SBarry Smith        (2) the number of processors sharing it,
108830dcb7c9SBarry Smith        (3) the processors sharing it
108930dcb7c9SBarry Smith   */
109030dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
109130dcb7c9SBarry Smith     cnt = 1;
109230dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
109330dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
109430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
109530dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
109630dcb7c9SBarry Smith         sends2[starts2[i]]++;
109730dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
109830dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
109932dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
110030dcb7c9SBarry Smith         cnt += nownedsenders[node];
110130dcb7c9SBarry Smith       }
110230dcb7c9SBarry Smith     }
110330dcb7c9SBarry Smith   }
110430dcb7c9SBarry Smith 
110530dcb7c9SBarry Smith   /* receive the message lengths */
110630dcb7c9SBarry Smith   nrecvs2 = nsends;
1107854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1108854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1109854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
111030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1111d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
111230dcb7c9SBarry Smith   }
1113d44834fbSBarry Smith 
11148a8e0b3aSBarry Smith   /* send the message lengths */
11158a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
11168a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
11178a8e0b3aSBarry Smith   }
11188a8e0b3aSBarry Smith 
1119d44834fbSBarry Smith   /* wait on receives of lens */
11200c468ba9SBarry Smith   if (nrecvs2) {
1121785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1122d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1123d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11240c468ba9SBarry Smith   }
1125a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1126d44834fbSBarry Smith 
112730dcb7c9SBarry Smith   starts3[0] = 0;
1128d44834fbSBarry Smith   nt         = 0;
112930dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
113030dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1131d44834fbSBarry Smith     nt          += lens2[i];
113230dcb7c9SBarry Smith   }
113376466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1134d44834fbSBarry Smith 
1135854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1136854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
113752b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
113832dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
113930dcb7c9SBarry Smith   }
114030dcb7c9SBarry Smith 
114130dcb7c9SBarry Smith   /* send the messages */
1142854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
114330dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
114432dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
114530dcb7c9SBarry Smith   }
114630dcb7c9SBarry Smith 
114730dcb7c9SBarry Smith   /* wait on receives */
11480c468ba9SBarry Smith   if (nrecvs2) {
1149785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
115030dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
115130dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11520c468ba9SBarry Smith   }
115330dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
115430dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
115530dcb7c9SBarry Smith 
115607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
115730dcb7c9SBarry Smith     cnt = 0;
115830dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
115930dcb7c9SBarry Smith       nt = recvs2[cnt++];
116030dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
11617904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
116230dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
11637904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
116430dcb7c9SBarry Smith         }
116530dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
116630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
116730dcb7c9SBarry Smith       }
116830dcb7c9SBarry Smith     }
11690ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
117007b52d57SBarry Smith   } /* -----------------------------------  */
117130dcb7c9SBarry Smith 
117230dcb7c9SBarry Smith   /* count number subdomains for each local node */
1173785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
117432dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
117530dcb7c9SBarry Smith   cnt  = 0;
117630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
117730dcb7c9SBarry Smith     nt = recvs2[cnt++];
117830dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1179f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
118030dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
118130dcb7c9SBarry Smith     }
118230dcb7c9SBarry Smith   }
118330dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
118430dcb7c9SBarry Smith   *nproc    = nt;
1185854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1186854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1187854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
11880298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1189785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
119030dcb7c9SBarry Smith   cnt  = 0;
119130dcb7c9SBarry Smith   for (i=0; i<size; i++) {
119230dcb7c9SBarry Smith     if (nprocs[i] > 0) {
119330dcb7c9SBarry Smith       bprocs[i]        = cnt;
119430dcb7c9SBarry Smith       (*procs)[cnt]    = i;
119530dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1196785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
119730dcb7c9SBarry Smith       cnt++;
119830dcb7c9SBarry Smith     }
119930dcb7c9SBarry Smith   }
120030dcb7c9SBarry Smith 
120130dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
120232dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
120330dcb7c9SBarry Smith   cnt  = 0;
120430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
120530dcb7c9SBarry Smith     nt = recvs2[cnt++];
120630dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1207f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
120830dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
120930dcb7c9SBarry Smith     }
121030dcb7c9SBarry Smith   }
121130dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
121207b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
121330dcb7c9SBarry Smith 
121407b52d57SBarry Smith   /* sort the node indexing by their global numbers */
121507b52d57SBarry Smith   nt = *nproc;
121607b52d57SBarry Smith   for (i=0; i<nt; i++) {
1217854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1218f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
121907b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
122007b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
122107b52d57SBarry Smith   }
122207b52d57SBarry Smith 
122307b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
122430dcb7c9SBarry Smith     nt = *nproc;
122530dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
12267904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
122730dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
12287904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
122930dcb7c9SBarry Smith       }
123030dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
123130dcb7c9SBarry Smith     }
12320ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
123307b52d57SBarry Smith   } /* -----------------------------------  */
123430dcb7c9SBarry Smith 
123530dcb7c9SBarry Smith   /* wait on sends */
123630dcb7c9SBarry Smith   if (nsends2) {
1237785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
123830dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
123930dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
124030dcb7c9SBarry Smith   }
124130dcb7c9SBarry Smith 
124230dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
124330dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
124430dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12453677ff5aSBarry Smith 
1246bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1247bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1248bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
124930dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
125030dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
125189d82c54SBarry Smith 
125289d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
125397f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
125489d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
12553a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
125630dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
125724cf384cSBarry Smith 
125824cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
125924cf384cSBarry Smith   first_procs    = (*procs)[0];
126024cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
126124cf384cSBarry Smith   first_indices  = (*indices)[0];
126224cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
126324cf384cSBarry Smith     if ((*procs)[i] == rank) {
126424cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
126524cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
126624cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
126724cf384cSBarry Smith       (*procs)[i]    = first_procs;
126824cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
126924cf384cSBarry Smith       (*indices)[i]  = first_indices;
127024cf384cSBarry Smith       break;
127124cf384cSBarry Smith     }
127224cf384cSBarry Smith   }
1273268a049cSStefano Zampini 
1274268a049cSStefano Zampini   /* save info for reuse */
1275268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1276268a049cSStefano Zampini   mapping->info_procs = *procs;
1277268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1278268a049cSStefano Zampini   mapping->info_indices = *indices;
1279268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
128089d82c54SBarry Smith   PetscFunctionReturn(0);
128189d82c54SBarry Smith }
128289d82c54SBarry Smith 
12834a2ae208SSatish Balay #undef __FUNCT__
12846a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
12856a818285SBarry Smith /*@C
12866a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
12876a818285SBarry Smith 
12886a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12896a818285SBarry Smith 
12906a818285SBarry Smith     Input Parameters:
12916a818285SBarry Smith .   mapping - the mapping from local to global indexing
12926a818285SBarry Smith 
12936a818285SBarry Smith     Output Parameter:
12946a818285SBarry Smith +   nproc - number of processors that are connected to this one
12956a818285SBarry Smith .   proc - neighboring processors
12966a818285SBarry Smith .   numproc - number of indices for each processor
12976a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12986a818285SBarry Smith 
12996a818285SBarry Smith     Level: advanced
13006a818285SBarry Smith 
13016a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13026a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
13036a818285SBarry Smith @*/
13046a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13056a818285SBarry Smith {
13066a818285SBarry Smith   PetscErrorCode ierr;
13076a818285SBarry Smith 
13086a818285SBarry Smith   PetscFunctionBegin;
1309cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1310268a049cSStefano Zampini   if (mapping->info_free) {
13116a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
13126a818285SBarry Smith     if (*indices) {
1313268a049cSStefano Zampini       PetscInt i;
1314268a049cSStefano Zampini 
13156a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
13166a818285SBarry Smith       for (i=1; i<*nproc; i++) {
13176a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
13186a818285SBarry Smith       }
13196a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
13206a818285SBarry Smith     }
1321268a049cSStefano Zampini   }
1322268a049cSStefano Zampini   *nproc = 0;
1323268a049cSStefano Zampini   *procs = NULL;
1324268a049cSStefano Zampini   *numprocs = NULL;
1325268a049cSStefano Zampini   *indices = NULL;
13266a818285SBarry Smith   PetscFunctionReturn(0);
13276a818285SBarry Smith }
13286a818285SBarry Smith 
13296a818285SBarry Smith #undef __FUNCT__
13306a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
13316a818285SBarry Smith /*@C
13326a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
13336a818285SBarry Smith      each index shared by more than one processor
13346a818285SBarry Smith 
13356a818285SBarry Smith     Collective on ISLocalToGlobalMapping
13366a818285SBarry Smith 
13376a818285SBarry Smith     Input Parameters:
13386a818285SBarry Smith .   mapping - the mapping from local to global indexing
13396a818285SBarry Smith 
13406a818285SBarry Smith     Output Parameter:
13416a818285SBarry Smith +   nproc - number of processors that are connected to this one
13426a818285SBarry Smith .   proc - neighboring processors
13436a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
13446a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
13456a818285SBarry Smith 
13466a818285SBarry Smith     Level: advanced
13476a818285SBarry Smith 
13486a818285SBarry Smith     Concepts: mapping^local to global
13496a818285SBarry Smith 
13506a818285SBarry Smith     Fortran Usage:
13516a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
13526a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
13536a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
13546a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
13556a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
13566a818285SBarry Smith 
13576a818285SBarry Smith 
13586a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13596a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
13606a818285SBarry Smith @*/
13616a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13626a818285SBarry Smith {
13636a818285SBarry Smith   PetscErrorCode ierr;
1364268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
13656a818285SBarry Smith 
13666a818285SBarry Smith   PetscFunctionBegin;
13676a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1368268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1369268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1370732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1371268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13726a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1373268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1374268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13756a818285SBarry Smith         for (k=0; k<bs; k++) {
13766a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13776a818285SBarry Smith         }
13786a818285SBarry Smith       }
1379268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13806a818285SBarry Smith     }
1381268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1382268a049cSStefano Zampini   } else {
1383268a049cSStefano Zampini     *numprocs = bnumprocs;
1384268a049cSStefano Zampini     *indices  = bindices;
13856a818285SBarry Smith   }
13866a818285SBarry Smith   PetscFunctionReturn(0);
13876a818285SBarry Smith }
13886a818285SBarry Smith 
13896a818285SBarry Smith #undef __FUNCT__
13904a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
139107b52d57SBarry Smith /*@C
139207b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
139389d82c54SBarry Smith 
139407b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
139507b52d57SBarry Smith 
139607b52d57SBarry Smith     Input Parameters:
139707b52d57SBarry Smith .   mapping - the mapping from local to global indexing
139807b52d57SBarry Smith 
139907b52d57SBarry Smith     Output Parameter:
140007b52d57SBarry Smith +   nproc - number of processors that are connected to this one
140107b52d57SBarry Smith .   proc - neighboring processors
140207b52d57SBarry Smith .   numproc - number of indices for each processor
140307b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
140407b52d57SBarry Smith 
140507b52d57SBarry Smith     Level: advanced
140607b52d57SBarry Smith 
140707b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
140807b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
140907b52d57SBarry Smith @*/
14107087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
141107b52d57SBarry Smith {
14126849ba73SBarry Smith   PetscErrorCode ierr;
141307b52d57SBarry Smith 
141407b52d57SBarry Smith   PetscFunctionBegin;
14156a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
141607b52d57SBarry Smith   PetscFunctionReturn(0);
141707b52d57SBarry Smith }
141886994e45SJed Brown 
141986994e45SJed Brown #undef __FUNCT__
142086994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
142186994e45SJed Brown /*@C
1422107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
142386994e45SJed Brown 
142486994e45SJed Brown    Not Collective
142586994e45SJed Brown 
142686994e45SJed Brown    Input Arguments:
142786994e45SJed Brown . ltog - local to global mapping
142886994e45SJed Brown 
142986994e45SJed Brown    Output Arguments:
1430565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
143186994e45SJed Brown 
143286994e45SJed Brown    Level: advanced
143386994e45SJed Brown 
1434107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1435107e9a97SBarry Smith 
1436107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
143786994e45SJed Brown @*/
14387087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
143986994e45SJed Brown {
144086994e45SJed Brown   PetscFunctionBegin;
144186994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
144286994e45SJed Brown   PetscValidPointer(array,2);
144345b6f7e9SBarry Smith   if (ltog->bs == 1) {
144486994e45SJed Brown     *array = ltog->indices;
144545b6f7e9SBarry Smith   } else {
144645b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
144745b6f7e9SBarry Smith     const PetscInt *ii;
144845b6f7e9SBarry Smith     PetscErrorCode ierr;
144945b6f7e9SBarry Smith 
145045b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
145145b6f7e9SBarry Smith     *array = jj;
145245b6f7e9SBarry Smith     k    = 0;
145345b6f7e9SBarry Smith     ii   = ltog->indices;
145445b6f7e9SBarry Smith     for (i=0; i<n; i++)
145545b6f7e9SBarry Smith       for (j=0; j<bs; j++)
145645b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
145745b6f7e9SBarry Smith   }
145886994e45SJed Brown   PetscFunctionReturn(0);
145986994e45SJed Brown }
146086994e45SJed Brown 
146186994e45SJed Brown #undef __FUNCT__
146286994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
146386994e45SJed Brown /*@C
1464193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
146586994e45SJed Brown 
146686994e45SJed Brown    Not Collective
146786994e45SJed Brown 
146886994e45SJed Brown    Input Arguments:
146986994e45SJed Brown + ltog - local to global mapping
147086994e45SJed Brown - array - array of indices
147186994e45SJed Brown 
147286994e45SJed Brown    Level: advanced
147386994e45SJed Brown 
147486994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
147586994e45SJed Brown @*/
14767087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
147786994e45SJed Brown {
147886994e45SJed Brown   PetscFunctionBegin;
147986994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
148086994e45SJed Brown   PetscValidPointer(array,2);
148145b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
148245b6f7e9SBarry Smith 
148345b6f7e9SBarry Smith   if (ltog->bs > 1) {
148445b6f7e9SBarry Smith     PetscErrorCode ierr;
148545b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
148645b6f7e9SBarry Smith   }
148745b6f7e9SBarry Smith   PetscFunctionReturn(0);
148845b6f7e9SBarry Smith }
148945b6f7e9SBarry Smith 
149045b6f7e9SBarry Smith #undef __FUNCT__
149145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
149245b6f7e9SBarry Smith /*@C
149345b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
149445b6f7e9SBarry Smith 
149545b6f7e9SBarry Smith    Not Collective
149645b6f7e9SBarry Smith 
149745b6f7e9SBarry Smith    Input Arguments:
149845b6f7e9SBarry Smith . ltog - local to global mapping
149945b6f7e9SBarry Smith 
150045b6f7e9SBarry Smith    Output Arguments:
150145b6f7e9SBarry Smith . array - array of indices
150245b6f7e9SBarry Smith 
150345b6f7e9SBarry Smith    Level: advanced
150445b6f7e9SBarry Smith 
150545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
150645b6f7e9SBarry Smith @*/
150745b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
150845b6f7e9SBarry Smith {
150945b6f7e9SBarry Smith   PetscFunctionBegin;
151045b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
151145b6f7e9SBarry Smith   PetscValidPointer(array,2);
151245b6f7e9SBarry Smith   *array = ltog->indices;
151345b6f7e9SBarry Smith   PetscFunctionReturn(0);
151445b6f7e9SBarry Smith }
151545b6f7e9SBarry Smith 
151645b6f7e9SBarry Smith #undef __FUNCT__
151745b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
151845b6f7e9SBarry Smith /*@C
151945b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
152045b6f7e9SBarry Smith 
152145b6f7e9SBarry Smith    Not Collective
152245b6f7e9SBarry Smith 
152345b6f7e9SBarry Smith    Input Arguments:
152445b6f7e9SBarry Smith + ltog - local to global mapping
152545b6f7e9SBarry Smith - array - array of indices
152645b6f7e9SBarry Smith 
152745b6f7e9SBarry Smith    Level: advanced
152845b6f7e9SBarry Smith 
152945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
153045b6f7e9SBarry Smith @*/
153145b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
153245b6f7e9SBarry Smith {
153345b6f7e9SBarry Smith   PetscFunctionBegin;
153445b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
153545b6f7e9SBarry Smith   PetscValidPointer(array,2);
153686994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
15370298fd71SBarry Smith   *array = NULL;
153886994e45SJed Brown   PetscFunctionReturn(0);
153986994e45SJed Brown }
1540f7efa3c7SJed Brown 
1541f7efa3c7SJed Brown #undef __FUNCT__
1542f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1543f7efa3c7SJed Brown /*@C
1544f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1545f7efa3c7SJed Brown 
1546f7efa3c7SJed Brown    Not Collective
1547f7efa3c7SJed Brown 
1548f7efa3c7SJed Brown    Input Arguments:
1549f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1550f7efa3c7SJed Brown . n - number of mappings to concatenate
1551f7efa3c7SJed Brown - ltogs - local to global mappings
1552f7efa3c7SJed Brown 
1553f7efa3c7SJed Brown    Output Arguments:
1554f7efa3c7SJed Brown . ltogcat - new mapping
1555f7efa3c7SJed Brown 
15569d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
15579d90f715SBarry Smith 
15589d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
15599d90f715SBarry Smith 
1560f7efa3c7SJed Brown    Level: advanced
1561f7efa3c7SJed Brown 
1562f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1563f7efa3c7SJed Brown @*/
1564f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1565f7efa3c7SJed Brown {
1566f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1567f7efa3c7SJed Brown   PetscErrorCode ierr;
1568f7efa3c7SJed Brown 
1569f7efa3c7SJed Brown   PetscFunctionBegin;
1570f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1571f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1572f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1573f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1574f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1575f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1576f7efa3c7SJed Brown     cnt += m;
1577f7efa3c7SJed Brown   }
1578785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1579f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1580f7efa3c7SJed Brown     const PetscInt *subidx;
1581f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1582f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1583f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1584f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1585f7efa3c7SJed Brown     cnt += m;
1586f7efa3c7SJed Brown   }
1587f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1588f7efa3c7SJed Brown   PetscFunctionReturn(0);
1589f7efa3c7SJed Brown }
159004a59952SBarry Smith 
159104a59952SBarry Smith 
1592