xref: /petsc/src/vec/is/utils/isltog.c (revision 8b7cb0e67edc0ad3c573fa4d3743f885f6250459)
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__
104a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
11565245c5SBarry Smith /*@
12107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
133b9aefa3SBarry Smith 
143b9aefa3SBarry Smith     Not Collective
153b9aefa3SBarry Smith 
163b9aefa3SBarry Smith     Input Parameter:
173b9aefa3SBarry Smith .   ltog - local to global mapping
183b9aefa3SBarry Smith 
193b9aefa3SBarry Smith     Output Parameter:
20107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
213b9aefa3SBarry Smith 
223b9aefa3SBarry Smith     Level: advanced
233b9aefa3SBarry Smith 
24273d9f13SBarry Smith     Concepts: mapping^local to global
253b9aefa3SBarry Smith 
263b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
273b9aefa3SBarry Smith @*/
287087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
293b9aefa3SBarry Smith {
303b9aefa3SBarry Smith   PetscFunctionBegin;
310700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
324482741eSBarry Smith   PetscValidIntPointer(n,2);
33107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
343b9aefa3SBarry Smith   PetscFunctionReturn(0);
353b9aefa3SBarry Smith }
363b9aefa3SBarry Smith 
374a2ae208SSatish Balay #undef __FUNCT__
384a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
395a5d4f66SBarry Smith /*@C
405a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
415a5d4f66SBarry Smith 
42b9cd556bSLois Curfman McInnes     Not Collective
43b9cd556bSLois Curfman McInnes 
445a5d4f66SBarry Smith     Input Parameters:
453b9aefa3SBarry Smith +   ltog - local to global mapping
463b9aefa3SBarry Smith -   viewer - viewer
475a5d4f66SBarry Smith 
48a997ad1aSLois Curfman McInnes     Level: advanced
49a997ad1aSLois Curfman McInnes 
50273d9f13SBarry Smith     Concepts: mapping^local to global
515a5d4f66SBarry Smith 
525a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
535a5d4f66SBarry Smith @*/
547087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
555a5d4f66SBarry Smith {
5632dcc486SBarry Smith   PetscInt       i;
5732dcc486SBarry Smith   PetscMPIInt    rank;
58ace3abfcSBarry Smith   PetscBool      iascii;
596849ba73SBarry Smith   PetscErrorCode ierr;
605a5d4f66SBarry Smith 
615a5d4f66SBarry Smith   PetscFunctionBegin;
620700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
633050cee2SBarry Smith   if (!viewer) {
64ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
653050cee2SBarry Smith   }
660700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
675a5d4f66SBarry Smith 
68ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
69251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
7032077d6dSBarry Smith   if (iascii) {
7198c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
721575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
735a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
747904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
756831982aSBarry Smith     }
76b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
771575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
781575c14dSBarry Smith   }
795a5d4f66SBarry Smith   PetscFunctionReturn(0);
805a5d4f66SBarry Smith }
815a5d4f66SBarry Smith 
824a2ae208SSatish Balay #undef __FUNCT__
834a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
841f428162SBarry Smith /*@
852bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
862bdab257SBarry Smith     ordering and a global parallel ordering.
872bdab257SBarry Smith 
880f5bd95cSBarry Smith     Not collective
89b9cd556bSLois Curfman McInnes 
90a997ad1aSLois Curfman McInnes     Input Parameter:
918c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
922bdab257SBarry Smith 
93a997ad1aSLois Curfman McInnes     Output Parameter:
942bdab257SBarry Smith .   mapping - new mapping data structure
952bdab257SBarry Smith 
96f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
97a997ad1aSLois Curfman McInnes     Level: advanced
98a997ad1aSLois Curfman McInnes 
99273d9f13SBarry Smith     Concepts: mapping^local to global
1002bdab257SBarry Smith 
1012bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1022bdab257SBarry Smith @*/
1037087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1042bdab257SBarry Smith {
1056849ba73SBarry Smith   PetscErrorCode ierr;
1063bbf0e92SBarry Smith   PetscInt       n,bs;
1075d0c19d7SBarry Smith   const PetscInt *indices;
1082bdab257SBarry Smith   MPI_Comm       comm;
1093bbf0e92SBarry Smith   PetscBool      isblock;
1103a40ed3dSBarry Smith 
1113a40ed3dSBarry Smith   PetscFunctionBegin;
1120700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1134482741eSBarry Smith   PetscValidPointer(mapping,2);
1142bdab257SBarry Smith 
1152bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1163b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1173bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1186006e8d2SBarry Smith   if (!isblock) {
119f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
120f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1212bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1226006e8d2SBarry Smith   } else {
1236006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
124f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
12528bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
126f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1276006e8d2SBarry Smith   }
1283a40ed3dSBarry Smith   PetscFunctionReturn(0);
1292bdab257SBarry Smith }
1305a5d4f66SBarry Smith 
131a4d96a55SJed Brown #undef __FUNCT__
132a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
133a4d96a55SJed Brown /*@C
134a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
135a4d96a55SJed Brown     ordering and a global parallel ordering.
136a4d96a55SJed Brown 
137a4d96a55SJed Brown     Collective
138a4d96a55SJed Brown 
139a4d96a55SJed Brown     Input Parameter:
140a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
141a4d96a55SJed Brown -   start - first global index on this process
142a4d96a55SJed Brown 
143a4d96a55SJed Brown     Output Parameter:
144a4d96a55SJed Brown .   mapping - new mapping data structure
145a4d96a55SJed Brown 
146a4d96a55SJed Brown     Level: advanced
147a4d96a55SJed Brown 
148a4d96a55SJed Brown     Concepts: mapping^local to global
149a4d96a55SJed Brown 
150a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
151a4d96a55SJed Brown @*/
152a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
153a4d96a55SJed Brown {
154a4d96a55SJed Brown   PetscErrorCode ierr;
155a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
156a4d96a55SJed Brown   const PetscInt *ilocal;
157a4d96a55SJed Brown   MPI_Comm       comm;
158a4d96a55SJed Brown 
159a4d96a55SJed Brown   PetscFunctionBegin;
160a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
161a4d96a55SJed Brown   PetscValidPointer(mapping,3);
162a4d96a55SJed Brown 
163a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1640298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
165f6e5521dSKarl Rupp   if (ilocal) {
166f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
167f6e5521dSKarl Rupp   }
168a4d96a55SJed Brown   else maxlocal = nleaves;
169785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
170785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
171a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
172a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
173a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
174a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
175f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
176a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
177a4d96a55SJed Brown   PetscFunctionReturn(0);
178a4d96a55SJed Brown }
179b46b645bSBarry Smith 
1804a2ae208SSatish Balay #undef __FUNCT__
18163fa5c83Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingSetBlockSize"
18263fa5c83Sstefano_zampini /*@
18363fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
18463fa5c83Sstefano_zampini 
18563fa5c83Sstefano_zampini     Not collective
18663fa5c83Sstefano_zampini 
18763fa5c83Sstefano_zampini     Input Parameters:
18863fa5c83Sstefano_zampini .   mapping - mapping data structure
18963fa5c83Sstefano_zampini .   bs - the blocksize
19063fa5c83Sstefano_zampini 
19163fa5c83Sstefano_zampini     Level: advanced
19263fa5c83Sstefano_zampini 
19363fa5c83Sstefano_zampini     Concepts: mapping^local to global
19463fa5c83Sstefano_zampini 
19563fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
19663fa5c83Sstefano_zampini @*/
19763fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
19863fa5c83Sstefano_zampini {
19963fa5c83Sstefano_zampini   PetscInt       *nid,*oid;
200*8b7cb0e6Sstefano_zampini   PetscInt       i,cn,on,obs,nn,cum,r,rbs,ri;
20163fa5c83Sstefano_zampini   PetscErrorCode ierr;
20263fa5c83Sstefano_zampini 
20363fa5c83Sstefano_zampini   PetscFunctionBegin;
20463fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
20563fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
20663fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
20763fa5c83Sstefano_zampini   on  = mapping->n;
20863fa5c83Sstefano_zampini   obs = mapping->bs;
20963fa5c83Sstefano_zampini   oid = mapping->indices;
21063fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
21163fa5c83Sstefano_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);
212*8b7cb0e6Sstefano_zampini   if (bs < obs && obs%bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D",bs,obs);
213*8b7cb0e6Sstefano_zampini   if (bs < obs) {
214*8b7cb0e6Sstefano_zampini     r   = bs;
215*8b7cb0e6Sstefano_zampini     rbs = obs/bs;
216*8b7cb0e6Sstefano_zampini     ri  = 1;
217*8b7cb0e6Sstefano_zampini   } else {
218*8b7cb0e6Sstefano_zampini     r   = obs;
219*8b7cb0e6Sstefano_zampini     rbs = 1;
220*8b7cb0e6Sstefano_zampini     ri  = bs/obs;
221*8b7cb0e6Sstefano_zampini   }
22263fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
223c9345713Sstefano_zampini   for (i=0,cum=0,cn=0;i<on;i++) {
224*8b7cb0e6Sstefano_zampini     if (oid[i] < 0) cn += r;
225*8b7cb0e6Sstefano_zampini     if ((cn && !(cn%bs)) || (oid[i] > -1 && !((oid[i]*obs)%bs))) {
22663fa5c83Sstefano_zampini       if (cum == nn) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices",bs,obs);
227*8b7cb0e6Sstefano_zampini       if (cn && cn%bs) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices (neg = %D, rbs %D, r %D)",bs,obs,cn,rbs,r);
228*8b7cb0e6Sstefano_zampini       if (cn) {
229*8b7cb0e6Sstefano_zampini         PetscInt j;
230*8b7cb0e6Sstefano_zampini         for (j=0;j<rbs;j++) nid[cum++] = -1;
231*8b7cb0e6Sstefano_zampini       } else {
232*8b7cb0e6Sstefano_zampini         PetscInt j;
233*8b7cb0e6Sstefano_zampini         for (j=1;j<ri;j++) {
234*8b7cb0e6Sstefano_zampini           if (i+j >= on) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices found",bs,obs);
235*8b7cb0e6Sstefano_zampini           if (oid[i] != oid[i+j]-j) SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices %D %D (%D,%D)",bs,obs,oid[i],oid[i+j],j,ri);
236*8b7cb0e6Sstefano_zampini         }
237*8b7cb0e6Sstefano_zampini         for (j=0;j<rbs;j++) nid[cum++] = (oid[i]*obs)/bs+j;
238*8b7cb0e6Sstefano_zampini       }
239c9345713Sstefano_zampini       cn   = 0;
24063fa5c83Sstefano_zampini     }
24163fa5c83Sstefano_zampini   }
242c9345713Sstefano_zampini   if (cum != nn || cn) {
24363fa5c83Sstefano_zampini     ierr = PetscFree(nid);CHKERRQ(ierr);
244*8b7cb0e6Sstefano_zampini     SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Incompatible block sizes %D and %D (new block indices found %D != %D, neg %D, rbs %D)",bs,obs,cum,nn,cn,rbs);
24563fa5c83Sstefano_zampini   }
24663fa5c83Sstefano_zampini   mapping->n           = nn;
24763fa5c83Sstefano_zampini   mapping->bs          = bs;
24863fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
24963fa5c83Sstefano_zampini   mapping->indices     = nid;
250c9345713Sstefano_zampini   ierr                 = PetscFree(mapping->globals);CHKERRQ(ierr);
251c9345713Sstefano_zampini   mapping->globalstart = 0;
252c9345713Sstefano_zampini   mapping->globalend   = 0;
25363fa5c83Sstefano_zampini   PetscFunctionReturn(0);
25463fa5c83Sstefano_zampini }
25563fa5c83Sstefano_zampini 
25663fa5c83Sstefano_zampini #undef __FUNCT__
25745b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
25845b6f7e9SBarry Smith /*@
25945b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
26045b6f7e9SBarry Smith     ordering and a global parallel ordering.
26145b6f7e9SBarry Smith 
26245b6f7e9SBarry Smith     Not Collective
26345b6f7e9SBarry Smith 
26445b6f7e9SBarry Smith     Input Parameters:
26545b6f7e9SBarry Smith .   mapping - mapping data structure
26645b6f7e9SBarry Smith 
26745b6f7e9SBarry Smith     Output Parameter:
26845b6f7e9SBarry Smith .   bs - the blocksize
26945b6f7e9SBarry Smith 
27045b6f7e9SBarry Smith     Level: advanced
27145b6f7e9SBarry Smith 
27245b6f7e9SBarry Smith     Concepts: mapping^local to global
27345b6f7e9SBarry Smith 
27445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
27545b6f7e9SBarry Smith @*/
27645b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
27745b6f7e9SBarry Smith {
27845b6f7e9SBarry Smith   PetscFunctionBegin;
279cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
28045b6f7e9SBarry Smith   *bs = mapping->bs;
28145b6f7e9SBarry Smith   PetscFunctionReturn(0);
28245b6f7e9SBarry Smith }
28345b6f7e9SBarry Smith 
28445b6f7e9SBarry Smith #undef __FUNCT__
2854a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
286ba5bb76aSSatish Balay /*@
28790f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
28890f02eecSBarry Smith     ordering and a global parallel ordering.
2892362add9SBarry Smith 
29089d82c54SBarry Smith     Not Collective, but communicator may have more than one process
291b9cd556bSLois Curfman McInnes 
2922362add9SBarry Smith     Input Parameters:
29389d82c54SBarry Smith +   comm - MPI communicator
294f0413b6fSBarry Smith .   bs - the block size
29528bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
29628bc9809SBarry 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
297d5ad8652SBarry Smith -   mode - see PetscCopyMode
2982362add9SBarry Smith 
299a997ad1aSLois Curfman McInnes     Output Parameter:
30090f02eecSBarry Smith .   mapping - new mapping data structure
3012362add9SBarry Smith 
302f0413b6fSBarry 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
303a997ad1aSLois Curfman McInnes     Level: advanced
304a997ad1aSLois Curfman McInnes 
305273d9f13SBarry Smith     Concepts: mapping^local to global
3062362add9SBarry Smith 
307d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
3082362add9SBarry Smith @*/
30960c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
3102362add9SBarry Smith {
3116849ba73SBarry Smith   PetscErrorCode ierr;
31232dcc486SBarry Smith   PetscInt       *in;
313b46b645bSBarry Smith 
314b46b645bSBarry Smith   PetscFunctionBegin;
31573911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
3164482741eSBarry Smith   PetscValidPointer(mapping,4);
317b46b645bSBarry Smith 
3180298fd71SBarry Smith   *mapping = NULL;
319607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
3202362add9SBarry Smith 
32173107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
32260c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
323d4bb536fSBarry Smith   (*mapping)->n             = n;
324f0413b6fSBarry Smith   (*mapping)->bs            = bs;
325268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
326268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
327268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
328268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
329268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
330d4bb536fSBarry Smith   /*
331d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
332d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
333d4bb536fSBarry Smith   */
334d4bb536fSBarry Smith   (*mapping)->globals = 0;
335d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
336785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
337d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
338d5ad8652SBarry Smith     (*mapping)->indices = in;
3396389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3406389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
3416389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
3426389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3436389a1a1SBarry Smith   }
34460c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
345d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
3463a40ed3dSBarry Smith   PetscFunctionReturn(0);
3472362add9SBarry Smith }
3482362add9SBarry Smith 
3494a2ae208SSatish Balay #undef __FUNCT__
3504a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
35190f02eecSBarry Smith /*@
35290f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
35390f02eecSBarry Smith    ordering and a global parallel ordering.
35490f02eecSBarry Smith 
3550f5bd95cSBarry Smith    Note Collective
356b9cd556bSLois Curfman McInnes 
35790f02eecSBarry Smith    Input Parameters:
35890f02eecSBarry Smith .  mapping - mapping data structure
35990f02eecSBarry Smith 
360a997ad1aSLois Curfman McInnes    Level: advanced
361a997ad1aSLois Curfman McInnes 
3623acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
36390f02eecSBarry Smith @*/
3646bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
36590f02eecSBarry Smith {
366dfbe8321SBarry Smith   PetscErrorCode ierr;
3675fd66863SKarl Rupp 
3683a40ed3dSBarry Smith   PetscFunctionBegin;
3696bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3706bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
371997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3726bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3736bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
374268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
375268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
376268a049cSStefano Zampini   if ((*mapping)->info_indices) {
377268a049cSStefano Zampini     PetscInt i;
378268a049cSStefano Zampini 
379268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
380268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
381268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
382268a049cSStefano Zampini     }
383268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
384268a049cSStefano Zampini   }
385d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
386992144d0SBarry Smith   *mapping = 0;
3873a40ed3dSBarry Smith   PetscFunctionReturn(0);
38890f02eecSBarry Smith }
38990f02eecSBarry Smith 
3904a2ae208SSatish Balay #undef __FUNCT__
3914a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
39290f02eecSBarry Smith /*@
3933acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3943acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3953acfe500SLois Curfman McInnes     context.
39690f02eecSBarry Smith 
397b9cd556bSLois Curfman McInnes     Not collective
398b9cd556bSLois Curfman McInnes 
39990f02eecSBarry Smith     Input Parameters:
400b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
401b9cd556bSLois Curfman McInnes -   is - index set in local numbering
40290f02eecSBarry Smith 
40390f02eecSBarry Smith     Output Parameters:
40490f02eecSBarry Smith .   newis - index set in global numbering
40590f02eecSBarry Smith 
406a997ad1aSLois Curfman McInnes     Level: advanced
407a997ad1aSLois Curfman McInnes 
408273d9f13SBarry Smith     Concepts: mapping^local to global
4093acfe500SLois Curfman McInnes 
41090f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
411d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
41290f02eecSBarry Smith @*/
4137087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
41490f02eecSBarry Smith {
4156849ba73SBarry Smith   PetscErrorCode ierr;
416e24637baSBarry Smith   PetscInt       n,*idxout;
4175d0c19d7SBarry Smith   const PetscInt *idxin;
4183a40ed3dSBarry Smith 
4193a40ed3dSBarry Smith   PetscFunctionBegin;
4200700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
4210700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
4224482741eSBarry Smith   PetscValidPointer(newis,3);
42390f02eecSBarry Smith 
4243b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
42590f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
426785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
427e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
4283b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
429543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4303a40ed3dSBarry Smith   PetscFunctionReturn(0);
43190f02eecSBarry Smith }
43290f02eecSBarry Smith 
433afcb2eb5SJed Brown #undef __FUNCT__
434afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
435b89cb25eSSatish Balay /*@
4363acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4373acfe500SLois Curfman McInnes    and converts them to the global numbering.
43890f02eecSBarry Smith 
439b9cd556bSLois Curfman McInnes    Not collective
440b9cd556bSLois Curfman McInnes 
441bb25748dSBarry Smith    Input Parameters:
442b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
443bb25748dSBarry Smith .  N - number of integers
444b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
445bb25748dSBarry Smith 
446bb25748dSBarry Smith    Output Parameter:
447bb25748dSBarry Smith .  out - indices in global numbering
448bb25748dSBarry Smith 
449b9cd556bSLois Curfman McInnes    Notes:
450b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
451d4bb536fSBarry Smith 
452a997ad1aSLois Curfman McInnes    Level: advanced
453a997ad1aSLois Curfman McInnes 
45445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4550752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
456d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
457bb25748dSBarry Smith 
458273d9f13SBarry Smith     Concepts: mapping^local to global
459afcb2eb5SJed Brown @*/
460afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
461afcb2eb5SJed Brown {
462cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
46345b6f7e9SBarry Smith 
46445b6f7e9SBarry Smith   PetscFunctionBegin;
465cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
466cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
467cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
46845b6f7e9SBarry Smith   if (bs == 1) {
469cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
47045b6f7e9SBarry Smith     for (i=0; i<N; i++) {
47145b6f7e9SBarry Smith       if (in[i] < 0) {
47245b6f7e9SBarry Smith         out[i] = in[i];
47345b6f7e9SBarry Smith         continue;
47445b6f7e9SBarry Smith       }
475e24637baSBarry 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);
47645b6f7e9SBarry Smith       out[i] = idx[in[i]];
47745b6f7e9SBarry Smith     }
47845b6f7e9SBarry Smith   } else {
479cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
48045b6f7e9SBarry Smith     for (i=0; i<N; i++) {
48145b6f7e9SBarry Smith       if (in[i] < 0) {
48245b6f7e9SBarry Smith         out[i] = in[i];
48345b6f7e9SBarry Smith         continue;
48445b6f7e9SBarry Smith       }
485e24637baSBarry 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);
48645b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
48745b6f7e9SBarry Smith     }
48845b6f7e9SBarry Smith   }
48945b6f7e9SBarry Smith   PetscFunctionReturn(0);
49045b6f7e9SBarry Smith }
49145b6f7e9SBarry Smith 
49245b6f7e9SBarry Smith #undef __FUNCT__
49345b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
49445b6f7e9SBarry Smith /*@
4956006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
49645b6f7e9SBarry Smith 
49745b6f7e9SBarry Smith    Not collective
49845b6f7e9SBarry Smith 
49945b6f7e9SBarry Smith    Input Parameters:
50045b6f7e9SBarry Smith +  mapping - the local to global mapping context
50145b6f7e9SBarry Smith .  N - number of integers
5026006e8d2SBarry Smith -  in - input indices in local block numbering
50345b6f7e9SBarry Smith 
50445b6f7e9SBarry Smith    Output Parameter:
5056006e8d2SBarry Smith .  out - indices in global block numbering
50645b6f7e9SBarry Smith 
50745b6f7e9SBarry Smith    Notes:
50845b6f7e9SBarry Smith    The in and out array parameters may be identical.
50945b6f7e9SBarry Smith 
5106006e8d2SBarry Smith    Example:
5116006e8d2SBarry 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
5126006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
5136006e8d2SBarry Smith 
51445b6f7e9SBarry Smith    Level: advanced
51545b6f7e9SBarry Smith 
51645b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
51745b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
51845b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
51945b6f7e9SBarry Smith 
52045b6f7e9SBarry Smith     Concepts: mapping^local to global
52145b6f7e9SBarry Smith @*/
52245b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
52345b6f7e9SBarry Smith {
524cbc1caf0SMatthew G. Knepley 
525cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
526cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
527cbc1caf0SMatthew G. Knepley   {
528afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
529afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
530d4bb536fSBarry Smith 
531afcb2eb5SJed Brown     for (i=0; i<N; i++) {
532afcb2eb5SJed Brown       if (in[i] < 0) {
533afcb2eb5SJed Brown         out[i] = in[i];
534afcb2eb5SJed Brown         continue;
535afcb2eb5SJed Brown       }
536e24637baSBarry 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);
537afcb2eb5SJed Brown       out[i] = idx[in[i]];
538afcb2eb5SJed Brown     }
539cbc1caf0SMatthew G. Knepley   }
540afcb2eb5SJed Brown   PetscFunctionReturn(0);
541afcb2eb5SJed Brown }
542d4bb536fSBarry Smith 
543d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
544d4bb536fSBarry Smith 
5454a2ae208SSatish Balay #undef __FUNCT__
5464a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
547d4bb536fSBarry Smith /*
548d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
549d4bb536fSBarry Smith */
5506849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
551d4bb536fSBarry Smith {
5526849ba73SBarry Smith   PetscErrorCode ierr;
55332dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
554d4bb536fSBarry Smith 
5553a40ed3dSBarry Smith   PetscFunctionBegin;
556d4bb536fSBarry Smith   end   = 0;
557ec268f7cSJed Brown   start = PETSC_MAX_INT;
558d4bb536fSBarry Smith 
559d4bb536fSBarry Smith   for (i=0; i<n; i++) {
560d4bb536fSBarry Smith     if (idx[i] < 0) continue;
561d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
562d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
563d4bb536fSBarry Smith   }
564d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
565d4bb536fSBarry Smith   mapping->globalstart = start;
566d4bb536fSBarry Smith   mapping->globalend   = end;
567d4bb536fSBarry Smith 
568854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
569b0a32e0cSBarry Smith   mapping->globals = globals;
570f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
571d4bb536fSBarry Smith   for (i=0; i<n; i++) {
572d4bb536fSBarry Smith     if (idx[i] < 0) continue;
573d4bb536fSBarry Smith     globals[idx[i] - start] = i;
574d4bb536fSBarry Smith   }
575d4bb536fSBarry Smith 
5763bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5773a40ed3dSBarry Smith   PetscFunctionReturn(0);
578d4bb536fSBarry Smith }
579d4bb536fSBarry Smith 
5804a2ae208SSatish Balay #undef __FUNCT__
5814a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
582d4bb536fSBarry Smith /*@
583a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
584a997ad1aSLois Curfman McInnes     specified with a global numbering.
585d4bb536fSBarry Smith 
586b9cd556bSLois Curfman McInnes     Not collective
587b9cd556bSLois Curfman McInnes 
588d4bb536fSBarry Smith     Input Parameters:
589b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
590d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
591d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
592d4bb536fSBarry Smith .   n - number of global indices to map
593b9cd556bSLois Curfman McInnes -   idx - global indices to map
594d4bb536fSBarry Smith 
595d4bb536fSBarry Smith     Output Parameters:
596b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
597b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
598e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5990298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
600e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
601e182c471SBarry Smith              a second time to set the values.
602d4bb536fSBarry Smith 
603b9cd556bSLois Curfman McInnes     Notes:
6040298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
605d4bb536fSBarry Smith 
6060f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6070f5bd95cSBarry Smith     array to compute these.
6080f5bd95cSBarry Smith 
609a997ad1aSLois Curfman McInnes     Level: advanced
610a997ad1aSLois Curfman McInnes 
61132fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
61232fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
61332fd6b96SBarry Smith 
614273d9f13SBarry Smith     Concepts: mapping^global to local
615d4bb536fSBarry Smith 
6169d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
617d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
618d4bb536fSBarry Smith @*/
6197087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
62032dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
621d4bb536fSBarry Smith {
6229d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
6239d90f715SBarry Smith   PetscErrorCode ierr;
6249d90f715SBarry Smith 
6259d90f715SBarry Smith   PetscFunctionBegin;
6269d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6279d90f715SBarry Smith   if (!mapping->globals) {
6289d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
6299d90f715SBarry Smith   }
6309d90f715SBarry Smith   globals = mapping->globals;
6319d90f715SBarry Smith   start   = mapping->globalstart;
6329d90f715SBarry Smith   end     = mapping->globalend;
6339d90f715SBarry Smith   bs      = mapping->bs;
6349d90f715SBarry Smith 
6359d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
6369d90f715SBarry Smith     if (idxout) {
6379d90f715SBarry Smith       for (i=0; i<n; i++) {
6389d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
6399d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
640663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
6419d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6429d90f715SBarry Smith       }
6439d90f715SBarry Smith     }
6449d90f715SBarry Smith     if (nout) *nout = n;
6459d90f715SBarry Smith   } else {
6469d90f715SBarry Smith     if (idxout) {
6479d90f715SBarry Smith       for (i=0; i<n; i++) {
6489d90f715SBarry Smith         if (idx[i] < 0) continue;
6499d90f715SBarry Smith         if (idx[i] < bs*start) continue;
650663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6519d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6529d90f715SBarry Smith         if (tmp < 0) continue;
6539d90f715SBarry Smith         idxout[nf++] = tmp;
6549d90f715SBarry Smith       }
6559d90f715SBarry Smith     } else {
6569d90f715SBarry Smith       for (i=0; i<n; i++) {
6579d90f715SBarry Smith         if (idx[i] < 0) continue;
6589d90f715SBarry Smith         if (idx[i] < bs*start) continue;
659663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6609d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6619d90f715SBarry Smith         if (tmp < 0) continue;
6629d90f715SBarry Smith         nf++;
6639d90f715SBarry Smith       }
6649d90f715SBarry Smith     }
6659d90f715SBarry Smith     if (nout) *nout = nf;
6669d90f715SBarry Smith   }
6679d90f715SBarry Smith   PetscFunctionReturn(0);
6689d90f715SBarry Smith }
6699d90f715SBarry Smith 
6709d90f715SBarry Smith #undef __FUNCT__
671d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
672d4fe737eSStefano Zampini /*@
673d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
674d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
675d4fe737eSStefano Zampini     context.
676d4fe737eSStefano Zampini 
677d4fe737eSStefano Zampini     Not collective
678d4fe737eSStefano Zampini 
679d4fe737eSStefano Zampini     Input Parameters:
680d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
681d4fe737eSStefano Zampini -   is - index set in global numbering
682d4fe737eSStefano Zampini 
683d4fe737eSStefano Zampini     Output Parameters:
684d4fe737eSStefano Zampini .   newis - index set in local numbering
685d4fe737eSStefano Zampini 
686d4fe737eSStefano Zampini     Level: advanced
687d4fe737eSStefano Zampini 
688d4fe737eSStefano Zampini     Concepts: mapping^local to global
689d4fe737eSStefano Zampini 
690d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
691d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
692d4fe737eSStefano Zampini @*/
693d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
694d4fe737eSStefano Zampini {
695d4fe737eSStefano Zampini   PetscErrorCode ierr;
696d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
697d4fe737eSStefano Zampini   const PetscInt *idxin;
698d4fe737eSStefano Zampini 
699d4fe737eSStefano Zampini   PetscFunctionBegin;
700d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
701d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
702d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
703d4fe737eSStefano Zampini 
704d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
705d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
706d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
707d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
708d4fe737eSStefano Zampini   } else {
709d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
710d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
711d4fe737eSStefano Zampini   }
712d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
713d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
714d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
715d4fe737eSStefano Zampini   PetscFunctionReturn(0);
716d4fe737eSStefano Zampini }
717d4fe737eSStefano Zampini 
718d4fe737eSStefano Zampini #undef __FUNCT__
7199d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
7209d90f715SBarry Smith /*@
7219d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
7229d90f715SBarry Smith     specified with a block global numbering.
7239d90f715SBarry Smith 
7249d90f715SBarry Smith     Not collective
7259d90f715SBarry Smith 
7269d90f715SBarry Smith     Input Parameters:
7279d90f715SBarry Smith +   mapping - mapping between local and global numbering
7289d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
7299d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
7309d90f715SBarry Smith .   n - number of global indices to map
7319d90f715SBarry Smith -   idx - global indices to map
7329d90f715SBarry Smith 
7339d90f715SBarry Smith     Output Parameters:
7349d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
7359d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
7369d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
7379d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
7389d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
7399d90f715SBarry Smith              a second time to set the values.
7409d90f715SBarry Smith 
7419d90f715SBarry Smith     Notes:
7429d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
7439d90f715SBarry Smith 
7449d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
7459d90f715SBarry Smith     array to compute these.
7469d90f715SBarry Smith 
7479d90f715SBarry Smith     Level: advanced
7489d90f715SBarry Smith 
7499d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
7509d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
7519d90f715SBarry Smith 
7529d90f715SBarry Smith     Concepts: mapping^global to local
7539d90f715SBarry Smith 
7549d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7559d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7569d90f715SBarry Smith @*/
7579d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7589d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7599d90f715SBarry Smith {
76032dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
7616849ba73SBarry Smith   PetscErrorCode ierr;
762d4bb536fSBarry Smith 
7633a40ed3dSBarry Smith   PetscFunctionBegin;
7640700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
765d4bb536fSBarry Smith   if (!mapping->globals) {
766d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
767d4bb536fSBarry Smith   }
768d4bb536fSBarry Smith   globals = mapping->globals;
769d4bb536fSBarry Smith   start   = mapping->globalstart;
770d4bb536fSBarry Smith   end     = mapping->globalend;
771d4bb536fSBarry Smith 
772d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
773d4bb536fSBarry Smith     if (idxout) {
774d4bb536fSBarry Smith       for (i=0; i<n; i++) {
775d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
776d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
777d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
778d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
779d4bb536fSBarry Smith       }
780d4bb536fSBarry Smith     }
781d4bb536fSBarry Smith     if (nout) *nout = n;
782d4bb536fSBarry Smith   } else {
783d4bb536fSBarry Smith     if (idxout) {
784d4bb536fSBarry Smith       for (i=0; i<n; i++) {
785d4bb536fSBarry Smith         if (idx[i] < 0) continue;
786d4bb536fSBarry Smith         if (idx[i] < start) continue;
787d4bb536fSBarry Smith         if (idx[i] > end) continue;
788d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
789d4bb536fSBarry Smith         if (tmp < 0) continue;
790d4bb536fSBarry Smith         idxout[nf++] = tmp;
791d4bb536fSBarry Smith       }
792d4bb536fSBarry Smith     } else {
793d4bb536fSBarry Smith       for (i=0; i<n; i++) {
794d4bb536fSBarry Smith         if (idx[i] < 0) continue;
795d4bb536fSBarry Smith         if (idx[i] < start) continue;
796d4bb536fSBarry Smith         if (idx[i] > end) continue;
797d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
798d4bb536fSBarry Smith         if (tmp < 0) continue;
799d4bb536fSBarry Smith         nf++;
800d4bb536fSBarry Smith       }
801d4bb536fSBarry Smith     }
802d4bb536fSBarry Smith     if (nout) *nout = nf;
803d4bb536fSBarry Smith   }
8043a40ed3dSBarry Smith   PetscFunctionReturn(0);
805d4bb536fSBarry Smith }
80690f02eecSBarry Smith 
8074a2ae208SSatish Balay #undef __FUNCT__
8086a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
80989d82c54SBarry Smith /*@C
8106a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
81189d82c54SBarry Smith      each index shared by more than one processor
81289d82c54SBarry Smith 
81389d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
81489d82c54SBarry Smith 
81589d82c54SBarry Smith     Input Parameters:
81689d82c54SBarry Smith .   mapping - the mapping from local to global indexing
81789d82c54SBarry Smith 
81889d82c54SBarry Smith     Output Parameter:
81989d82c54SBarry Smith +   nproc - number of processors that are connected to this one
82089d82c54SBarry Smith .   proc - neighboring processors
82107b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
8223463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
82389d82c54SBarry Smith 
82489d82c54SBarry Smith     Level: advanced
82589d82c54SBarry Smith 
826273d9f13SBarry Smith     Concepts: mapping^local to global
82789d82c54SBarry Smith 
8282cfcea29SBarry Smith     Fortran Usage:
8292cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
8302cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
8312cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
8322cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
8332cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
8342cfcea29SBarry Smith 
8352cfcea29SBarry Smith 
83607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
83707b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
83889d82c54SBarry Smith @*/
8396a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
84089d82c54SBarry Smith {
8416849ba73SBarry Smith   PetscErrorCode ierr;
842268a049cSStefano Zampini 
843268a049cSStefano Zampini   PetscFunctionBegin;
844268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
845268a049cSStefano Zampini   if (mapping->info_cached) {
846268a049cSStefano Zampini     *nproc = mapping->info_nproc;
847268a049cSStefano Zampini     *procs = mapping->info_procs;
848268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
849268a049cSStefano Zampini     *indices = mapping->info_indices;
850268a049cSStefano Zampini   } else {
851268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
852268a049cSStefano Zampini   }
853268a049cSStefano Zampini   PetscFunctionReturn(0);
854268a049cSStefano Zampini }
855268a049cSStefano Zampini 
856268a049cSStefano Zampini #undef __FUNCT__
857268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
858268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
859268a049cSStefano Zampini {
860268a049cSStefano Zampini   PetscErrorCode ierr;
86197f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
86232dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
86332dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
86497f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
86532dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
86632dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
86789d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
86830dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
869ce94432eSBarry Smith   MPI_Comm       comm;
870ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
87189d82c54SBarry Smith 
87289d82c54SBarry Smith   PetscFunctionBegin;
873ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
87424cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
87524cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
87624cf384cSBarry Smith   if (size == 1) {
87724cf384cSBarry Smith     *nproc         = 0;
8780298fd71SBarry Smith     *procs         = NULL;
87995dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
8801e2105dcSBarry Smith     (*numprocs)[0] = 0;
88195dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
8820298fd71SBarry Smith     (*indices)[0]  = NULL;
883268a049cSStefano Zampini     /* save info for reuse */
884268a049cSStefano Zampini     mapping->info_nproc = *nproc;
885268a049cSStefano Zampini     mapping->info_procs = *procs;
886268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
887268a049cSStefano Zampini     mapping->info_indices = *indices;
888268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
88924cf384cSBarry Smith     PetscFunctionReturn(0);
89024cf384cSBarry Smith   }
89124cf384cSBarry Smith 
892c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
89307b52d57SBarry Smith 
8943677ff5aSBarry Smith   /*
8956a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
8963677ff5aSBarry Smith 
8973677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
8983677ff5aSBarry Smith            numbering, just for this routine.
8993677ff5aSBarry Smith 
9003677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
9013677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
9023677ff5aSBarry Smith 
9033677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
9043677ff5aSBarry Smith 
9053677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
9063677ff5aSBarry Smith            local subdomain
9073677ff5aSBarry Smith   */
90824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
90924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
91024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
91189d82c54SBarry Smith 
91289d82c54SBarry Smith   for (i=0; i<n; i++) {
91389d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
91489d82c54SBarry Smith   }
915b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
91678058e43SBarry Smith   Ng++;
91789d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
91889d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
919bc8ff85bSBarry Smith   scale  = Ng/size + 1;
920a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
921caba0dd0SBarry Smith   rstart = scale*rank;
92289d82c54SBarry Smith 
92389d82c54SBarry Smith   /* determine ownership ranges of global indices */
924785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
92532dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
92689d82c54SBarry Smith 
92789d82c54SBarry Smith   /* determine owners of each local node  */
928785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
92989d82c54SBarry Smith   for (i=0; i<n; i++) {
9303677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
93127c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
9323677ff5aSBarry Smith     owner[i]         = proc;
93327c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
93489d82c54SBarry Smith   }
93527c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
9367904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
93789d82c54SBarry Smith 
93889d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
93927c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9407904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
94189d82c54SBarry Smith 
94289d82c54SBarry Smith   /* post receives for owned rows */
943785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
944854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
94589d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
94632dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
94789d82c54SBarry Smith   }
94889d82c54SBarry Smith 
94989d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
950854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
951854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
95289d82c54SBarry Smith   starts[0] = 0;
953f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
95489d82c54SBarry Smith   for (i=0; i<n; i++) {
95589d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
95630dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
95789d82c54SBarry Smith   }
95889d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
95989d82c54SBarry Smith   starts[0] = 0;
960f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
96189d82c54SBarry Smith 
96289d82c54SBarry Smith   /* send the messages */
963854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
964854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
96589d82c54SBarry Smith   cnt = 0;
96689d82c54SBarry Smith   for (i=0; i<size; i++) {
96727c402fcSBarry Smith     if (nprocs[2*i]) {
96832dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
96930dcb7c9SBarry Smith       dest[cnt] = i;
97089d82c54SBarry Smith       cnt++;
97189d82c54SBarry Smith     }
97289d82c54SBarry Smith   }
97389d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
97489d82c54SBarry Smith 
97589d82c54SBarry Smith   /* wait on receives */
976854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
977854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
97889d82c54SBarry Smith   cnt  = nrecvs;
979854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
98032dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
98189d82c54SBarry Smith   while (cnt) {
98289d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
98389d82c54SBarry Smith     /* unpack receives into our local space */
98432dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
98589d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
98630dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
987caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
98830dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
98989d82c54SBarry Smith     cnt--;
99089d82c54SBarry Smith   }
99189d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
99289d82c54SBarry Smith 
99330dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
994bc8ff85bSBarry Smith   nowned  = 0;
995bc8ff85bSBarry Smith   nownedm = 0;
996bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
997bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
998bc8ff85bSBarry Smith   }
999bc8ff85bSBarry Smith 
1000bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1001854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1002854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1003bc8ff85bSBarry Smith   starts[0] = 0;
1004bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1005bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1006bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1007bc8ff85bSBarry Smith   }
1008bc8ff85bSBarry Smith 
100930dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1010bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1011bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
101230dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1013f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1014bc8ff85bSBarry Smith     }
1015bc8ff85bSBarry Smith   }
1016bc8ff85bSBarry Smith 
101707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
101830dcb7c9SBarry Smith     starts[0] = 0;
101930dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
102030dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
102130dcb7c9SBarry Smith       else starts[i] = starts[i-1];
102230dcb7c9SBarry Smith     }
102330dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
102430dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
10257904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
102630dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
10277904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
102830dcb7c9SBarry Smith         }
102930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
103030dcb7c9SBarry Smith       }
103130dcb7c9SBarry Smith     }
10320ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
103307b52d57SBarry Smith   } /* -----------------------------------  */
103430dcb7c9SBarry Smith 
10353677ff5aSBarry Smith   /* wait on original sends */
10363a96401aSBarry Smith   if (nsends) {
1037785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
10383a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10393a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10403a96401aSBarry Smith   }
104189d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10423a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
10433677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
10443677ff5aSBarry Smith 
10453677ff5aSBarry Smith   /* pack messages to send back to local owners */
104630dcb7c9SBarry Smith   starts[0] = 0;
104730dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
104830dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
104930dcb7c9SBarry Smith     else starts[i] = starts[i-1];
105030dcb7c9SBarry Smith   }
105130dcb7c9SBarry Smith   nsends2 = nrecvs;
1052854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
105330dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
105430dcb7c9SBarry Smith     nprocs[i] = 1;
105530dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
105630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1057f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
105830dcb7c9SBarry Smith     }
105930dcb7c9SBarry Smith   }
1060f6e5521dSKarl Rupp   nt = 0;
1061f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1062f6e5521dSKarl Rupp 
1063854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1064854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1065f6e5521dSKarl Rupp 
1066f6e5521dSKarl Rupp   starts2[0] = 0;
1067f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
106830dcb7c9SBarry Smith   /*
106930dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
107030dcb7c9SBarry Smith        (0) the number of nodes being sent back
107130dcb7c9SBarry Smith        (1) the local node number,
107230dcb7c9SBarry Smith        (2) the number of processors sharing it,
107330dcb7c9SBarry Smith        (3) the processors sharing it
107430dcb7c9SBarry Smith   */
107530dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
107630dcb7c9SBarry Smith     cnt = 1;
107730dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
107830dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
107930dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
108030dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
108130dcb7c9SBarry Smith         sends2[starts2[i]]++;
108230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
108330dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
108432dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
108530dcb7c9SBarry Smith         cnt += nownedsenders[node];
108630dcb7c9SBarry Smith       }
108730dcb7c9SBarry Smith     }
108830dcb7c9SBarry Smith   }
108930dcb7c9SBarry Smith 
109030dcb7c9SBarry Smith   /* receive the message lengths */
109130dcb7c9SBarry Smith   nrecvs2 = nsends;
1092854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1093854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1094854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
109530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1096d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
109730dcb7c9SBarry Smith   }
1098d44834fbSBarry Smith 
10998a8e0b3aSBarry Smith   /* send the message lengths */
11008a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
11018a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
11028a8e0b3aSBarry Smith   }
11038a8e0b3aSBarry Smith 
1104d44834fbSBarry Smith   /* wait on receives of lens */
11050c468ba9SBarry Smith   if (nrecvs2) {
1106785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1107d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1108d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11090c468ba9SBarry Smith   }
1110a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1111d44834fbSBarry Smith 
111230dcb7c9SBarry Smith   starts3[0] = 0;
1113d44834fbSBarry Smith   nt         = 0;
111430dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
111530dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1116d44834fbSBarry Smith     nt          += lens2[i];
111730dcb7c9SBarry Smith   }
111876466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1119d44834fbSBarry Smith 
1120854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1121854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
112252b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
112332dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
112430dcb7c9SBarry Smith   }
112530dcb7c9SBarry Smith 
112630dcb7c9SBarry Smith   /* send the messages */
1127854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
112830dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
112932dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
113030dcb7c9SBarry Smith   }
113130dcb7c9SBarry Smith 
113230dcb7c9SBarry Smith   /* wait on receives */
11330c468ba9SBarry Smith   if (nrecvs2) {
1134785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
113530dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
113630dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11370c468ba9SBarry Smith   }
113830dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
113930dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
114030dcb7c9SBarry Smith 
114107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
114230dcb7c9SBarry Smith     cnt = 0;
114330dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
114430dcb7c9SBarry Smith       nt = recvs2[cnt++];
114530dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
11467904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
114730dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
11487904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
114930dcb7c9SBarry Smith         }
115030dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
115130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
115230dcb7c9SBarry Smith       }
115330dcb7c9SBarry Smith     }
11540ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
115507b52d57SBarry Smith   } /* -----------------------------------  */
115630dcb7c9SBarry Smith 
115730dcb7c9SBarry Smith   /* count number subdomains for each local node */
1158785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
115932dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
116030dcb7c9SBarry Smith   cnt  = 0;
116130dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
116230dcb7c9SBarry Smith     nt = recvs2[cnt++];
116330dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1164f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
116530dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
116630dcb7c9SBarry Smith     }
116730dcb7c9SBarry Smith   }
116830dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
116930dcb7c9SBarry Smith   *nproc    = nt;
1170854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1171854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1172854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
11730298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1174785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
117530dcb7c9SBarry Smith   cnt  = 0;
117630dcb7c9SBarry Smith   for (i=0; i<size; i++) {
117730dcb7c9SBarry Smith     if (nprocs[i] > 0) {
117830dcb7c9SBarry Smith       bprocs[i]        = cnt;
117930dcb7c9SBarry Smith       (*procs)[cnt]    = i;
118030dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1181785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
118230dcb7c9SBarry Smith       cnt++;
118330dcb7c9SBarry Smith     }
118430dcb7c9SBarry Smith   }
118530dcb7c9SBarry Smith 
118630dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
118732dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
118830dcb7c9SBarry Smith   cnt  = 0;
118930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
119030dcb7c9SBarry Smith     nt = recvs2[cnt++];
119130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1192f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
119330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
119430dcb7c9SBarry Smith     }
119530dcb7c9SBarry Smith   }
119630dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
119707b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
119830dcb7c9SBarry Smith 
119907b52d57SBarry Smith   /* sort the node indexing by their global numbers */
120007b52d57SBarry Smith   nt = *nproc;
120107b52d57SBarry Smith   for (i=0; i<nt; i++) {
1202854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1203f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
120407b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
120507b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
120607b52d57SBarry Smith   }
120707b52d57SBarry Smith 
120807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
120930dcb7c9SBarry Smith     nt = *nproc;
121030dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
12117904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
121230dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
12137904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
121430dcb7c9SBarry Smith       }
121530dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
121630dcb7c9SBarry Smith     }
12170ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
121807b52d57SBarry Smith   } /* -----------------------------------  */
121930dcb7c9SBarry Smith 
122030dcb7c9SBarry Smith   /* wait on sends */
122130dcb7c9SBarry Smith   if (nsends2) {
1222785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
122330dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
122430dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
122530dcb7c9SBarry Smith   }
122630dcb7c9SBarry Smith 
122730dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
122830dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
122930dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12303677ff5aSBarry Smith 
1231bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1232bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1233bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
123430dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
123530dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
123689d82c54SBarry Smith 
123789d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
123897f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
123989d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
12403a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
124130dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
124224cf384cSBarry Smith 
124324cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
124424cf384cSBarry Smith   first_procs    = (*procs)[0];
124524cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
124624cf384cSBarry Smith   first_indices  = (*indices)[0];
124724cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
124824cf384cSBarry Smith     if ((*procs)[i] == rank) {
124924cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
125024cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
125124cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
125224cf384cSBarry Smith       (*procs)[i]    = first_procs;
125324cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
125424cf384cSBarry Smith       (*indices)[i]  = first_indices;
125524cf384cSBarry Smith       break;
125624cf384cSBarry Smith     }
125724cf384cSBarry Smith   }
1258268a049cSStefano Zampini 
1259268a049cSStefano Zampini   /* save info for reuse */
1260268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1261268a049cSStefano Zampini   mapping->info_procs = *procs;
1262268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1263268a049cSStefano Zampini   mapping->info_indices = *indices;
1264268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
126589d82c54SBarry Smith   PetscFunctionReturn(0);
126689d82c54SBarry Smith }
126789d82c54SBarry Smith 
12684a2ae208SSatish Balay #undef __FUNCT__
12696a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
12706a818285SBarry Smith /*@C
12716a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
12726a818285SBarry Smith 
12736a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12746a818285SBarry Smith 
12756a818285SBarry Smith     Input Parameters:
12766a818285SBarry Smith .   mapping - the mapping from local to global indexing
12776a818285SBarry Smith 
12786a818285SBarry Smith     Output Parameter:
12796a818285SBarry Smith +   nproc - number of processors that are connected to this one
12806a818285SBarry Smith .   proc - neighboring processors
12816a818285SBarry Smith .   numproc - number of indices for each processor
12826a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12836a818285SBarry Smith 
12846a818285SBarry Smith     Level: advanced
12856a818285SBarry Smith 
12866a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12876a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
12886a818285SBarry Smith @*/
12896a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12906a818285SBarry Smith {
12916a818285SBarry Smith   PetscErrorCode ierr;
12926a818285SBarry Smith 
12936a818285SBarry Smith   PetscFunctionBegin;
1294cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1295268a049cSStefano Zampini   if (mapping->info_free) {
12966a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
12976a818285SBarry Smith     if (*indices) {
1298268a049cSStefano Zampini       PetscInt i;
1299268a049cSStefano Zampini 
13006a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
13016a818285SBarry Smith       for (i=1; i<*nproc; i++) {
13026a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
13036a818285SBarry Smith       }
13046a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
13056a818285SBarry Smith     }
1306268a049cSStefano Zampini   }
1307268a049cSStefano Zampini   *nproc = 0;
1308268a049cSStefano Zampini   *procs = NULL;
1309268a049cSStefano Zampini   *numprocs = NULL;
1310268a049cSStefano Zampini   *indices = NULL;
13116a818285SBarry Smith   PetscFunctionReturn(0);
13126a818285SBarry Smith }
13136a818285SBarry Smith 
13146a818285SBarry Smith #undef __FUNCT__
13156a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
13166a818285SBarry Smith /*@C
13176a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
13186a818285SBarry Smith      each index shared by more than one processor
13196a818285SBarry Smith 
13206a818285SBarry Smith     Collective on ISLocalToGlobalMapping
13216a818285SBarry Smith 
13226a818285SBarry Smith     Input Parameters:
13236a818285SBarry Smith .   mapping - the mapping from local to global indexing
13246a818285SBarry Smith 
13256a818285SBarry Smith     Output Parameter:
13266a818285SBarry Smith +   nproc - number of processors that are connected to this one
13276a818285SBarry Smith .   proc - neighboring processors
13286a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
13296a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
13306a818285SBarry Smith 
13316a818285SBarry Smith     Level: advanced
13326a818285SBarry Smith 
13336a818285SBarry Smith     Concepts: mapping^local to global
13346a818285SBarry Smith 
13356a818285SBarry Smith     Fortran Usage:
13366a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
13376a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
13386a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
13396a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
13406a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
13416a818285SBarry Smith 
13426a818285SBarry Smith 
13436a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13446a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
13456a818285SBarry Smith @*/
13466a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13476a818285SBarry Smith {
13486a818285SBarry Smith   PetscErrorCode ierr;
1349268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
13506a818285SBarry Smith 
13516a818285SBarry Smith   PetscFunctionBegin;
13526a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1353268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1354268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1355732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1356268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13576a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1358268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1359268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13606a818285SBarry Smith         for (k=0; k<bs; k++) {
13616a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13626a818285SBarry Smith         }
13636a818285SBarry Smith       }
1364268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13656a818285SBarry Smith     }
1366268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1367268a049cSStefano Zampini   } else {
1368268a049cSStefano Zampini     *numprocs = bnumprocs;
1369268a049cSStefano Zampini     *indices  = bindices;
13706a818285SBarry Smith   }
13716a818285SBarry Smith   PetscFunctionReturn(0);
13726a818285SBarry Smith }
13736a818285SBarry Smith 
13746a818285SBarry Smith #undef __FUNCT__
13754a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
137607b52d57SBarry Smith /*@C
137707b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
137889d82c54SBarry Smith 
137907b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
138007b52d57SBarry Smith 
138107b52d57SBarry Smith     Input Parameters:
138207b52d57SBarry Smith .   mapping - the mapping from local to global indexing
138307b52d57SBarry Smith 
138407b52d57SBarry Smith     Output Parameter:
138507b52d57SBarry Smith +   nproc - number of processors that are connected to this one
138607b52d57SBarry Smith .   proc - neighboring processors
138707b52d57SBarry Smith .   numproc - number of indices for each processor
138807b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
138907b52d57SBarry Smith 
139007b52d57SBarry Smith     Level: advanced
139107b52d57SBarry Smith 
139207b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
139307b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
139407b52d57SBarry Smith @*/
13957087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
139607b52d57SBarry Smith {
13976849ba73SBarry Smith   PetscErrorCode ierr;
139807b52d57SBarry Smith 
139907b52d57SBarry Smith   PetscFunctionBegin;
14006a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
140107b52d57SBarry Smith   PetscFunctionReturn(0);
140207b52d57SBarry Smith }
140386994e45SJed Brown 
140486994e45SJed Brown #undef __FUNCT__
140586994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
140686994e45SJed Brown /*@C
1407107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
140886994e45SJed Brown 
140986994e45SJed Brown    Not Collective
141086994e45SJed Brown 
141186994e45SJed Brown    Input Arguments:
141286994e45SJed Brown . ltog - local to global mapping
141386994e45SJed Brown 
141486994e45SJed Brown    Output Arguments:
1415565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
141686994e45SJed Brown 
141786994e45SJed Brown    Level: advanced
141886994e45SJed Brown 
1419107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1420107e9a97SBarry Smith 
1421107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
142286994e45SJed Brown @*/
14237087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
142486994e45SJed Brown {
142586994e45SJed Brown   PetscFunctionBegin;
142686994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
142786994e45SJed Brown   PetscValidPointer(array,2);
142845b6f7e9SBarry Smith   if (ltog->bs == 1) {
142986994e45SJed Brown     *array = ltog->indices;
143045b6f7e9SBarry Smith   } else {
143145b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
143245b6f7e9SBarry Smith     const PetscInt *ii;
143345b6f7e9SBarry Smith     PetscErrorCode ierr;
143445b6f7e9SBarry Smith 
143545b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
143645b6f7e9SBarry Smith     *array = jj;
143745b6f7e9SBarry Smith     k    = 0;
143845b6f7e9SBarry Smith     ii   = ltog->indices;
143945b6f7e9SBarry Smith     for (i=0; i<n; i++)
144045b6f7e9SBarry Smith       for (j=0; j<bs; j++)
144145b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
144245b6f7e9SBarry Smith   }
144386994e45SJed Brown   PetscFunctionReturn(0);
144486994e45SJed Brown }
144586994e45SJed Brown 
144686994e45SJed Brown #undef __FUNCT__
144786994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
144886994e45SJed Brown /*@C
1449193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
145086994e45SJed Brown 
145186994e45SJed Brown    Not Collective
145286994e45SJed Brown 
145386994e45SJed Brown    Input Arguments:
145486994e45SJed Brown + ltog - local to global mapping
145586994e45SJed Brown - array - array of indices
145686994e45SJed Brown 
145786994e45SJed Brown    Level: advanced
145886994e45SJed Brown 
145986994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
146086994e45SJed Brown @*/
14617087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
146286994e45SJed Brown {
146386994e45SJed Brown   PetscFunctionBegin;
146486994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
146586994e45SJed Brown   PetscValidPointer(array,2);
146645b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
146745b6f7e9SBarry Smith 
146845b6f7e9SBarry Smith   if (ltog->bs > 1) {
146945b6f7e9SBarry Smith     PetscErrorCode ierr;
147045b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
147145b6f7e9SBarry Smith   }
147245b6f7e9SBarry Smith   PetscFunctionReturn(0);
147345b6f7e9SBarry Smith }
147445b6f7e9SBarry Smith 
147545b6f7e9SBarry Smith #undef __FUNCT__
147645b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
147745b6f7e9SBarry Smith /*@C
147845b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
147945b6f7e9SBarry Smith 
148045b6f7e9SBarry Smith    Not Collective
148145b6f7e9SBarry Smith 
148245b6f7e9SBarry Smith    Input Arguments:
148345b6f7e9SBarry Smith . ltog - local to global mapping
148445b6f7e9SBarry Smith 
148545b6f7e9SBarry Smith    Output Arguments:
148645b6f7e9SBarry Smith . array - array of indices
148745b6f7e9SBarry Smith 
148845b6f7e9SBarry Smith    Level: advanced
148945b6f7e9SBarry Smith 
149045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
149145b6f7e9SBarry Smith @*/
149245b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
149345b6f7e9SBarry Smith {
149445b6f7e9SBarry Smith   PetscFunctionBegin;
149545b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
149645b6f7e9SBarry Smith   PetscValidPointer(array,2);
149745b6f7e9SBarry Smith   *array = ltog->indices;
149845b6f7e9SBarry Smith   PetscFunctionReturn(0);
149945b6f7e9SBarry Smith }
150045b6f7e9SBarry Smith 
150145b6f7e9SBarry Smith #undef __FUNCT__
150245b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
150345b6f7e9SBarry Smith /*@C
150445b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
150545b6f7e9SBarry Smith 
150645b6f7e9SBarry Smith    Not Collective
150745b6f7e9SBarry Smith 
150845b6f7e9SBarry Smith    Input Arguments:
150945b6f7e9SBarry Smith + ltog - local to global mapping
151045b6f7e9SBarry Smith - array - array of indices
151145b6f7e9SBarry Smith 
151245b6f7e9SBarry Smith    Level: advanced
151345b6f7e9SBarry Smith 
151445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
151545b6f7e9SBarry Smith @*/
151645b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
151745b6f7e9SBarry Smith {
151845b6f7e9SBarry Smith   PetscFunctionBegin;
151945b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
152045b6f7e9SBarry Smith   PetscValidPointer(array,2);
152186994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
15220298fd71SBarry Smith   *array = NULL;
152386994e45SJed Brown   PetscFunctionReturn(0);
152486994e45SJed Brown }
1525f7efa3c7SJed Brown 
1526f7efa3c7SJed Brown #undef __FUNCT__
1527f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1528f7efa3c7SJed Brown /*@C
1529f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1530f7efa3c7SJed Brown 
1531f7efa3c7SJed Brown    Not Collective
1532f7efa3c7SJed Brown 
1533f7efa3c7SJed Brown    Input Arguments:
1534f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1535f7efa3c7SJed Brown . n - number of mappings to concatenate
1536f7efa3c7SJed Brown - ltogs - local to global mappings
1537f7efa3c7SJed Brown 
1538f7efa3c7SJed Brown    Output Arguments:
1539f7efa3c7SJed Brown . ltogcat - new mapping
1540f7efa3c7SJed Brown 
15419d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
15429d90f715SBarry Smith 
15439d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
15449d90f715SBarry Smith 
1545f7efa3c7SJed Brown    Level: advanced
1546f7efa3c7SJed Brown 
1547f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1548f7efa3c7SJed Brown @*/
1549f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1550f7efa3c7SJed Brown {
1551f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1552f7efa3c7SJed Brown   PetscErrorCode ierr;
1553f7efa3c7SJed Brown 
1554f7efa3c7SJed Brown   PetscFunctionBegin;
1555f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1556f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1557f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1558f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1559f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1560f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1561f7efa3c7SJed Brown     cnt += m;
1562f7efa3c7SJed Brown   }
1563785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1564f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1565f7efa3c7SJed Brown     const PetscInt *subidx;
1566f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1567f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1568f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1569f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1570f7efa3c7SJed Brown     cnt += m;
1571f7efa3c7SJed Brown   }
1572f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1573f7efa3c7SJed Brown   PetscFunctionReturn(0);
1574f7efa3c7SJed Brown }
157504a59952SBarry Smith 
157604a59952SBarry Smith 
1577