xref: /petsc/src/vec/is/utils/isltog.c (revision c9345713c0ceec43ecc24ae48e7f0ad0720dee63)
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*c9345713Sstefano_zampini   PetscInt       i,cn,on,obs,nn,cum;
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);
21263fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
213*c9345713Sstefano_zampini   for (i=0,cum=0,cn=0;i<on;i++) {
214*c9345713Sstefano_zampini     if (oid[i] < 0) cn++;
215*c9345713Sstefano_zampini     if (cn == bs || (oid[i] > -1 && !((oid[i]*obs)%bs))) {
21663fa5c83Sstefano_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);
217*c9345713Sstefano_zampini       if (cn && cn != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices",bs,obs);
218*c9345713Sstefano_zampini       if (cn) nid[cum++] = -1;
219*c9345713Sstefano_zampini       else nid[cum++] = (oid[i]*obs)/bs;
220*c9345713Sstefano_zampini       cn = 0;
22163fa5c83Sstefano_zampini     }
22263fa5c83Sstefano_zampini   }
223*c9345713Sstefano_zampini   if (cum != nn || cn) {
22463fa5c83Sstefano_zampini     ierr = PetscFree(nid);CHKERRQ(ierr);
225*c9345713Sstefano_zampini     SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Incompatible block sizes %D and %D (new block indices found %D != %D, neg %d)",bs,obs,cum,nn,cn);
22663fa5c83Sstefano_zampini   }
22763fa5c83Sstefano_zampini   mapping->n           = nn;
22863fa5c83Sstefano_zampini   mapping->bs          = bs;
22963fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
23063fa5c83Sstefano_zampini   mapping->indices     = nid;
231*c9345713Sstefano_zampini   ierr                 = PetscFree(mapping->globals);CHKERRQ(ierr);
232*c9345713Sstefano_zampini   mapping->globalstart = 0;
233*c9345713Sstefano_zampini   mapping->globalend   = 0;
23463fa5c83Sstefano_zampini   PetscFunctionReturn(0);
23563fa5c83Sstefano_zampini }
23663fa5c83Sstefano_zampini 
23763fa5c83Sstefano_zampini #undef __FUNCT__
23845b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
23945b6f7e9SBarry Smith /*@
24045b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
24145b6f7e9SBarry Smith     ordering and a global parallel ordering.
24245b6f7e9SBarry Smith 
24345b6f7e9SBarry Smith     Not Collective
24445b6f7e9SBarry Smith 
24545b6f7e9SBarry Smith     Input Parameters:
24645b6f7e9SBarry Smith .   mapping - mapping data structure
24745b6f7e9SBarry Smith 
24845b6f7e9SBarry Smith     Output Parameter:
24945b6f7e9SBarry Smith .   bs - the blocksize
25045b6f7e9SBarry Smith 
25145b6f7e9SBarry Smith     Level: advanced
25245b6f7e9SBarry Smith 
25345b6f7e9SBarry Smith     Concepts: mapping^local to global
25445b6f7e9SBarry Smith 
25545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
25645b6f7e9SBarry Smith @*/
25745b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
25845b6f7e9SBarry Smith {
25945b6f7e9SBarry Smith   PetscFunctionBegin;
260cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
26145b6f7e9SBarry Smith   *bs = mapping->bs;
26245b6f7e9SBarry Smith   PetscFunctionReturn(0);
26345b6f7e9SBarry Smith }
26445b6f7e9SBarry Smith 
26545b6f7e9SBarry Smith #undef __FUNCT__
2664a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
267ba5bb76aSSatish Balay /*@
26890f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
26990f02eecSBarry Smith     ordering and a global parallel ordering.
2702362add9SBarry Smith 
27189d82c54SBarry Smith     Not Collective, but communicator may have more than one process
272b9cd556bSLois Curfman McInnes 
2732362add9SBarry Smith     Input Parameters:
27489d82c54SBarry Smith +   comm - MPI communicator
275f0413b6fSBarry Smith .   bs - the block size
27628bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
27728bc9809SBarry 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
278d5ad8652SBarry Smith -   mode - see PetscCopyMode
2792362add9SBarry Smith 
280a997ad1aSLois Curfman McInnes     Output Parameter:
28190f02eecSBarry Smith .   mapping - new mapping data structure
2822362add9SBarry Smith 
283f0413b6fSBarry 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
284a997ad1aSLois Curfman McInnes     Level: advanced
285a997ad1aSLois Curfman McInnes 
286273d9f13SBarry Smith     Concepts: mapping^local to global
2872362add9SBarry Smith 
288d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2892362add9SBarry Smith @*/
29060c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2912362add9SBarry Smith {
2926849ba73SBarry Smith   PetscErrorCode ierr;
29332dcc486SBarry Smith   PetscInt       *in;
294b46b645bSBarry Smith 
295b46b645bSBarry Smith   PetscFunctionBegin;
29673911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2974482741eSBarry Smith   PetscValidPointer(mapping,4);
298b46b645bSBarry Smith 
2990298fd71SBarry Smith   *mapping = NULL;
300607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
3012362add9SBarry Smith 
30273107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
30360c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
304d4bb536fSBarry Smith   (*mapping)->n             = n;
305f0413b6fSBarry Smith   (*mapping)->bs            = bs;
306268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
307268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
308268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
309268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
310268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
311d4bb536fSBarry Smith   /*
312d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
313d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
314d4bb536fSBarry Smith   */
315d4bb536fSBarry Smith   (*mapping)->globals = 0;
316d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
317785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
318d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
319d5ad8652SBarry Smith     (*mapping)->indices = in;
3206389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3216389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
3226389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
3236389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3246389a1a1SBarry Smith   }
32560c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
326d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
3273a40ed3dSBarry Smith   PetscFunctionReturn(0);
3282362add9SBarry Smith }
3292362add9SBarry Smith 
3304a2ae208SSatish Balay #undef __FUNCT__
3314a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
33290f02eecSBarry Smith /*@
33390f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
33490f02eecSBarry Smith    ordering and a global parallel ordering.
33590f02eecSBarry Smith 
3360f5bd95cSBarry Smith    Note Collective
337b9cd556bSLois Curfman McInnes 
33890f02eecSBarry Smith    Input Parameters:
33990f02eecSBarry Smith .  mapping - mapping data structure
34090f02eecSBarry Smith 
341a997ad1aSLois Curfman McInnes    Level: advanced
342a997ad1aSLois Curfman McInnes 
3433acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
34490f02eecSBarry Smith @*/
3456bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
34690f02eecSBarry Smith {
347dfbe8321SBarry Smith   PetscErrorCode ierr;
3485fd66863SKarl Rupp 
3493a40ed3dSBarry Smith   PetscFunctionBegin;
3506bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3516bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
352997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3536bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3546bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
355268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
356268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
357268a049cSStefano Zampini   if ((*mapping)->info_indices) {
358268a049cSStefano Zampini     PetscInt i;
359268a049cSStefano Zampini 
360268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
361268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
362268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
363268a049cSStefano Zampini     }
364268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
365268a049cSStefano Zampini   }
366d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
367992144d0SBarry Smith   *mapping = 0;
3683a40ed3dSBarry Smith   PetscFunctionReturn(0);
36990f02eecSBarry Smith }
37090f02eecSBarry Smith 
3714a2ae208SSatish Balay #undef __FUNCT__
3724a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
37390f02eecSBarry Smith /*@
3743acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3753acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3763acfe500SLois Curfman McInnes     context.
37790f02eecSBarry Smith 
378b9cd556bSLois Curfman McInnes     Not collective
379b9cd556bSLois Curfman McInnes 
38090f02eecSBarry Smith     Input Parameters:
381b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
382b9cd556bSLois Curfman McInnes -   is - index set in local numbering
38390f02eecSBarry Smith 
38490f02eecSBarry Smith     Output Parameters:
38590f02eecSBarry Smith .   newis - index set in global numbering
38690f02eecSBarry Smith 
387a997ad1aSLois Curfman McInnes     Level: advanced
388a997ad1aSLois Curfman McInnes 
389273d9f13SBarry Smith     Concepts: mapping^local to global
3903acfe500SLois Curfman McInnes 
39190f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
392d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
39390f02eecSBarry Smith @*/
3947087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
39590f02eecSBarry Smith {
3966849ba73SBarry Smith   PetscErrorCode ierr;
397e24637baSBarry Smith   PetscInt       n,*idxout;
3985d0c19d7SBarry Smith   const PetscInt *idxin;
3993a40ed3dSBarry Smith 
4003a40ed3dSBarry Smith   PetscFunctionBegin;
4010700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
4020700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
4034482741eSBarry Smith   PetscValidPointer(newis,3);
40490f02eecSBarry Smith 
4053b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
40690f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
407785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
408e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
4093b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
410543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4113a40ed3dSBarry Smith   PetscFunctionReturn(0);
41290f02eecSBarry Smith }
41390f02eecSBarry Smith 
414afcb2eb5SJed Brown #undef __FUNCT__
415afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
416b89cb25eSSatish Balay /*@
4173acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4183acfe500SLois Curfman McInnes    and converts them to the global numbering.
41990f02eecSBarry Smith 
420b9cd556bSLois Curfman McInnes    Not collective
421b9cd556bSLois Curfman McInnes 
422bb25748dSBarry Smith    Input Parameters:
423b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
424bb25748dSBarry Smith .  N - number of integers
425b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
426bb25748dSBarry Smith 
427bb25748dSBarry Smith    Output Parameter:
428bb25748dSBarry Smith .  out - indices in global numbering
429bb25748dSBarry Smith 
430b9cd556bSLois Curfman McInnes    Notes:
431b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
432d4bb536fSBarry Smith 
433a997ad1aSLois Curfman McInnes    Level: advanced
434a997ad1aSLois Curfman McInnes 
43545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4360752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
437d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
438bb25748dSBarry Smith 
439273d9f13SBarry Smith     Concepts: mapping^local to global
440afcb2eb5SJed Brown @*/
441afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
442afcb2eb5SJed Brown {
443cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
44445b6f7e9SBarry Smith 
44545b6f7e9SBarry Smith   PetscFunctionBegin;
446cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
447cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
448cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
44945b6f7e9SBarry Smith   if (bs == 1) {
450cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
45145b6f7e9SBarry Smith     for (i=0; i<N; i++) {
45245b6f7e9SBarry Smith       if (in[i] < 0) {
45345b6f7e9SBarry Smith         out[i] = in[i];
45445b6f7e9SBarry Smith         continue;
45545b6f7e9SBarry Smith       }
456e24637baSBarry 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);
45745b6f7e9SBarry Smith       out[i] = idx[in[i]];
45845b6f7e9SBarry Smith     }
45945b6f7e9SBarry Smith   } else {
460cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
46145b6f7e9SBarry Smith     for (i=0; i<N; i++) {
46245b6f7e9SBarry Smith       if (in[i] < 0) {
46345b6f7e9SBarry Smith         out[i] = in[i];
46445b6f7e9SBarry Smith         continue;
46545b6f7e9SBarry Smith       }
466e24637baSBarry 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);
46745b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
46845b6f7e9SBarry Smith     }
46945b6f7e9SBarry Smith   }
47045b6f7e9SBarry Smith   PetscFunctionReturn(0);
47145b6f7e9SBarry Smith }
47245b6f7e9SBarry Smith 
47345b6f7e9SBarry Smith #undef __FUNCT__
47445b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
47545b6f7e9SBarry Smith /*@
4766006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
47745b6f7e9SBarry Smith 
47845b6f7e9SBarry Smith    Not collective
47945b6f7e9SBarry Smith 
48045b6f7e9SBarry Smith    Input Parameters:
48145b6f7e9SBarry Smith +  mapping - the local to global mapping context
48245b6f7e9SBarry Smith .  N - number of integers
4836006e8d2SBarry Smith -  in - input indices in local block numbering
48445b6f7e9SBarry Smith 
48545b6f7e9SBarry Smith    Output Parameter:
4866006e8d2SBarry Smith .  out - indices in global block numbering
48745b6f7e9SBarry Smith 
48845b6f7e9SBarry Smith    Notes:
48945b6f7e9SBarry Smith    The in and out array parameters may be identical.
49045b6f7e9SBarry Smith 
4916006e8d2SBarry Smith    Example:
4926006e8d2SBarry 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
4936006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
4946006e8d2SBarry Smith 
49545b6f7e9SBarry Smith    Level: advanced
49645b6f7e9SBarry Smith 
49745b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
49845b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
49945b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
50045b6f7e9SBarry Smith 
50145b6f7e9SBarry Smith     Concepts: mapping^local to global
50245b6f7e9SBarry Smith @*/
50345b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
50445b6f7e9SBarry Smith {
505cbc1caf0SMatthew G. Knepley 
506cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
507cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
508cbc1caf0SMatthew G. Knepley   {
509afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
510afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
511d4bb536fSBarry Smith 
512afcb2eb5SJed Brown     for (i=0; i<N; i++) {
513afcb2eb5SJed Brown       if (in[i] < 0) {
514afcb2eb5SJed Brown         out[i] = in[i];
515afcb2eb5SJed Brown         continue;
516afcb2eb5SJed Brown       }
517e24637baSBarry 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);
518afcb2eb5SJed Brown       out[i] = idx[in[i]];
519afcb2eb5SJed Brown     }
520cbc1caf0SMatthew G. Knepley   }
521afcb2eb5SJed Brown   PetscFunctionReturn(0);
522afcb2eb5SJed Brown }
523d4bb536fSBarry Smith 
524d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
525d4bb536fSBarry Smith 
5264a2ae208SSatish Balay #undef __FUNCT__
5274a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
528d4bb536fSBarry Smith /*
529d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
530d4bb536fSBarry Smith */
5316849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
532d4bb536fSBarry Smith {
5336849ba73SBarry Smith   PetscErrorCode ierr;
53432dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
535d4bb536fSBarry Smith 
5363a40ed3dSBarry Smith   PetscFunctionBegin;
537d4bb536fSBarry Smith   end   = 0;
538ec268f7cSJed Brown   start = PETSC_MAX_INT;
539d4bb536fSBarry Smith 
540d4bb536fSBarry Smith   for (i=0; i<n; i++) {
541d4bb536fSBarry Smith     if (idx[i] < 0) continue;
542d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
543d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
544d4bb536fSBarry Smith   }
545d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
546d4bb536fSBarry Smith   mapping->globalstart = start;
547d4bb536fSBarry Smith   mapping->globalend   = end;
548d4bb536fSBarry Smith 
549854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
550b0a32e0cSBarry Smith   mapping->globals = globals;
551f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
552d4bb536fSBarry Smith   for (i=0; i<n; i++) {
553d4bb536fSBarry Smith     if (idx[i] < 0) continue;
554d4bb536fSBarry Smith     globals[idx[i] - start] = i;
555d4bb536fSBarry Smith   }
556d4bb536fSBarry Smith 
5573bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5583a40ed3dSBarry Smith   PetscFunctionReturn(0);
559d4bb536fSBarry Smith }
560d4bb536fSBarry Smith 
5614a2ae208SSatish Balay #undef __FUNCT__
5624a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
563d4bb536fSBarry Smith /*@
564a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
565a997ad1aSLois Curfman McInnes     specified with a global numbering.
566d4bb536fSBarry Smith 
567b9cd556bSLois Curfman McInnes     Not collective
568b9cd556bSLois Curfman McInnes 
569d4bb536fSBarry Smith     Input Parameters:
570b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
571d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
572d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
573d4bb536fSBarry Smith .   n - number of global indices to map
574b9cd556bSLois Curfman McInnes -   idx - global indices to map
575d4bb536fSBarry Smith 
576d4bb536fSBarry Smith     Output Parameters:
577b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
578b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
579e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5800298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
581e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
582e182c471SBarry Smith              a second time to set the values.
583d4bb536fSBarry Smith 
584b9cd556bSLois Curfman McInnes     Notes:
5850298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
586d4bb536fSBarry Smith 
5870f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5880f5bd95cSBarry Smith     array to compute these.
5890f5bd95cSBarry Smith 
590a997ad1aSLois Curfman McInnes     Level: advanced
591a997ad1aSLois Curfman McInnes 
59232fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
59332fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
59432fd6b96SBarry Smith 
595273d9f13SBarry Smith     Concepts: mapping^global to local
596d4bb536fSBarry Smith 
5979d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
598d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
599d4bb536fSBarry Smith @*/
6007087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
60132dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
602d4bb536fSBarry Smith {
6039d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
6049d90f715SBarry Smith   PetscErrorCode ierr;
6059d90f715SBarry Smith 
6069d90f715SBarry Smith   PetscFunctionBegin;
6079d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6089d90f715SBarry Smith   if (!mapping->globals) {
6099d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
6109d90f715SBarry Smith   }
6119d90f715SBarry Smith   globals = mapping->globals;
6129d90f715SBarry Smith   start   = mapping->globalstart;
6139d90f715SBarry Smith   end     = mapping->globalend;
6149d90f715SBarry Smith   bs      = mapping->bs;
6159d90f715SBarry Smith 
6169d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
6179d90f715SBarry Smith     if (idxout) {
6189d90f715SBarry Smith       for (i=0; i<n; i++) {
6199d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
6209d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
621663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
6229d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6239d90f715SBarry Smith       }
6249d90f715SBarry Smith     }
6259d90f715SBarry Smith     if (nout) *nout = n;
6269d90f715SBarry Smith   } else {
6279d90f715SBarry Smith     if (idxout) {
6289d90f715SBarry Smith       for (i=0; i<n; i++) {
6299d90f715SBarry Smith         if (idx[i] < 0) continue;
6309d90f715SBarry Smith         if (idx[i] < bs*start) continue;
631663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6329d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6339d90f715SBarry Smith         if (tmp < 0) continue;
6349d90f715SBarry Smith         idxout[nf++] = tmp;
6359d90f715SBarry Smith       }
6369d90f715SBarry Smith     } else {
6379d90f715SBarry Smith       for (i=0; i<n; i++) {
6389d90f715SBarry Smith         if (idx[i] < 0) continue;
6399d90f715SBarry Smith         if (idx[i] < bs*start) continue;
640663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6419d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6429d90f715SBarry Smith         if (tmp < 0) continue;
6439d90f715SBarry Smith         nf++;
6449d90f715SBarry Smith       }
6459d90f715SBarry Smith     }
6469d90f715SBarry Smith     if (nout) *nout = nf;
6479d90f715SBarry Smith   }
6489d90f715SBarry Smith   PetscFunctionReturn(0);
6499d90f715SBarry Smith }
6509d90f715SBarry Smith 
6519d90f715SBarry Smith #undef __FUNCT__
652d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
653d4fe737eSStefano Zampini /*@
654d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
655d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
656d4fe737eSStefano Zampini     context.
657d4fe737eSStefano Zampini 
658d4fe737eSStefano Zampini     Not collective
659d4fe737eSStefano Zampini 
660d4fe737eSStefano Zampini     Input Parameters:
661d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
662d4fe737eSStefano Zampini -   is - index set in global numbering
663d4fe737eSStefano Zampini 
664d4fe737eSStefano Zampini     Output Parameters:
665d4fe737eSStefano Zampini .   newis - index set in local numbering
666d4fe737eSStefano Zampini 
667d4fe737eSStefano Zampini     Level: advanced
668d4fe737eSStefano Zampini 
669d4fe737eSStefano Zampini     Concepts: mapping^local to global
670d4fe737eSStefano Zampini 
671d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
672d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
673d4fe737eSStefano Zampini @*/
674d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
675d4fe737eSStefano Zampini {
676d4fe737eSStefano Zampini   PetscErrorCode ierr;
677d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
678d4fe737eSStefano Zampini   const PetscInt *idxin;
679d4fe737eSStefano Zampini 
680d4fe737eSStefano Zampini   PetscFunctionBegin;
681d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
682d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
683d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
684d4fe737eSStefano Zampini 
685d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
686d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
687d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
688d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
689d4fe737eSStefano Zampini   } else {
690d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
691d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
692d4fe737eSStefano Zampini   }
693d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
694d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
695d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
696d4fe737eSStefano Zampini   PetscFunctionReturn(0);
697d4fe737eSStefano Zampini }
698d4fe737eSStefano Zampini 
699d4fe737eSStefano Zampini #undef __FUNCT__
7009d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
7019d90f715SBarry Smith /*@
7029d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
7039d90f715SBarry Smith     specified with a block global numbering.
7049d90f715SBarry Smith 
7059d90f715SBarry Smith     Not collective
7069d90f715SBarry Smith 
7079d90f715SBarry Smith     Input Parameters:
7089d90f715SBarry Smith +   mapping - mapping between local and global numbering
7099d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
7109d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
7119d90f715SBarry Smith .   n - number of global indices to map
7129d90f715SBarry Smith -   idx - global indices to map
7139d90f715SBarry Smith 
7149d90f715SBarry Smith     Output Parameters:
7159d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
7169d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
7179d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
7189d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
7199d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
7209d90f715SBarry Smith              a second time to set the values.
7219d90f715SBarry Smith 
7229d90f715SBarry Smith     Notes:
7239d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
7249d90f715SBarry Smith 
7259d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
7269d90f715SBarry Smith     array to compute these.
7279d90f715SBarry Smith 
7289d90f715SBarry Smith     Level: advanced
7299d90f715SBarry Smith 
7309d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
7319d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
7329d90f715SBarry Smith 
7339d90f715SBarry Smith     Concepts: mapping^global to local
7349d90f715SBarry Smith 
7359d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7369d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7379d90f715SBarry Smith @*/
7389d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7399d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7409d90f715SBarry Smith {
74132dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
7426849ba73SBarry Smith   PetscErrorCode ierr;
743d4bb536fSBarry Smith 
7443a40ed3dSBarry Smith   PetscFunctionBegin;
7450700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
746d4bb536fSBarry Smith   if (!mapping->globals) {
747d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
748d4bb536fSBarry Smith   }
749d4bb536fSBarry Smith   globals = mapping->globals;
750d4bb536fSBarry Smith   start   = mapping->globalstart;
751d4bb536fSBarry Smith   end     = mapping->globalend;
752d4bb536fSBarry Smith 
753d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
754d4bb536fSBarry Smith     if (idxout) {
755d4bb536fSBarry Smith       for (i=0; i<n; i++) {
756d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
757d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
758d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
759d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
760d4bb536fSBarry Smith       }
761d4bb536fSBarry Smith     }
762d4bb536fSBarry Smith     if (nout) *nout = n;
763d4bb536fSBarry Smith   } else {
764d4bb536fSBarry Smith     if (idxout) {
765d4bb536fSBarry Smith       for (i=0; i<n; i++) {
766d4bb536fSBarry Smith         if (idx[i] < 0) continue;
767d4bb536fSBarry Smith         if (idx[i] < start) continue;
768d4bb536fSBarry Smith         if (idx[i] > end) continue;
769d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
770d4bb536fSBarry Smith         if (tmp < 0) continue;
771d4bb536fSBarry Smith         idxout[nf++] = tmp;
772d4bb536fSBarry Smith       }
773d4bb536fSBarry Smith     } else {
774d4bb536fSBarry Smith       for (i=0; i<n; i++) {
775d4bb536fSBarry Smith         if (idx[i] < 0) continue;
776d4bb536fSBarry Smith         if (idx[i] < start) continue;
777d4bb536fSBarry Smith         if (idx[i] > end) continue;
778d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
779d4bb536fSBarry Smith         if (tmp < 0) continue;
780d4bb536fSBarry Smith         nf++;
781d4bb536fSBarry Smith       }
782d4bb536fSBarry Smith     }
783d4bb536fSBarry Smith     if (nout) *nout = nf;
784d4bb536fSBarry Smith   }
7853a40ed3dSBarry Smith   PetscFunctionReturn(0);
786d4bb536fSBarry Smith }
78790f02eecSBarry Smith 
7884a2ae208SSatish Balay #undef __FUNCT__
7896a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
79089d82c54SBarry Smith /*@C
7916a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
79289d82c54SBarry Smith      each index shared by more than one processor
79389d82c54SBarry Smith 
79489d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
79589d82c54SBarry Smith 
79689d82c54SBarry Smith     Input Parameters:
79789d82c54SBarry Smith .   mapping - the mapping from local to global indexing
79889d82c54SBarry Smith 
79989d82c54SBarry Smith     Output Parameter:
80089d82c54SBarry Smith +   nproc - number of processors that are connected to this one
80189d82c54SBarry Smith .   proc - neighboring processors
80207b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
8033463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
80489d82c54SBarry Smith 
80589d82c54SBarry Smith     Level: advanced
80689d82c54SBarry Smith 
807273d9f13SBarry Smith     Concepts: mapping^local to global
80889d82c54SBarry Smith 
8092cfcea29SBarry Smith     Fortran Usage:
8102cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
8112cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
8122cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
8132cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
8142cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
8152cfcea29SBarry Smith 
8162cfcea29SBarry Smith 
81707b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
81807b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
81989d82c54SBarry Smith @*/
8206a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
82189d82c54SBarry Smith {
8226849ba73SBarry Smith   PetscErrorCode ierr;
823268a049cSStefano Zampini 
824268a049cSStefano Zampini   PetscFunctionBegin;
825268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
826268a049cSStefano Zampini   if (mapping->info_cached) {
827268a049cSStefano Zampini     *nproc = mapping->info_nproc;
828268a049cSStefano Zampini     *procs = mapping->info_procs;
829268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
830268a049cSStefano Zampini     *indices = mapping->info_indices;
831268a049cSStefano Zampini   } else {
832268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
833268a049cSStefano Zampini   }
834268a049cSStefano Zampini   PetscFunctionReturn(0);
835268a049cSStefano Zampini }
836268a049cSStefano Zampini 
837268a049cSStefano Zampini #undef __FUNCT__
838268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
839268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
840268a049cSStefano Zampini {
841268a049cSStefano Zampini   PetscErrorCode ierr;
84297f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
84332dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
84432dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
84597f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
84632dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
84732dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
84889d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
84930dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
850ce94432eSBarry Smith   MPI_Comm       comm;
851ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
85289d82c54SBarry Smith 
85389d82c54SBarry Smith   PetscFunctionBegin;
854ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
85524cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
85624cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
85724cf384cSBarry Smith   if (size == 1) {
85824cf384cSBarry Smith     *nproc         = 0;
8590298fd71SBarry Smith     *procs         = NULL;
86095dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
8611e2105dcSBarry Smith     (*numprocs)[0] = 0;
86295dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
8630298fd71SBarry Smith     (*indices)[0]  = NULL;
864268a049cSStefano Zampini     /* save info for reuse */
865268a049cSStefano Zampini     mapping->info_nproc = *nproc;
866268a049cSStefano Zampini     mapping->info_procs = *procs;
867268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
868268a049cSStefano Zampini     mapping->info_indices = *indices;
869268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
87024cf384cSBarry Smith     PetscFunctionReturn(0);
87124cf384cSBarry Smith   }
87224cf384cSBarry Smith 
873c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
87407b52d57SBarry Smith 
8753677ff5aSBarry Smith   /*
8766a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
8773677ff5aSBarry Smith 
8783677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
8793677ff5aSBarry Smith            numbering, just for this routine.
8803677ff5aSBarry Smith 
8813677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
8823677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
8833677ff5aSBarry Smith 
8843677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
8853677ff5aSBarry Smith 
8863677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
8873677ff5aSBarry Smith            local subdomain
8883677ff5aSBarry Smith   */
88924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
89024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
89124cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
89289d82c54SBarry Smith 
89389d82c54SBarry Smith   for (i=0; i<n; i++) {
89489d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
89589d82c54SBarry Smith   }
896b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
89778058e43SBarry Smith   Ng++;
89889d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
89989d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
900bc8ff85bSBarry Smith   scale  = Ng/size + 1;
901a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
902caba0dd0SBarry Smith   rstart = scale*rank;
90389d82c54SBarry Smith 
90489d82c54SBarry Smith   /* determine ownership ranges of global indices */
905785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
90632dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
90789d82c54SBarry Smith 
90889d82c54SBarry Smith   /* determine owners of each local node  */
909785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
91089d82c54SBarry Smith   for (i=0; i<n; i++) {
9113677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
91227c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
9133677ff5aSBarry Smith     owner[i]         = proc;
91427c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
91589d82c54SBarry Smith   }
91627c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
9177904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
91889d82c54SBarry Smith 
91989d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
92027c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9217904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
92289d82c54SBarry Smith 
92389d82c54SBarry Smith   /* post receives for owned rows */
924785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
925854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
92689d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
92732dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
92889d82c54SBarry Smith   }
92989d82c54SBarry Smith 
93089d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
931854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
932854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
93389d82c54SBarry Smith   starts[0] = 0;
934f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
93589d82c54SBarry Smith   for (i=0; i<n; i++) {
93689d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
93730dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
93889d82c54SBarry Smith   }
93989d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
94089d82c54SBarry Smith   starts[0] = 0;
941f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
94289d82c54SBarry Smith 
94389d82c54SBarry Smith   /* send the messages */
944854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
945854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
94689d82c54SBarry Smith   cnt = 0;
94789d82c54SBarry Smith   for (i=0; i<size; i++) {
94827c402fcSBarry Smith     if (nprocs[2*i]) {
94932dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
95030dcb7c9SBarry Smith       dest[cnt] = i;
95189d82c54SBarry Smith       cnt++;
95289d82c54SBarry Smith     }
95389d82c54SBarry Smith   }
95489d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
95589d82c54SBarry Smith 
95689d82c54SBarry Smith   /* wait on receives */
957854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
958854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
95989d82c54SBarry Smith   cnt  = nrecvs;
960854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
96132dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
96289d82c54SBarry Smith   while (cnt) {
96389d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
96489d82c54SBarry Smith     /* unpack receives into our local space */
96532dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
96689d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
96730dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
968caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
96930dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
97089d82c54SBarry Smith     cnt--;
97189d82c54SBarry Smith   }
97289d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
97389d82c54SBarry Smith 
97430dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
975bc8ff85bSBarry Smith   nowned  = 0;
976bc8ff85bSBarry Smith   nownedm = 0;
977bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
978bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
979bc8ff85bSBarry Smith   }
980bc8ff85bSBarry Smith 
981bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
982854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
983854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
984bc8ff85bSBarry Smith   starts[0] = 0;
985bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
986bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
987bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
988bc8ff85bSBarry Smith   }
989bc8ff85bSBarry Smith 
99030dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
991bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
992bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
99330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
994f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
995bc8ff85bSBarry Smith     }
996bc8ff85bSBarry Smith   }
997bc8ff85bSBarry Smith 
99807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
99930dcb7c9SBarry Smith     starts[0] = 0;
100030dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
100130dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
100230dcb7c9SBarry Smith       else starts[i] = starts[i-1];
100330dcb7c9SBarry Smith     }
100430dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
100530dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
10067904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
100730dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
10087904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
100930dcb7c9SBarry Smith         }
101030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
101130dcb7c9SBarry Smith       }
101230dcb7c9SBarry Smith     }
10130ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
101407b52d57SBarry Smith   } /* -----------------------------------  */
101530dcb7c9SBarry Smith 
10163677ff5aSBarry Smith   /* wait on original sends */
10173a96401aSBarry Smith   if (nsends) {
1018785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
10193a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10203a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10213a96401aSBarry Smith   }
102289d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10233a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
10243677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
10253677ff5aSBarry Smith 
10263677ff5aSBarry Smith   /* pack messages to send back to local owners */
102730dcb7c9SBarry Smith   starts[0] = 0;
102830dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
102930dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
103030dcb7c9SBarry Smith     else starts[i] = starts[i-1];
103130dcb7c9SBarry Smith   }
103230dcb7c9SBarry Smith   nsends2 = nrecvs;
1033854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
103430dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
103530dcb7c9SBarry Smith     nprocs[i] = 1;
103630dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
103730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1038f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
103930dcb7c9SBarry Smith     }
104030dcb7c9SBarry Smith   }
1041f6e5521dSKarl Rupp   nt = 0;
1042f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1043f6e5521dSKarl Rupp 
1044854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1045854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1046f6e5521dSKarl Rupp 
1047f6e5521dSKarl Rupp   starts2[0] = 0;
1048f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
104930dcb7c9SBarry Smith   /*
105030dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
105130dcb7c9SBarry Smith        (0) the number of nodes being sent back
105230dcb7c9SBarry Smith        (1) the local node number,
105330dcb7c9SBarry Smith        (2) the number of processors sharing it,
105430dcb7c9SBarry Smith        (3) the processors sharing it
105530dcb7c9SBarry Smith   */
105630dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
105730dcb7c9SBarry Smith     cnt = 1;
105830dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
105930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
106030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
106130dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
106230dcb7c9SBarry Smith         sends2[starts2[i]]++;
106330dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
106430dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
106532dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
106630dcb7c9SBarry Smith         cnt += nownedsenders[node];
106730dcb7c9SBarry Smith       }
106830dcb7c9SBarry Smith     }
106930dcb7c9SBarry Smith   }
107030dcb7c9SBarry Smith 
107130dcb7c9SBarry Smith   /* receive the message lengths */
107230dcb7c9SBarry Smith   nrecvs2 = nsends;
1073854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1074854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1075854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
107630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1077d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
107830dcb7c9SBarry Smith   }
1079d44834fbSBarry Smith 
10808a8e0b3aSBarry Smith   /* send the message lengths */
10818a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
10828a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
10838a8e0b3aSBarry Smith   }
10848a8e0b3aSBarry Smith 
1085d44834fbSBarry Smith   /* wait on receives of lens */
10860c468ba9SBarry Smith   if (nrecvs2) {
1087785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1088d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1089d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10900c468ba9SBarry Smith   }
1091a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1092d44834fbSBarry Smith 
109330dcb7c9SBarry Smith   starts3[0] = 0;
1094d44834fbSBarry Smith   nt         = 0;
109530dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
109630dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1097d44834fbSBarry Smith     nt          += lens2[i];
109830dcb7c9SBarry Smith   }
109976466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1100d44834fbSBarry Smith 
1101854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1102854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
110352b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
110432dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
110530dcb7c9SBarry Smith   }
110630dcb7c9SBarry Smith 
110730dcb7c9SBarry Smith   /* send the messages */
1108854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
110930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
111032dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
111130dcb7c9SBarry Smith   }
111230dcb7c9SBarry Smith 
111330dcb7c9SBarry Smith   /* wait on receives */
11140c468ba9SBarry Smith   if (nrecvs2) {
1115785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
111630dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
111730dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11180c468ba9SBarry Smith   }
111930dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
112030dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
112130dcb7c9SBarry Smith 
112207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
112330dcb7c9SBarry Smith     cnt = 0;
112430dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
112530dcb7c9SBarry Smith       nt = recvs2[cnt++];
112630dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
11277904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
112830dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
11297904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
113030dcb7c9SBarry Smith         }
113130dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
113230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
113330dcb7c9SBarry Smith       }
113430dcb7c9SBarry Smith     }
11350ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
113607b52d57SBarry Smith   } /* -----------------------------------  */
113730dcb7c9SBarry Smith 
113830dcb7c9SBarry Smith   /* count number subdomains for each local node */
1139785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
114032dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
114130dcb7c9SBarry Smith   cnt  = 0;
114230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
114330dcb7c9SBarry Smith     nt = recvs2[cnt++];
114430dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1145f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
114630dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
114730dcb7c9SBarry Smith     }
114830dcb7c9SBarry Smith   }
114930dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
115030dcb7c9SBarry Smith   *nproc    = nt;
1151854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1152854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1153854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
11540298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1155785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
115630dcb7c9SBarry Smith   cnt  = 0;
115730dcb7c9SBarry Smith   for (i=0; i<size; i++) {
115830dcb7c9SBarry Smith     if (nprocs[i] > 0) {
115930dcb7c9SBarry Smith       bprocs[i]        = cnt;
116030dcb7c9SBarry Smith       (*procs)[cnt]    = i;
116130dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1162785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
116330dcb7c9SBarry Smith       cnt++;
116430dcb7c9SBarry Smith     }
116530dcb7c9SBarry Smith   }
116630dcb7c9SBarry Smith 
116730dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
116832dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
116930dcb7c9SBarry Smith   cnt  = 0;
117030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
117130dcb7c9SBarry Smith     nt = recvs2[cnt++];
117230dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1173f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
117430dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
117530dcb7c9SBarry Smith     }
117630dcb7c9SBarry Smith   }
117730dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
117807b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
117930dcb7c9SBarry Smith 
118007b52d57SBarry Smith   /* sort the node indexing by their global numbers */
118107b52d57SBarry Smith   nt = *nproc;
118207b52d57SBarry Smith   for (i=0; i<nt; i++) {
1183854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1184f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
118507b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
118607b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
118707b52d57SBarry Smith   }
118807b52d57SBarry Smith 
118907b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
119030dcb7c9SBarry Smith     nt = *nproc;
119130dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
11927904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
119330dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
11947904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
119530dcb7c9SBarry Smith       }
119630dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
119730dcb7c9SBarry Smith     }
11980ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
119907b52d57SBarry Smith   } /* -----------------------------------  */
120030dcb7c9SBarry Smith 
120130dcb7c9SBarry Smith   /* wait on sends */
120230dcb7c9SBarry Smith   if (nsends2) {
1203785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
120430dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
120530dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
120630dcb7c9SBarry Smith   }
120730dcb7c9SBarry Smith 
120830dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
120930dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
121030dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12113677ff5aSBarry Smith 
1212bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1213bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1214bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
121530dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
121630dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
121789d82c54SBarry Smith 
121889d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
121997f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
122089d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
12213a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
122230dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
122324cf384cSBarry Smith 
122424cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
122524cf384cSBarry Smith   first_procs    = (*procs)[0];
122624cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
122724cf384cSBarry Smith   first_indices  = (*indices)[0];
122824cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
122924cf384cSBarry Smith     if ((*procs)[i] == rank) {
123024cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
123124cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
123224cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
123324cf384cSBarry Smith       (*procs)[i]    = first_procs;
123424cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
123524cf384cSBarry Smith       (*indices)[i]  = first_indices;
123624cf384cSBarry Smith       break;
123724cf384cSBarry Smith     }
123824cf384cSBarry Smith   }
1239268a049cSStefano Zampini 
1240268a049cSStefano Zampini   /* save info for reuse */
1241268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1242268a049cSStefano Zampini   mapping->info_procs = *procs;
1243268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1244268a049cSStefano Zampini   mapping->info_indices = *indices;
1245268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
124689d82c54SBarry Smith   PetscFunctionReturn(0);
124789d82c54SBarry Smith }
124889d82c54SBarry Smith 
12494a2ae208SSatish Balay #undef __FUNCT__
12506a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
12516a818285SBarry Smith /*@C
12526a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
12536a818285SBarry Smith 
12546a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12556a818285SBarry Smith 
12566a818285SBarry Smith     Input Parameters:
12576a818285SBarry Smith .   mapping - the mapping from local to global indexing
12586a818285SBarry Smith 
12596a818285SBarry Smith     Output Parameter:
12606a818285SBarry Smith +   nproc - number of processors that are connected to this one
12616a818285SBarry Smith .   proc - neighboring processors
12626a818285SBarry Smith .   numproc - number of indices for each processor
12636a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12646a818285SBarry Smith 
12656a818285SBarry Smith     Level: advanced
12666a818285SBarry Smith 
12676a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12686a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
12696a818285SBarry Smith @*/
12706a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12716a818285SBarry Smith {
12726a818285SBarry Smith   PetscErrorCode ierr;
12736a818285SBarry Smith 
12746a818285SBarry Smith   PetscFunctionBegin;
1275cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1276268a049cSStefano Zampini   if (mapping->info_free) {
12776a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
12786a818285SBarry Smith     if (*indices) {
1279268a049cSStefano Zampini       PetscInt i;
1280268a049cSStefano Zampini 
12816a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
12826a818285SBarry Smith       for (i=1; i<*nproc; i++) {
12836a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
12846a818285SBarry Smith       }
12856a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
12866a818285SBarry Smith     }
1287268a049cSStefano Zampini   }
1288268a049cSStefano Zampini   *nproc = 0;
1289268a049cSStefano Zampini   *procs = NULL;
1290268a049cSStefano Zampini   *numprocs = NULL;
1291268a049cSStefano Zampini   *indices = NULL;
12926a818285SBarry Smith   PetscFunctionReturn(0);
12936a818285SBarry Smith }
12946a818285SBarry Smith 
12956a818285SBarry Smith #undef __FUNCT__
12966a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
12976a818285SBarry Smith /*@C
12986a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
12996a818285SBarry Smith      each index shared by more than one processor
13006a818285SBarry Smith 
13016a818285SBarry Smith     Collective on ISLocalToGlobalMapping
13026a818285SBarry Smith 
13036a818285SBarry Smith     Input Parameters:
13046a818285SBarry Smith .   mapping - the mapping from local to global indexing
13056a818285SBarry Smith 
13066a818285SBarry Smith     Output Parameter:
13076a818285SBarry Smith +   nproc - number of processors that are connected to this one
13086a818285SBarry Smith .   proc - neighboring processors
13096a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
13106a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
13116a818285SBarry Smith 
13126a818285SBarry Smith     Level: advanced
13136a818285SBarry Smith 
13146a818285SBarry Smith     Concepts: mapping^local to global
13156a818285SBarry Smith 
13166a818285SBarry Smith     Fortran Usage:
13176a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
13186a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
13196a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
13206a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
13216a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
13226a818285SBarry Smith 
13236a818285SBarry Smith 
13246a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13256a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
13266a818285SBarry Smith @*/
13276a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13286a818285SBarry Smith {
13296a818285SBarry Smith   PetscErrorCode ierr;
1330268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
13316a818285SBarry Smith 
13326a818285SBarry Smith   PetscFunctionBegin;
13336a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1334268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1335268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1336732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1337268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13386a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1339268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1340268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13416a818285SBarry Smith         for (k=0; k<bs; k++) {
13426a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13436a818285SBarry Smith         }
13446a818285SBarry Smith       }
1345268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13466a818285SBarry Smith     }
1347268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1348268a049cSStefano Zampini   } else {
1349268a049cSStefano Zampini     *numprocs = bnumprocs;
1350268a049cSStefano Zampini     *indices  = bindices;
13516a818285SBarry Smith   }
13526a818285SBarry Smith   PetscFunctionReturn(0);
13536a818285SBarry Smith }
13546a818285SBarry Smith 
13556a818285SBarry Smith #undef __FUNCT__
13564a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
135707b52d57SBarry Smith /*@C
135807b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
135989d82c54SBarry Smith 
136007b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
136107b52d57SBarry Smith 
136207b52d57SBarry Smith     Input Parameters:
136307b52d57SBarry Smith .   mapping - the mapping from local to global indexing
136407b52d57SBarry Smith 
136507b52d57SBarry Smith     Output Parameter:
136607b52d57SBarry Smith +   nproc - number of processors that are connected to this one
136707b52d57SBarry Smith .   proc - neighboring processors
136807b52d57SBarry Smith .   numproc - number of indices for each processor
136907b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
137007b52d57SBarry Smith 
137107b52d57SBarry Smith     Level: advanced
137207b52d57SBarry Smith 
137307b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
137407b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
137507b52d57SBarry Smith @*/
13767087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
137707b52d57SBarry Smith {
13786849ba73SBarry Smith   PetscErrorCode ierr;
137907b52d57SBarry Smith 
138007b52d57SBarry Smith   PetscFunctionBegin;
13816a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
138207b52d57SBarry Smith   PetscFunctionReturn(0);
138307b52d57SBarry Smith }
138486994e45SJed Brown 
138586994e45SJed Brown #undef __FUNCT__
138686994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
138786994e45SJed Brown /*@C
1388107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
138986994e45SJed Brown 
139086994e45SJed Brown    Not Collective
139186994e45SJed Brown 
139286994e45SJed Brown    Input Arguments:
139386994e45SJed Brown . ltog - local to global mapping
139486994e45SJed Brown 
139586994e45SJed Brown    Output Arguments:
1396565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
139786994e45SJed Brown 
139886994e45SJed Brown    Level: advanced
139986994e45SJed Brown 
1400107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1401107e9a97SBarry Smith 
1402107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
140386994e45SJed Brown @*/
14047087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
140586994e45SJed Brown {
140686994e45SJed Brown   PetscFunctionBegin;
140786994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
140886994e45SJed Brown   PetscValidPointer(array,2);
140945b6f7e9SBarry Smith   if (ltog->bs == 1) {
141086994e45SJed Brown     *array = ltog->indices;
141145b6f7e9SBarry Smith   } else {
141245b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
141345b6f7e9SBarry Smith     const PetscInt *ii;
141445b6f7e9SBarry Smith     PetscErrorCode ierr;
141545b6f7e9SBarry Smith 
141645b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
141745b6f7e9SBarry Smith     *array = jj;
141845b6f7e9SBarry Smith     k    = 0;
141945b6f7e9SBarry Smith     ii   = ltog->indices;
142045b6f7e9SBarry Smith     for (i=0; i<n; i++)
142145b6f7e9SBarry Smith       for (j=0; j<bs; j++)
142245b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
142345b6f7e9SBarry Smith   }
142486994e45SJed Brown   PetscFunctionReturn(0);
142586994e45SJed Brown }
142686994e45SJed Brown 
142786994e45SJed Brown #undef __FUNCT__
142886994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
142986994e45SJed Brown /*@C
1430193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
143186994e45SJed Brown 
143286994e45SJed Brown    Not Collective
143386994e45SJed Brown 
143486994e45SJed Brown    Input Arguments:
143586994e45SJed Brown + ltog - local to global mapping
143686994e45SJed Brown - array - array of indices
143786994e45SJed Brown 
143886994e45SJed Brown    Level: advanced
143986994e45SJed Brown 
144086994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
144186994e45SJed Brown @*/
14427087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
144386994e45SJed Brown {
144486994e45SJed Brown   PetscFunctionBegin;
144586994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
144686994e45SJed Brown   PetscValidPointer(array,2);
144745b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
144845b6f7e9SBarry Smith 
144945b6f7e9SBarry Smith   if (ltog->bs > 1) {
145045b6f7e9SBarry Smith     PetscErrorCode ierr;
145145b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
145245b6f7e9SBarry Smith   }
145345b6f7e9SBarry Smith   PetscFunctionReturn(0);
145445b6f7e9SBarry Smith }
145545b6f7e9SBarry Smith 
145645b6f7e9SBarry Smith #undef __FUNCT__
145745b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
145845b6f7e9SBarry Smith /*@C
145945b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
146045b6f7e9SBarry Smith 
146145b6f7e9SBarry Smith    Not Collective
146245b6f7e9SBarry Smith 
146345b6f7e9SBarry Smith    Input Arguments:
146445b6f7e9SBarry Smith . ltog - local to global mapping
146545b6f7e9SBarry Smith 
146645b6f7e9SBarry Smith    Output Arguments:
146745b6f7e9SBarry Smith . array - array of indices
146845b6f7e9SBarry Smith 
146945b6f7e9SBarry Smith    Level: advanced
147045b6f7e9SBarry Smith 
147145b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
147245b6f7e9SBarry Smith @*/
147345b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
147445b6f7e9SBarry Smith {
147545b6f7e9SBarry Smith   PetscFunctionBegin;
147645b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
147745b6f7e9SBarry Smith   PetscValidPointer(array,2);
147845b6f7e9SBarry Smith   *array = ltog->indices;
147945b6f7e9SBarry Smith   PetscFunctionReturn(0);
148045b6f7e9SBarry Smith }
148145b6f7e9SBarry Smith 
148245b6f7e9SBarry Smith #undef __FUNCT__
148345b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
148445b6f7e9SBarry Smith /*@C
148545b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
148645b6f7e9SBarry Smith 
148745b6f7e9SBarry Smith    Not Collective
148845b6f7e9SBarry Smith 
148945b6f7e9SBarry Smith    Input Arguments:
149045b6f7e9SBarry Smith + ltog - local to global mapping
149145b6f7e9SBarry Smith - array - array of indices
149245b6f7e9SBarry Smith 
149345b6f7e9SBarry Smith    Level: advanced
149445b6f7e9SBarry Smith 
149545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
149645b6f7e9SBarry Smith @*/
149745b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
149845b6f7e9SBarry Smith {
149945b6f7e9SBarry Smith   PetscFunctionBegin;
150045b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
150145b6f7e9SBarry Smith   PetscValidPointer(array,2);
150286994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
15030298fd71SBarry Smith   *array = NULL;
150486994e45SJed Brown   PetscFunctionReturn(0);
150586994e45SJed Brown }
1506f7efa3c7SJed Brown 
1507f7efa3c7SJed Brown #undef __FUNCT__
1508f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1509f7efa3c7SJed Brown /*@C
1510f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1511f7efa3c7SJed Brown 
1512f7efa3c7SJed Brown    Not Collective
1513f7efa3c7SJed Brown 
1514f7efa3c7SJed Brown    Input Arguments:
1515f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1516f7efa3c7SJed Brown . n - number of mappings to concatenate
1517f7efa3c7SJed Brown - ltogs - local to global mappings
1518f7efa3c7SJed Brown 
1519f7efa3c7SJed Brown    Output Arguments:
1520f7efa3c7SJed Brown . ltogcat - new mapping
1521f7efa3c7SJed Brown 
15229d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
15239d90f715SBarry Smith 
15249d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
15259d90f715SBarry Smith 
1526f7efa3c7SJed Brown    Level: advanced
1527f7efa3c7SJed Brown 
1528f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1529f7efa3c7SJed Brown @*/
1530f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1531f7efa3c7SJed Brown {
1532f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1533f7efa3c7SJed Brown   PetscErrorCode ierr;
1534f7efa3c7SJed Brown 
1535f7efa3c7SJed Brown   PetscFunctionBegin;
1536f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1537f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1538f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1539f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1540f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1541f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1542f7efa3c7SJed Brown     cnt += m;
1543f7efa3c7SJed Brown   }
1544785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1545f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1546f7efa3c7SJed Brown     const PetscInt *subidx;
1547f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1548f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1549f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1550f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1551f7efa3c7SJed Brown     cnt += m;
1552f7efa3c7SJed Brown   }
1553f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1554f7efa3c7SJed Brown   PetscFunctionReturn(0);
1555f7efa3c7SJed Brown }
155604a59952SBarry Smith 
155704a59952SBarry Smith 
1558