xref: /petsc/src/vec/is/utils/isltog.c (revision 6006e8d2bc81abd7d683aff9ef939b950c197c1a)
12362add9SBarry Smith 
2b45d2f2cSJed Brown #include <petsc-private/isimpl.h>    /*I "petscis.h"  I*/
30c312b8eSJed Brown #include <petscsf.h>
4665c2dedSJed Brown #include <petscviewer.h>
52362add9SBarry Smith 
67087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID;
78e58c17dSMatthew Knepley 
804a59952SBarry Smith 
94a2ae208SSatish Balay #undef __FUNCT__
10743c9b42SStefano Zampini #define __FUNCT__ "ISG2LMapApply"
11186d4ecdSBarry Smith PetscErrorCode ISG2LMapApply(ISLocalToGlobalMapping mapping,PetscInt n,const PetscInt in[],PetscInt out[])
12186d4ecdSBarry Smith {
13186d4ecdSBarry Smith   PetscErrorCode ierr;
14743c9b42SStefano Zampini   PetscInt       i,start,end;
15186d4ecdSBarry Smith 
16186d4ecdSBarry Smith   PetscFunctionBegin;
17186d4ecdSBarry Smith   if (!mapping->globals) {
18186d4ecdSBarry Smith     ierr = ISGlobalToLocalMappingApply(mapping,IS_GTOLM_MASK,0,0,0,0);CHKERRQ(ierr);
19186d4ecdSBarry Smith   }
20743c9b42SStefano Zampini   start = mapping->globalstart;
21743c9b42SStefano Zampini   end = mapping->globalend;
22186d4ecdSBarry Smith   for (i=0; i<n; i++) {
23186d4ecdSBarry Smith     if (in[i] < 0)          out[i] = in[i];
24186d4ecdSBarry Smith     else if (in[i] < start) out[i] = -1;
25186d4ecdSBarry Smith     else if (in[i] > end)   out[i] = -1;
26743c9b42SStefano Zampini     else                    out[i] = mapping->globals[in[i] - start];
27186d4ecdSBarry Smith   }
28186d4ecdSBarry Smith   PetscFunctionReturn(0);
29186d4ecdSBarry Smith }
30186d4ecdSBarry Smith 
31186d4ecdSBarry Smith 
32186d4ecdSBarry Smith #undef __FUNCT__
334a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
34565245c5SBarry Smith /*@
35107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
363b9aefa3SBarry Smith 
373b9aefa3SBarry Smith     Not Collective
383b9aefa3SBarry Smith 
393b9aefa3SBarry Smith     Input Parameter:
403b9aefa3SBarry Smith .   ltog - local to global mapping
413b9aefa3SBarry Smith 
423b9aefa3SBarry Smith     Output Parameter:
43107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
443b9aefa3SBarry Smith 
453b9aefa3SBarry Smith     Level: advanced
463b9aefa3SBarry Smith 
47273d9f13SBarry Smith     Concepts: mapping^local to global
483b9aefa3SBarry Smith 
493b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
503b9aefa3SBarry Smith @*/
517087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
523b9aefa3SBarry Smith {
533b9aefa3SBarry Smith   PetscFunctionBegin;
540700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
554482741eSBarry Smith   PetscValidIntPointer(n,2);
56107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
573b9aefa3SBarry Smith   PetscFunctionReturn(0);
583b9aefa3SBarry Smith }
593b9aefa3SBarry Smith 
604a2ae208SSatish Balay #undef __FUNCT__
614a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
625a5d4f66SBarry Smith /*@C
635a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
645a5d4f66SBarry Smith 
65b9cd556bSLois Curfman McInnes     Not Collective
66b9cd556bSLois Curfman McInnes 
675a5d4f66SBarry Smith     Input Parameters:
683b9aefa3SBarry Smith +   ltog - local to global mapping
693b9aefa3SBarry Smith -   viewer - viewer
705a5d4f66SBarry Smith 
71a997ad1aSLois Curfman McInnes     Level: advanced
72a997ad1aSLois Curfman McInnes 
73273d9f13SBarry Smith     Concepts: mapping^local to global
745a5d4f66SBarry Smith 
755a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
765a5d4f66SBarry Smith @*/
777087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
785a5d4f66SBarry Smith {
7932dcc486SBarry Smith   PetscInt       i;
8032dcc486SBarry Smith   PetscMPIInt    rank;
81ace3abfcSBarry Smith   PetscBool      iascii;
826849ba73SBarry Smith   PetscErrorCode ierr;
835a5d4f66SBarry Smith 
845a5d4f66SBarry Smith   PetscFunctionBegin;
850700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
863050cee2SBarry Smith   if (!viewer) {
87ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
883050cee2SBarry Smith   }
890700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
905a5d4f66SBarry Smith 
91ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
92251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
9332077d6dSBarry Smith   if (iascii) {
9498c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
957b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
965a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
977904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
986831982aSBarry Smith     }
99b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1007b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
1017b23a99aSBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
1025a5d4f66SBarry Smith   PetscFunctionReturn(0);
1035a5d4f66SBarry Smith }
1045a5d4f66SBarry Smith 
1054a2ae208SSatish Balay #undef __FUNCT__
1064a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1071f428162SBarry Smith /*@
1082bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1092bdab257SBarry Smith     ordering and a global parallel ordering.
1102bdab257SBarry Smith 
1110f5bd95cSBarry Smith     Not collective
112b9cd556bSLois Curfman McInnes 
113a997ad1aSLois Curfman McInnes     Input Parameter:
1148c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1152bdab257SBarry Smith 
116a997ad1aSLois Curfman McInnes     Output Parameter:
1172bdab257SBarry Smith .   mapping - new mapping data structure
1182bdab257SBarry Smith 
119f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
120a997ad1aSLois Curfman McInnes     Level: advanced
121a997ad1aSLois Curfman McInnes 
122273d9f13SBarry Smith     Concepts: mapping^local to global
1232bdab257SBarry Smith 
1242bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1252bdab257SBarry Smith @*/
1267087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1272bdab257SBarry Smith {
1286849ba73SBarry Smith   PetscErrorCode ierr;
1293bbf0e92SBarry Smith   PetscInt       n,bs;
1305d0c19d7SBarry Smith   const PetscInt *indices;
1312bdab257SBarry Smith   MPI_Comm       comm;
1323bbf0e92SBarry Smith   PetscBool      isblock;
1333a40ed3dSBarry Smith 
1343a40ed3dSBarry Smith   PetscFunctionBegin;
1350700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1364482741eSBarry Smith   PetscValidPointer(mapping,2);
1372bdab257SBarry Smith 
1382bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1393b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1403bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
141*6006e8d2SBarry Smith   if (!isblock) {
142f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
143f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1442bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
145*6006e8d2SBarry Smith   } else {
146*6006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
147f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
148f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
149f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
150*6006e8d2SBarry Smith   }
1513a40ed3dSBarry Smith   PetscFunctionReturn(0);
1522bdab257SBarry Smith }
1535a5d4f66SBarry Smith 
154a4d96a55SJed Brown #undef __FUNCT__
155a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
156a4d96a55SJed Brown /*@C
157a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
158a4d96a55SJed Brown     ordering and a global parallel ordering.
159a4d96a55SJed Brown 
160a4d96a55SJed Brown     Collective
161a4d96a55SJed Brown 
162a4d96a55SJed Brown     Input Parameter:
163a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
164a4d96a55SJed Brown -   start - first global index on this process
165a4d96a55SJed Brown 
166a4d96a55SJed Brown     Output Parameter:
167a4d96a55SJed Brown .   mapping - new mapping data structure
168a4d96a55SJed Brown 
169a4d96a55SJed Brown     Level: advanced
170a4d96a55SJed Brown 
171a4d96a55SJed Brown     Concepts: mapping^local to global
172a4d96a55SJed Brown 
173a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
174a4d96a55SJed Brown @*/
175a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
176a4d96a55SJed Brown {
177a4d96a55SJed Brown   PetscErrorCode ierr;
178a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
179a4d96a55SJed Brown   const PetscInt *ilocal;
180a4d96a55SJed Brown   MPI_Comm       comm;
181a4d96a55SJed Brown 
182a4d96a55SJed Brown   PetscFunctionBegin;
183a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
184a4d96a55SJed Brown   PetscValidPointer(mapping,3);
185a4d96a55SJed Brown 
186a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1870298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
188f6e5521dSKarl Rupp   if (ilocal) {
189f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
190f6e5521dSKarl Rupp   }
191a4d96a55SJed Brown   else maxlocal = nleaves;
192785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
193785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
194a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
195a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
196a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
197a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
198f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
199a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
200a4d96a55SJed Brown   PetscFunctionReturn(0);
201a4d96a55SJed Brown }
202b46b645bSBarry Smith 
2034a2ae208SSatish Balay #undef __FUNCT__
20445b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
20545b6f7e9SBarry Smith /*@
20645b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
20745b6f7e9SBarry Smith     ordering and a global parallel ordering.
20845b6f7e9SBarry Smith 
20945b6f7e9SBarry Smith     Not Collective
21045b6f7e9SBarry Smith 
21145b6f7e9SBarry Smith     Input Parameters:
21245b6f7e9SBarry Smith .   mapping - mapping data structure
21345b6f7e9SBarry Smith 
21445b6f7e9SBarry Smith     Output Parameter:
21545b6f7e9SBarry Smith .   bs - the blocksize
21645b6f7e9SBarry Smith 
21745b6f7e9SBarry Smith     Level: advanced
21845b6f7e9SBarry Smith 
21945b6f7e9SBarry Smith     Concepts: mapping^local to global
22045b6f7e9SBarry Smith 
22145b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
22245b6f7e9SBarry Smith @*/
22345b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
22445b6f7e9SBarry Smith {
22545b6f7e9SBarry Smith   PetscFunctionBegin;
22645b6f7e9SBarry Smith   *bs = mapping->bs;
22745b6f7e9SBarry Smith   PetscFunctionReturn(0);
22845b6f7e9SBarry Smith }
22945b6f7e9SBarry Smith 
23045b6f7e9SBarry Smith #undef __FUNCT__
2314a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
232ba5bb76aSSatish Balay /*@
23390f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
23490f02eecSBarry Smith     ordering and a global parallel ordering.
2352362add9SBarry Smith 
23689d82c54SBarry Smith     Not Collective, but communicator may have more than one process
237b9cd556bSLois Curfman McInnes 
2382362add9SBarry Smith     Input Parameters:
23989d82c54SBarry Smith +   comm - MPI communicator
240f0413b6fSBarry Smith .   bs - the block size
24190f02eecSBarry Smith .   n - the number of local elements
242f0413b6fSBarry 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 by the blocksize bs
243d5ad8652SBarry Smith -   mode - see PetscCopyMode
2442362add9SBarry Smith 
245a997ad1aSLois Curfman McInnes     Output Parameter:
24690f02eecSBarry Smith .   mapping - new mapping data structure
2472362add9SBarry Smith 
248f0413b6fSBarry 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
249a997ad1aSLois Curfman McInnes     Level: advanced
250a997ad1aSLois Curfman McInnes 
251273d9f13SBarry Smith     Concepts: mapping^local to global
2522362add9SBarry Smith 
253d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2542362add9SBarry Smith @*/
255f0413b6fSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2562362add9SBarry Smith {
2576849ba73SBarry Smith   PetscErrorCode ierr;
25832dcc486SBarry Smith   PetscInt       *in;
259b46b645bSBarry Smith 
260b46b645bSBarry Smith   PetscFunctionBegin;
26173911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2624482741eSBarry Smith   PetscValidPointer(mapping,4);
263b46b645bSBarry Smith 
2640298fd71SBarry Smith   *mapping = NULL;
265607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2662362add9SBarry Smith 
26767c2884eSBarry Smith   ierr = PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
26852e6d16bSBarry Smith                            cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
269d4bb536fSBarry Smith   (*mapping)->n  = n;
270f0413b6fSBarry Smith   (*mapping)->bs = bs;
271d4bb536fSBarry Smith   /*
272d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
273d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
274d4bb536fSBarry Smith   */
275d4bb536fSBarry Smith   (*mapping)->globals = 0;
276d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
277785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
278d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
279d5ad8652SBarry Smith     (*mapping)->indices = in;
2806389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2816389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
2826389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
2836389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2846389a1a1SBarry Smith   }
285f6e5521dSKarl Rupp   else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
2863a40ed3dSBarry Smith   PetscFunctionReturn(0);
2872362add9SBarry Smith }
2882362add9SBarry Smith 
2894a2ae208SSatish Balay #undef __FUNCT__
2904a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
29190f02eecSBarry Smith /*@
29290f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
29390f02eecSBarry Smith    ordering and a global parallel ordering.
29490f02eecSBarry Smith 
2950f5bd95cSBarry Smith    Note Collective
296b9cd556bSLois Curfman McInnes 
29790f02eecSBarry Smith    Input Parameters:
29890f02eecSBarry Smith .  mapping - mapping data structure
29990f02eecSBarry Smith 
300a997ad1aSLois Curfman McInnes    Level: advanced
301a997ad1aSLois Curfman McInnes 
3023acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
30390f02eecSBarry Smith @*/
3046bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
30590f02eecSBarry Smith {
306dfbe8321SBarry Smith   PetscErrorCode ierr;
3075fd66863SKarl Rupp 
3083a40ed3dSBarry Smith   PetscFunctionBegin;
3096bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3106bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
311997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3126bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3136bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->globals);CHKERRQ(ierr);
314d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
315992144d0SBarry Smith   *mapping = 0;
3163a40ed3dSBarry Smith   PetscFunctionReturn(0);
31790f02eecSBarry Smith }
31890f02eecSBarry Smith 
3194a2ae208SSatish Balay #undef __FUNCT__
3204a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
32190f02eecSBarry Smith /*@
3223acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3233acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3243acfe500SLois Curfman McInnes     context.
32590f02eecSBarry Smith 
326b9cd556bSLois Curfman McInnes     Not collective
327b9cd556bSLois Curfman McInnes 
32890f02eecSBarry Smith     Input Parameters:
329b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
330b9cd556bSLois Curfman McInnes -   is - index set in local numbering
33190f02eecSBarry Smith 
33290f02eecSBarry Smith     Output Parameters:
33390f02eecSBarry Smith .   newis - index set in global numbering
33490f02eecSBarry Smith 
335a997ad1aSLois Curfman McInnes     Level: advanced
336a997ad1aSLois Curfman McInnes 
337273d9f13SBarry Smith     Concepts: mapping^local to global
3383acfe500SLois Curfman McInnes 
33990f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
340d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
34190f02eecSBarry Smith @*/
3427087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
34390f02eecSBarry Smith {
3446849ba73SBarry Smith   PetscErrorCode ierr;
345e24637baSBarry Smith   PetscInt       n,*idxout;
3465d0c19d7SBarry Smith   const PetscInt *idxin;
3473a40ed3dSBarry Smith 
3483a40ed3dSBarry Smith   PetscFunctionBegin;
3490700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3500700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3514482741eSBarry Smith   PetscValidPointer(newis,3);
35290f02eecSBarry Smith 
3533b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
35490f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
355785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
356e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
3573b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
358543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
3593a40ed3dSBarry Smith   PetscFunctionReturn(0);
36090f02eecSBarry Smith }
36190f02eecSBarry Smith 
362afcb2eb5SJed Brown #undef __FUNCT__
363afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
364b89cb25eSSatish Balay /*@
3653acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3663acfe500SLois Curfman McInnes    and converts them to the global numbering.
36790f02eecSBarry Smith 
368b9cd556bSLois Curfman McInnes    Not collective
369b9cd556bSLois Curfman McInnes 
370bb25748dSBarry Smith    Input Parameters:
371b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
372bb25748dSBarry Smith .  N - number of integers
373b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
374bb25748dSBarry Smith 
375bb25748dSBarry Smith    Output Parameter:
376bb25748dSBarry Smith .  out - indices in global numbering
377bb25748dSBarry Smith 
378b9cd556bSLois Curfman McInnes    Notes:
379b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
380d4bb536fSBarry Smith 
381a997ad1aSLois Curfman McInnes    Level: advanced
382a997ad1aSLois Curfman McInnes 
38345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3840752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
385d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
386bb25748dSBarry Smith 
387273d9f13SBarry Smith     Concepts: mapping^local to global
388afcb2eb5SJed Brown @*/
389afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
390afcb2eb5SJed Brown {
391e24637baSBarry Smith   PetscInt       i,bs = mapping->bs,Nmax = bs*mapping->n;
39245b6f7e9SBarry Smith   const PetscInt *idx = mapping->indices;
39345b6f7e9SBarry Smith 
39445b6f7e9SBarry Smith   PetscFunctionBegin;
39545b6f7e9SBarry Smith   if (bs == 1) {
39645b6f7e9SBarry Smith     for (i=0; i<N; i++) {
39745b6f7e9SBarry Smith       if (in[i] < 0) {
39845b6f7e9SBarry Smith         out[i] = in[i];
39945b6f7e9SBarry Smith         continue;
40045b6f7e9SBarry Smith       }
401e24637baSBarry 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);
40245b6f7e9SBarry Smith       out[i] = idx[in[i]];
40345b6f7e9SBarry Smith     }
40445b6f7e9SBarry Smith   } else {
40545b6f7e9SBarry Smith     for (i=0; i<N; i++) {
40645b6f7e9SBarry Smith       if (in[i] < 0) {
40745b6f7e9SBarry Smith         out[i] = in[i];
40845b6f7e9SBarry Smith         continue;
40945b6f7e9SBarry Smith       }
410e24637baSBarry 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);
41145b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
41245b6f7e9SBarry Smith     }
41345b6f7e9SBarry Smith   }
41445b6f7e9SBarry Smith   PetscFunctionReturn(0);
41545b6f7e9SBarry Smith }
41645b6f7e9SBarry Smith 
41745b6f7e9SBarry Smith #undef __FUNCT__
41845b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
41945b6f7e9SBarry Smith /*@
420*6006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
42145b6f7e9SBarry Smith 
42245b6f7e9SBarry Smith    Not collective
42345b6f7e9SBarry Smith 
42445b6f7e9SBarry Smith    Input Parameters:
42545b6f7e9SBarry Smith +  mapping - the local to global mapping context
42645b6f7e9SBarry Smith .  N - number of integers
427*6006e8d2SBarry Smith -  in - input indices in local block numbering
42845b6f7e9SBarry Smith 
42945b6f7e9SBarry Smith    Output Parameter:
430*6006e8d2SBarry Smith .  out - indices in global block numbering
43145b6f7e9SBarry Smith 
43245b6f7e9SBarry Smith    Notes:
43345b6f7e9SBarry Smith    The in and out array parameters may be identical.
43445b6f7e9SBarry Smith 
435*6006e8d2SBarry Smith    Example:
436*6006e8d2SBarry 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
437*6006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
438*6006e8d2SBarry Smith 
43945b6f7e9SBarry Smith    Level: advanced
44045b6f7e9SBarry Smith 
44145b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
44245b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
44345b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
44445b6f7e9SBarry Smith 
44545b6f7e9SBarry Smith     Concepts: mapping^local to global
44645b6f7e9SBarry Smith @*/
44745b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
44845b6f7e9SBarry Smith {
449afcb2eb5SJed Brown   PetscInt       i,Nmax = mapping->n;
450afcb2eb5SJed Brown   const PetscInt *idx = mapping->indices;
451d4bb536fSBarry Smith 
452afcb2eb5SJed Brown   PetscFunctionBegin;
453afcb2eb5SJed Brown   for (i=0; i<N; i++) {
454afcb2eb5SJed Brown     if (in[i] < 0) {
455afcb2eb5SJed Brown       out[i] = in[i];
456afcb2eb5SJed Brown       continue;
457afcb2eb5SJed Brown     }
458e24637baSBarry 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);
459afcb2eb5SJed Brown     out[i] = idx[in[i]];
460afcb2eb5SJed Brown   }
461afcb2eb5SJed Brown   PetscFunctionReturn(0);
462afcb2eb5SJed Brown }
463d4bb536fSBarry Smith 
464d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
465d4bb536fSBarry Smith 
4664a2ae208SSatish Balay #undef __FUNCT__
4674a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
468d4bb536fSBarry Smith /*
469d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
470d4bb536fSBarry Smith */
4716849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
472d4bb536fSBarry Smith {
4736849ba73SBarry Smith   PetscErrorCode ierr;
47432dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
475d4bb536fSBarry Smith 
4763a40ed3dSBarry Smith   PetscFunctionBegin;
477d4bb536fSBarry Smith   end   = 0;
478ec268f7cSJed Brown   start = PETSC_MAX_INT;
479d4bb536fSBarry Smith 
480d4bb536fSBarry Smith   for (i=0; i<n; i++) {
481d4bb536fSBarry Smith     if (idx[i] < 0) continue;
482d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
483d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
484d4bb536fSBarry Smith   }
485d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
486d4bb536fSBarry Smith   mapping->globalstart = start;
487d4bb536fSBarry Smith   mapping->globalend   = end;
488d4bb536fSBarry Smith 
489785e854fSJed Brown   ierr             = PetscMalloc1((end-start+2),&globals);CHKERRQ(ierr);
490b0a32e0cSBarry Smith   mapping->globals = globals;
491f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
492d4bb536fSBarry Smith   for (i=0; i<n; i++) {
493d4bb536fSBarry Smith     if (idx[i] < 0) continue;
494d4bb536fSBarry Smith     globals[idx[i] - start] = i;
495d4bb536fSBarry Smith   }
496d4bb536fSBarry Smith 
4973bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
4983a40ed3dSBarry Smith   PetscFunctionReturn(0);
499d4bb536fSBarry Smith }
500d4bb536fSBarry Smith 
5014a2ae208SSatish Balay #undef __FUNCT__
5024a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
503d4bb536fSBarry Smith /*@
504a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
505a997ad1aSLois Curfman McInnes     specified with a global numbering.
506d4bb536fSBarry Smith 
507b9cd556bSLois Curfman McInnes     Not collective
508b9cd556bSLois Curfman McInnes 
509d4bb536fSBarry Smith     Input Parameters:
510b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
511d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
512d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
513d4bb536fSBarry Smith .   n - number of global indices to map
514b9cd556bSLois Curfman McInnes -   idx - global indices to map
515d4bb536fSBarry Smith 
516d4bb536fSBarry Smith     Output Parameters:
517b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
518b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
519e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5200298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
521e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
522e182c471SBarry Smith              a second time to set the values.
523d4bb536fSBarry Smith 
524b9cd556bSLois Curfman McInnes     Notes:
5250298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
526d4bb536fSBarry Smith 
5270f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5280f5bd95cSBarry Smith     array to compute these.
5290f5bd95cSBarry Smith 
530a997ad1aSLois Curfman McInnes     Level: advanced
531a997ad1aSLois Curfman McInnes 
53232fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
53332fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
53432fd6b96SBarry Smith 
535273d9f13SBarry Smith     Concepts: mapping^global to local
536d4bb536fSBarry Smith 
5379d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
538d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
539d4bb536fSBarry Smith @*/
5407087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
54132dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
542d4bb536fSBarry Smith {
5439d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
5449d90f715SBarry Smith   PetscErrorCode ierr;
5459d90f715SBarry Smith 
5469d90f715SBarry Smith   PetscFunctionBegin;
5479d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
5489d90f715SBarry Smith   if (!mapping->globals) {
5499d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
5509d90f715SBarry Smith   }
5519d90f715SBarry Smith   globals = mapping->globals;
5529d90f715SBarry Smith   start   = mapping->globalstart;
5539d90f715SBarry Smith   end     = mapping->globalend;
5549d90f715SBarry Smith   bs      = mapping->bs;
5559d90f715SBarry Smith 
5569d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
5579d90f715SBarry Smith     if (idxout) {
5589d90f715SBarry Smith       for (i=0; i<n; i++) {
5599d90f715SBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
5609d90f715SBarry Smith         else if (idx[i] < bs*start) idxout[i] = -1;
5619d90f715SBarry Smith         else if (idx[i] > bs*end)   idxout[i] = -1;
5629d90f715SBarry Smith         else                        idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5639d90f715SBarry Smith       }
5649d90f715SBarry Smith     }
5659d90f715SBarry Smith     if (nout) *nout = n;
5669d90f715SBarry Smith   } else {
5679d90f715SBarry Smith     if (idxout) {
5689d90f715SBarry Smith       for (i=0; i<n; i++) {
5699d90f715SBarry Smith         if (idx[i] < 0) continue;
5709d90f715SBarry Smith         if (idx[i] < bs*start) continue;
5719d90f715SBarry Smith         if (idx[i] > bs*end) continue;
5729d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5739d90f715SBarry Smith         if (tmp < 0) continue;
5749d90f715SBarry Smith         idxout[nf++] = tmp;
5759d90f715SBarry Smith       }
5769d90f715SBarry Smith     } else {
5779d90f715SBarry Smith       for (i=0; i<n; i++) {
5789d90f715SBarry Smith         if (idx[i] < 0) continue;
5799d90f715SBarry Smith         if (idx[i] < bs*start) continue;
5809d90f715SBarry Smith         if (idx[i] > bs*end) continue;
5819d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5829d90f715SBarry Smith         if (tmp < 0) continue;
5839d90f715SBarry Smith         nf++;
5849d90f715SBarry Smith       }
5859d90f715SBarry Smith     }
5869d90f715SBarry Smith     if (nout) *nout = nf;
5879d90f715SBarry Smith   }
5889d90f715SBarry Smith   PetscFunctionReturn(0);
5899d90f715SBarry Smith }
5909d90f715SBarry Smith 
5919d90f715SBarry Smith #undef __FUNCT__
5929d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
5939d90f715SBarry Smith /*@
5949d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
5959d90f715SBarry Smith     specified with a block global numbering.
5969d90f715SBarry Smith 
5979d90f715SBarry Smith     Not collective
5989d90f715SBarry Smith 
5999d90f715SBarry Smith     Input Parameters:
6009d90f715SBarry Smith +   mapping - mapping between local and global numbering
6019d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
6029d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
6039d90f715SBarry Smith .   n - number of global indices to map
6049d90f715SBarry Smith -   idx - global indices to map
6059d90f715SBarry Smith 
6069d90f715SBarry Smith     Output Parameters:
6079d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
6089d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
6099d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
6109d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
6119d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
6129d90f715SBarry Smith              a second time to set the values.
6139d90f715SBarry Smith 
6149d90f715SBarry Smith     Notes:
6159d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
6169d90f715SBarry Smith 
6179d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6189d90f715SBarry Smith     array to compute these.
6199d90f715SBarry Smith 
6209d90f715SBarry Smith     Level: advanced
6219d90f715SBarry Smith 
6229d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
6239d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
6249d90f715SBarry Smith 
6259d90f715SBarry Smith     Concepts: mapping^global to local
6269d90f715SBarry Smith 
6279d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
6289d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
6299d90f715SBarry Smith @*/
6309d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
6319d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
6329d90f715SBarry Smith {
63332dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
6346849ba73SBarry Smith   PetscErrorCode ierr;
635d4bb536fSBarry Smith 
6363a40ed3dSBarry Smith   PetscFunctionBegin;
6370700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
638d4bb536fSBarry Smith   if (!mapping->globals) {
639d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
640d4bb536fSBarry Smith   }
641d4bb536fSBarry Smith   globals = mapping->globals;
642d4bb536fSBarry Smith   start   = mapping->globalstart;
643d4bb536fSBarry Smith   end     = mapping->globalend;
644d4bb536fSBarry Smith 
645d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
646d4bb536fSBarry Smith     if (idxout) {
647d4bb536fSBarry Smith       for (i=0; i<n; i++) {
648d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
649d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
650d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
651d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
652d4bb536fSBarry Smith       }
653d4bb536fSBarry Smith     }
654d4bb536fSBarry Smith     if (nout) *nout = n;
655d4bb536fSBarry Smith   } else {
656d4bb536fSBarry Smith     if (idxout) {
657d4bb536fSBarry Smith       for (i=0; i<n; i++) {
658d4bb536fSBarry Smith         if (idx[i] < 0) continue;
659d4bb536fSBarry Smith         if (idx[i] < start) continue;
660d4bb536fSBarry Smith         if (idx[i] > end) continue;
661d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
662d4bb536fSBarry Smith         if (tmp < 0) continue;
663d4bb536fSBarry Smith         idxout[nf++] = tmp;
664d4bb536fSBarry Smith       }
665d4bb536fSBarry Smith     } else {
666d4bb536fSBarry Smith       for (i=0; i<n; i++) {
667d4bb536fSBarry Smith         if (idx[i] < 0) continue;
668d4bb536fSBarry Smith         if (idx[i] < start) continue;
669d4bb536fSBarry Smith         if (idx[i] > end) continue;
670d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
671d4bb536fSBarry Smith         if (tmp < 0) continue;
672d4bb536fSBarry Smith         nf++;
673d4bb536fSBarry Smith       }
674d4bb536fSBarry Smith     }
675d4bb536fSBarry Smith     if (nout) *nout = nf;
676d4bb536fSBarry Smith   }
6773a40ed3dSBarry Smith   PetscFunctionReturn(0);
678d4bb536fSBarry Smith }
67990f02eecSBarry Smith 
6804a2ae208SSatish Balay #undef __FUNCT__
6816a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
68289d82c54SBarry Smith /*@C
6836a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
68489d82c54SBarry Smith      each index shared by more than one processor
68589d82c54SBarry Smith 
68689d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
68789d82c54SBarry Smith 
68889d82c54SBarry Smith     Input Parameters:
68989d82c54SBarry Smith .   mapping - the mapping from local to global indexing
69089d82c54SBarry Smith 
69189d82c54SBarry Smith     Output Parameter:
69289d82c54SBarry Smith +   nproc - number of processors that are connected to this one
69389d82c54SBarry Smith .   proc - neighboring processors
69407b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
6953463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
69689d82c54SBarry Smith 
69789d82c54SBarry Smith     Level: advanced
69889d82c54SBarry Smith 
699273d9f13SBarry Smith     Concepts: mapping^local to global
70089d82c54SBarry Smith 
7012cfcea29SBarry Smith     Fortran Usage:
7022cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
7032cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
7042cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
7052cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
7062cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
7072cfcea29SBarry Smith 
7082cfcea29SBarry Smith 
70907b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
71007b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
71189d82c54SBarry Smith @*/
7126a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
71389d82c54SBarry Smith {
7146849ba73SBarry Smith   PetscErrorCode ierr;
71597f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
71632dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
71732dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
71897f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
71932dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
72032dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
72189d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
72230dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
723ce94432eSBarry Smith   MPI_Comm       comm;
724ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
72589d82c54SBarry Smith 
72689d82c54SBarry Smith   PetscFunctionBegin;
7270700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
728ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
72924cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
73024cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
73124cf384cSBarry Smith   if (size == 1) {
73224cf384cSBarry Smith     *nproc         = 0;
7330298fd71SBarry Smith     *procs         = NULL;
73432dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
7351e2105dcSBarry Smith     (*numprocs)[0] = 0;
73632dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
7370298fd71SBarry Smith     (*indices)[0]  = NULL;
73824cf384cSBarry Smith     PetscFunctionReturn(0);
73924cf384cSBarry Smith   }
74024cf384cSBarry Smith 
7410298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
74207b52d57SBarry Smith 
7433677ff5aSBarry Smith   /*
7446a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
7453677ff5aSBarry Smith 
7463677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
7473677ff5aSBarry Smith            numbering, just for this routine.
7483677ff5aSBarry Smith 
7493677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
7503677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
7513677ff5aSBarry Smith 
7523677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
7533677ff5aSBarry Smith 
7543677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
7553677ff5aSBarry Smith            local subdomain
7563677ff5aSBarry Smith   */
75724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
75824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
75924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
76089d82c54SBarry Smith 
76189d82c54SBarry Smith   for (i=0; i<n; i++) {
76289d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
76389d82c54SBarry Smith   }
76432dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
76578058e43SBarry Smith   Ng++;
76689d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
76789d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
768bc8ff85bSBarry Smith   scale  = Ng/size + 1;
769a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
770caba0dd0SBarry Smith   rstart = scale*rank;
77189d82c54SBarry Smith 
77289d82c54SBarry Smith   /* determine ownership ranges of global indices */
773785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
77432dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
77589d82c54SBarry Smith 
77689d82c54SBarry Smith   /* determine owners of each local node  */
777785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
77889d82c54SBarry Smith   for (i=0; i<n; i++) {
7793677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
78027c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
7813677ff5aSBarry Smith     owner[i]         = proc;
78227c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
78389d82c54SBarry Smith   }
78427c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
7857904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
78689d82c54SBarry Smith 
78789d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
78827c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
7897904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
79089d82c54SBarry Smith 
79189d82c54SBarry Smith   /* post receives for owned rows */
792785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
793785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1),&recv_waits);CHKERRQ(ierr);
79489d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
79532dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
79689d82c54SBarry Smith   }
79789d82c54SBarry Smith 
79889d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
799785e854fSJed Brown   ierr      = PetscMalloc1((2*n+1),&sends);CHKERRQ(ierr);
800785e854fSJed Brown   ierr      = PetscMalloc1((size+1),&starts);CHKERRQ(ierr);
80189d82c54SBarry Smith   starts[0] = 0;
802f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
80389d82c54SBarry Smith   for (i=0; i<n; i++) {
80489d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
80530dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
80689d82c54SBarry Smith   }
80789d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
80889d82c54SBarry Smith   starts[0] = 0;
809f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
81089d82c54SBarry Smith 
81189d82c54SBarry Smith   /* send the messages */
812785e854fSJed Brown   ierr = PetscMalloc1((nsends+1),&send_waits);CHKERRQ(ierr);
813785e854fSJed Brown   ierr = PetscMalloc1((nsends+1),&dest);CHKERRQ(ierr);
81489d82c54SBarry Smith   cnt = 0;
81589d82c54SBarry Smith   for (i=0; i<size; i++) {
81627c402fcSBarry Smith     if (nprocs[2*i]) {
81732dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
81830dcb7c9SBarry Smith       dest[cnt] = i;
81989d82c54SBarry Smith       cnt++;
82089d82c54SBarry Smith     }
82189d82c54SBarry Smith   }
82289d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
82389d82c54SBarry Smith 
82489d82c54SBarry Smith   /* wait on receives */
825785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1),&source);CHKERRQ(ierr);
826785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1),&len);CHKERRQ(ierr);
82789d82c54SBarry Smith   cnt  = nrecvs;
828785e854fSJed Brown   ierr = PetscMalloc1((ng+1),&nownedsenders);CHKERRQ(ierr);
82932dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
83089d82c54SBarry Smith   while (cnt) {
83189d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
83289d82c54SBarry Smith     /* unpack receives into our local space */
83332dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
83489d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
83530dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
836caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
83730dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
83889d82c54SBarry Smith     cnt--;
83989d82c54SBarry Smith   }
84089d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
84189d82c54SBarry Smith 
84230dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
843bc8ff85bSBarry Smith   nowned  = 0;
844bc8ff85bSBarry Smith   nownedm = 0;
845bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
846bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
847bc8ff85bSBarry Smith   }
848bc8ff85bSBarry Smith 
849bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
850785e854fSJed Brown   ierr      = PetscMalloc1((nownedm+1),&ownedsenders);CHKERRQ(ierr);
851785e854fSJed Brown   ierr      = PetscMalloc1((ng+1),&starts);CHKERRQ(ierr);
852bc8ff85bSBarry Smith   starts[0] = 0;
853bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
854bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
855bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
856bc8ff85bSBarry Smith   }
857bc8ff85bSBarry Smith 
85830dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
859bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
860bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
86130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
862f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
863bc8ff85bSBarry Smith     }
864bc8ff85bSBarry Smith   }
865bc8ff85bSBarry Smith 
86607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
86730dcb7c9SBarry Smith     starts[0] = 0;
86830dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
86930dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
87030dcb7c9SBarry Smith       else starts[i] = starts[i-1];
87130dcb7c9SBarry Smith     }
87230dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
87330dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
8747904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
87530dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
8767904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
87730dcb7c9SBarry Smith         }
87830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
87930dcb7c9SBarry Smith       }
88030dcb7c9SBarry Smith     }
8810ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
88207b52d57SBarry Smith   } /* -----------------------------------  */
88330dcb7c9SBarry Smith 
8843677ff5aSBarry Smith   /* wait on original sends */
8853a96401aSBarry Smith   if (nsends) {
886785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
8873a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
8883a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
8893a96401aSBarry Smith   }
89089d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8913a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
8923677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
8933677ff5aSBarry Smith 
8943677ff5aSBarry Smith   /* pack messages to send back to local owners */
89530dcb7c9SBarry Smith   starts[0] = 0;
89630dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
89730dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
89830dcb7c9SBarry Smith     else starts[i] = starts[i-1];
89930dcb7c9SBarry Smith   }
90030dcb7c9SBarry Smith   nsends2 = nrecvs;
901785e854fSJed Brown   ierr    = PetscMalloc1((nsends2+1),&nprocs);CHKERRQ(ierr); /* length of each message */
90230dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
90330dcb7c9SBarry Smith     nprocs[i] = 1;
90430dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
90530dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
906f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
90730dcb7c9SBarry Smith     }
90830dcb7c9SBarry Smith   }
909f6e5521dSKarl Rupp   nt = 0;
910f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
911f6e5521dSKarl Rupp 
912785e854fSJed Brown   ierr = PetscMalloc1((nt+1),&sends2);CHKERRQ(ierr);
913785e854fSJed Brown   ierr = PetscMalloc1((nsends2+1),&starts2);CHKERRQ(ierr);
914f6e5521dSKarl Rupp 
915f6e5521dSKarl Rupp   starts2[0] = 0;
916f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
91730dcb7c9SBarry Smith   /*
91830dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
91930dcb7c9SBarry Smith        (0) the number of nodes being sent back
92030dcb7c9SBarry Smith        (1) the local node number,
92130dcb7c9SBarry Smith        (2) the number of processors sharing it,
92230dcb7c9SBarry Smith        (3) the processors sharing it
92330dcb7c9SBarry Smith   */
92430dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
92530dcb7c9SBarry Smith     cnt = 1;
92630dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
92730dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
92830dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
92930dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
93030dcb7c9SBarry Smith         sends2[starts2[i]]++;
93130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
93230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
93332dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
93430dcb7c9SBarry Smith         cnt += nownedsenders[node];
93530dcb7c9SBarry Smith       }
93630dcb7c9SBarry Smith     }
93730dcb7c9SBarry Smith   }
93830dcb7c9SBarry Smith 
93930dcb7c9SBarry Smith   /* receive the message lengths */
94030dcb7c9SBarry Smith   nrecvs2 = nsends;
941785e854fSJed Brown   ierr    = PetscMalloc1((nrecvs2+1),&lens2);CHKERRQ(ierr);
942785e854fSJed Brown   ierr    = PetscMalloc1((nrecvs2+1),&starts3);CHKERRQ(ierr);
943785e854fSJed Brown   ierr    = PetscMalloc1((nrecvs2+1),&recv_waits);CHKERRQ(ierr);
94430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
945d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
94630dcb7c9SBarry Smith   }
947d44834fbSBarry Smith 
9488a8e0b3aSBarry Smith   /* send the message lengths */
9498a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
9508a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
9518a8e0b3aSBarry Smith   }
9528a8e0b3aSBarry Smith 
953d44834fbSBarry Smith   /* wait on receives of lens */
9540c468ba9SBarry Smith   if (nrecvs2) {
955785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
956d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
957d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
9580c468ba9SBarry Smith   }
959a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
960d44834fbSBarry Smith 
96130dcb7c9SBarry Smith   starts3[0] = 0;
962d44834fbSBarry Smith   nt         = 0;
96330dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
96430dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
965d44834fbSBarry Smith     nt          += lens2[i];
96630dcb7c9SBarry Smith   }
96776466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
968d44834fbSBarry Smith 
969785e854fSJed Brown   ierr = PetscMalloc1((nt+1),&recvs2);CHKERRQ(ierr);
970785e854fSJed Brown   ierr = PetscMalloc1((nrecvs2+1),&recv_waits);CHKERRQ(ierr);
97152b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
97232dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
97330dcb7c9SBarry Smith   }
97430dcb7c9SBarry Smith 
97530dcb7c9SBarry Smith   /* send the messages */
976785e854fSJed Brown   ierr = PetscMalloc1((nsends2+1),&send_waits);CHKERRQ(ierr);
97730dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
97832dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
97930dcb7c9SBarry Smith   }
98030dcb7c9SBarry Smith 
98130dcb7c9SBarry Smith   /* wait on receives */
9820c468ba9SBarry Smith   if (nrecvs2) {
983785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
98430dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
98530dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
9860c468ba9SBarry Smith   }
98730dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
98830dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
98930dcb7c9SBarry Smith 
99007b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
99130dcb7c9SBarry Smith     cnt = 0;
99230dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
99330dcb7c9SBarry Smith       nt = recvs2[cnt++];
99430dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
9957904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
99630dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
9977904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
99830dcb7c9SBarry Smith         }
99930dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
100030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
100130dcb7c9SBarry Smith       }
100230dcb7c9SBarry Smith     }
10030ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
100407b52d57SBarry Smith   } /* -----------------------------------  */
100530dcb7c9SBarry Smith 
100630dcb7c9SBarry Smith   /* count number subdomains for each local node */
1007785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
100832dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
100930dcb7c9SBarry Smith   cnt  = 0;
101030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
101130dcb7c9SBarry Smith     nt = recvs2[cnt++];
101230dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1013f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
101430dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
101530dcb7c9SBarry Smith     }
101630dcb7c9SBarry Smith   }
101730dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
101830dcb7c9SBarry Smith   *nproc    = nt;
1019785e854fSJed Brown   ierr = PetscMalloc1((nt+1),procs);CHKERRQ(ierr);
1020785e854fSJed Brown   ierr = PetscMalloc1((nt+1),numprocs);CHKERRQ(ierr);
1021785e854fSJed Brown   ierr = PetscMalloc1((nt+1),indices);CHKERRQ(ierr);
10220298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1023785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
102430dcb7c9SBarry Smith   cnt       = 0;
102530dcb7c9SBarry Smith   for (i=0; i<size; i++) {
102630dcb7c9SBarry Smith     if (nprocs[i] > 0) {
102730dcb7c9SBarry Smith       bprocs[i]        = cnt;
102830dcb7c9SBarry Smith       (*procs)[cnt]    = i;
102930dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1030785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
103130dcb7c9SBarry Smith       cnt++;
103230dcb7c9SBarry Smith     }
103330dcb7c9SBarry Smith   }
103430dcb7c9SBarry Smith 
103530dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
103632dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
103730dcb7c9SBarry Smith   cnt  = 0;
103830dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
103930dcb7c9SBarry Smith     nt = recvs2[cnt++];
104030dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1041f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
104230dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
104330dcb7c9SBarry Smith     }
104430dcb7c9SBarry Smith   }
104530dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
104607b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
104730dcb7c9SBarry Smith 
104807b52d57SBarry Smith   /* sort the node indexing by their global numbers */
104907b52d57SBarry Smith   nt = *nproc;
105007b52d57SBarry Smith   for (i=0; i<nt; i++) {
1051785e854fSJed Brown     ierr = PetscMalloc1(((*numprocs)[i]),&tmp);CHKERRQ(ierr);
1052f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
105307b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
105407b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
105507b52d57SBarry Smith   }
105607b52d57SBarry Smith 
105707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
105830dcb7c9SBarry Smith     nt = *nproc;
105930dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
10607904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
106130dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
10627904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
106330dcb7c9SBarry Smith       }
106430dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
106530dcb7c9SBarry Smith     }
10660ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
106707b52d57SBarry Smith   } /* -----------------------------------  */
106830dcb7c9SBarry Smith 
106930dcb7c9SBarry Smith   /* wait on sends */
107030dcb7c9SBarry Smith   if (nsends2) {
1071785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
107230dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
107330dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
107430dcb7c9SBarry Smith   }
107530dcb7c9SBarry Smith 
107630dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
107730dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
107830dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10793677ff5aSBarry Smith 
1080bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1081bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1082bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
108330dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
108430dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
108589d82c54SBarry Smith 
108689d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
108797f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
108889d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
10893a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
109030dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
109124cf384cSBarry Smith 
109224cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
109324cf384cSBarry Smith   first_procs    = (*procs)[0];
109424cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
109524cf384cSBarry Smith   first_indices  = (*indices)[0];
109624cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
109724cf384cSBarry Smith     if ((*procs)[i] == rank) {
109824cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
109924cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
110024cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
110124cf384cSBarry Smith       (*procs)[i]    = first_procs;
110224cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
110324cf384cSBarry Smith       (*indices)[i]  = first_indices;
110424cf384cSBarry Smith       break;
110524cf384cSBarry Smith     }
110624cf384cSBarry Smith   }
110789d82c54SBarry Smith   PetscFunctionReturn(0);
110889d82c54SBarry Smith }
110989d82c54SBarry Smith 
11104a2ae208SSatish Balay #undef __FUNCT__
11116a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
11126a818285SBarry Smith /*@C
11136a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
11146a818285SBarry Smith 
11156a818285SBarry Smith     Collective on ISLocalToGlobalMapping
11166a818285SBarry Smith 
11176a818285SBarry Smith     Input Parameters:
11186a818285SBarry Smith .   mapping - the mapping from local to global indexing
11196a818285SBarry Smith 
11206a818285SBarry Smith     Output Parameter:
11216a818285SBarry Smith +   nproc - number of processors that are connected to this one
11226a818285SBarry Smith .   proc - neighboring processors
11236a818285SBarry Smith .   numproc - number of indices for each processor
11246a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
11256a818285SBarry Smith 
11266a818285SBarry Smith     Level: advanced
11276a818285SBarry Smith 
11286a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
11296a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
11306a818285SBarry Smith @*/
11316a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
11326a818285SBarry Smith {
11336a818285SBarry Smith   PetscErrorCode ierr;
11346a818285SBarry Smith   PetscInt       i;
11356a818285SBarry Smith 
11366a818285SBarry Smith   PetscFunctionBegin;
11376a818285SBarry Smith   ierr = PetscFree(*procs);CHKERRQ(ierr);
11386a818285SBarry Smith   ierr = PetscFree(*numprocs);CHKERRQ(ierr);
11396a818285SBarry Smith   if (*indices) {
11406a818285SBarry Smith     ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
11416a818285SBarry Smith     for (i=1; i<*nproc; i++) {
11426a818285SBarry Smith       ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
11436a818285SBarry Smith     }
11446a818285SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
11456a818285SBarry Smith   }
11466a818285SBarry Smith   PetscFunctionReturn(0);
11476a818285SBarry Smith }
11486a818285SBarry Smith 
11496a818285SBarry Smith #undef __FUNCT__
11506a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
11516a818285SBarry Smith /*@C
11526a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
11536a818285SBarry Smith      each index shared by more than one processor
11546a818285SBarry Smith 
11556a818285SBarry Smith     Collective on ISLocalToGlobalMapping
11566a818285SBarry Smith 
11576a818285SBarry Smith     Input Parameters:
11586a818285SBarry Smith .   mapping - the mapping from local to global indexing
11596a818285SBarry Smith 
11606a818285SBarry Smith     Output Parameter:
11616a818285SBarry Smith +   nproc - number of processors that are connected to this one
11626a818285SBarry Smith .   proc - neighboring processors
11636a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
11646a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
11656a818285SBarry Smith 
11666a818285SBarry Smith     Level: advanced
11676a818285SBarry Smith 
11686a818285SBarry Smith     Concepts: mapping^local to global
11696a818285SBarry Smith 
11706a818285SBarry Smith     Fortran Usage:
11716a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
11726a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
11736a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
11746a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
11756a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
11766a818285SBarry Smith 
11776a818285SBarry Smith 
11786a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
11796a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
11806a818285SBarry Smith @*/
11816a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
11826a818285SBarry Smith {
11836a818285SBarry Smith   PetscErrorCode ierr;
11846a818285SBarry Smith   PetscInt       **bindices = NULL,bs = mapping->bs,i,j,k;
11856a818285SBarry Smith 
11866a818285SBarry Smith   PetscFunctionBegin;
11876a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
11886a818285SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,numprocs,&bindices);CHKERRQ(ierr);
1189732f65e3SBarry Smith   ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
11906a818285SBarry Smith   for (i=0; i<*nproc; i++) {
11916a818285SBarry Smith     ierr = PetscMalloc1(bs*(*numprocs)[i],&(*indices)[i]);CHKERRQ(ierr);
11926a818285SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
11936a818285SBarry Smith       for (k=0; k<bs; k++) {
11946a818285SBarry Smith         (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
11956a818285SBarry Smith       }
11966a818285SBarry Smith     }
11976a818285SBarry Smith     (*numprocs)[i] *= bs;
11986a818285SBarry Smith   }
11996a818285SBarry Smith   if (bindices) {
12006a818285SBarry Smith     ierr = PetscFree(bindices[0]);CHKERRQ(ierr);
12016a818285SBarry Smith     for (i=1; i<*nproc; i++) {
12026a818285SBarry Smith       ierr = PetscFree(bindices[i]);CHKERRQ(ierr);
12036a818285SBarry Smith     }
12046a818285SBarry Smith     ierr = PetscFree(bindices);CHKERRQ(ierr);
12056a818285SBarry Smith   }
12066a818285SBarry Smith   PetscFunctionReturn(0);
12076a818285SBarry Smith }
12086a818285SBarry Smith 
12096a818285SBarry Smith #undef __FUNCT__
12104a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
121107b52d57SBarry Smith /*@C
121207b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
121389d82c54SBarry Smith 
121407b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
121507b52d57SBarry Smith 
121607b52d57SBarry Smith     Input Parameters:
121707b52d57SBarry Smith .   mapping - the mapping from local to global indexing
121807b52d57SBarry Smith 
121907b52d57SBarry Smith     Output Parameter:
122007b52d57SBarry Smith +   nproc - number of processors that are connected to this one
122107b52d57SBarry Smith .   proc - neighboring processors
122207b52d57SBarry Smith .   numproc - number of indices for each processor
122307b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
122407b52d57SBarry Smith 
122507b52d57SBarry Smith     Level: advanced
122607b52d57SBarry Smith 
122707b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
122807b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
122907b52d57SBarry Smith @*/
12307087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
123107b52d57SBarry Smith {
12326849ba73SBarry Smith   PetscErrorCode ierr;
123307b52d57SBarry Smith 
123407b52d57SBarry Smith   PetscFunctionBegin;
12356a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
123607b52d57SBarry Smith   PetscFunctionReturn(0);
123707b52d57SBarry Smith }
123886994e45SJed Brown 
123986994e45SJed Brown #undef __FUNCT__
124086994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
124186994e45SJed Brown /*@C
1242107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
124386994e45SJed Brown 
124486994e45SJed Brown    Not Collective
124586994e45SJed Brown 
124686994e45SJed Brown    Input Arguments:
124786994e45SJed Brown . ltog - local to global mapping
124886994e45SJed Brown 
124986994e45SJed Brown    Output Arguments:
1250565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
125186994e45SJed Brown 
125286994e45SJed Brown    Level: advanced
125386994e45SJed Brown 
1254107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1255107e9a97SBarry Smith 
1256107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
125786994e45SJed Brown @*/
12587087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
125986994e45SJed Brown {
126086994e45SJed Brown   PetscFunctionBegin;
126186994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
126286994e45SJed Brown   PetscValidPointer(array,2);
126345b6f7e9SBarry Smith   if (ltog->bs == 1) {
126486994e45SJed Brown     *array = ltog->indices;
126545b6f7e9SBarry Smith   } else {
126645b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
126745b6f7e9SBarry Smith     const PetscInt *ii;
126845b6f7e9SBarry Smith     PetscErrorCode ierr;
126945b6f7e9SBarry Smith 
127045b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
127145b6f7e9SBarry Smith     *array = jj;
127245b6f7e9SBarry Smith     k    = 0;
127345b6f7e9SBarry Smith     ii   = ltog->indices;
127445b6f7e9SBarry Smith     for (i=0; i<n; i++)
127545b6f7e9SBarry Smith       for (j=0; j<bs; j++)
127645b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
127745b6f7e9SBarry Smith   }
127886994e45SJed Brown   PetscFunctionReturn(0);
127986994e45SJed Brown }
128086994e45SJed Brown 
128186994e45SJed Brown #undef __FUNCT__
128286994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
128386994e45SJed Brown /*@C
128486994e45SJed Brown    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingRestoreIndices()
128586994e45SJed Brown 
128686994e45SJed Brown    Not Collective
128786994e45SJed Brown 
128886994e45SJed Brown    Input Arguments:
128986994e45SJed Brown + ltog - local to global mapping
129086994e45SJed Brown - array - array of indices
129186994e45SJed Brown 
129286994e45SJed Brown    Level: advanced
129386994e45SJed Brown 
129486994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
129586994e45SJed Brown @*/
12967087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
129786994e45SJed Brown {
129886994e45SJed Brown   PetscFunctionBegin;
129986994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
130086994e45SJed Brown   PetscValidPointer(array,2);
130145b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
130245b6f7e9SBarry Smith 
130345b6f7e9SBarry Smith   if (ltog->bs > 1) {
130445b6f7e9SBarry Smith     PetscErrorCode ierr;
130545b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
130645b6f7e9SBarry Smith   }
130745b6f7e9SBarry Smith   PetscFunctionReturn(0);
130845b6f7e9SBarry Smith }
130945b6f7e9SBarry Smith 
131045b6f7e9SBarry Smith #undef __FUNCT__
131145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
131245b6f7e9SBarry Smith /*@C
131345b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
131445b6f7e9SBarry Smith 
131545b6f7e9SBarry Smith    Not Collective
131645b6f7e9SBarry Smith 
131745b6f7e9SBarry Smith    Input Arguments:
131845b6f7e9SBarry Smith . ltog - local to global mapping
131945b6f7e9SBarry Smith 
132045b6f7e9SBarry Smith    Output Arguments:
132145b6f7e9SBarry Smith . array - array of indices
132245b6f7e9SBarry Smith 
132345b6f7e9SBarry Smith    Level: advanced
132445b6f7e9SBarry Smith 
132545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
132645b6f7e9SBarry Smith @*/
132745b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
132845b6f7e9SBarry Smith {
132945b6f7e9SBarry Smith   PetscFunctionBegin;
133045b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
133145b6f7e9SBarry Smith   PetscValidPointer(array,2);
133245b6f7e9SBarry Smith   *array = ltog->indices;
133345b6f7e9SBarry Smith   PetscFunctionReturn(0);
133445b6f7e9SBarry Smith }
133545b6f7e9SBarry Smith 
133645b6f7e9SBarry Smith #undef __FUNCT__
133745b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
133845b6f7e9SBarry Smith /*@C
133945b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
134045b6f7e9SBarry Smith 
134145b6f7e9SBarry Smith    Not Collective
134245b6f7e9SBarry Smith 
134345b6f7e9SBarry Smith    Input Arguments:
134445b6f7e9SBarry Smith + ltog - local to global mapping
134545b6f7e9SBarry Smith - array - array of indices
134645b6f7e9SBarry Smith 
134745b6f7e9SBarry Smith    Level: advanced
134845b6f7e9SBarry Smith 
134945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
135045b6f7e9SBarry Smith @*/
135145b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
135245b6f7e9SBarry Smith {
135345b6f7e9SBarry Smith   PetscFunctionBegin;
135445b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
135545b6f7e9SBarry Smith   PetscValidPointer(array,2);
135686994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
13570298fd71SBarry Smith   *array = NULL;
135886994e45SJed Brown   PetscFunctionReturn(0);
135986994e45SJed Brown }
1360f7efa3c7SJed Brown 
1361f7efa3c7SJed Brown #undef __FUNCT__
1362f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1363f7efa3c7SJed Brown /*@C
1364f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1365f7efa3c7SJed Brown 
1366f7efa3c7SJed Brown    Not Collective
1367f7efa3c7SJed Brown 
1368f7efa3c7SJed Brown    Input Arguments:
1369f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1370f7efa3c7SJed Brown . n - number of mappings to concatenate
1371f7efa3c7SJed Brown - ltogs - local to global mappings
1372f7efa3c7SJed Brown 
1373f7efa3c7SJed Brown    Output Arguments:
1374f7efa3c7SJed Brown . ltogcat - new mapping
1375f7efa3c7SJed Brown 
13769d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
13779d90f715SBarry Smith 
13789d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
13799d90f715SBarry Smith 
1380f7efa3c7SJed Brown    Level: advanced
1381f7efa3c7SJed Brown 
1382f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1383f7efa3c7SJed Brown @*/
1384f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1385f7efa3c7SJed Brown {
1386f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1387f7efa3c7SJed Brown   PetscErrorCode ierr;
1388f7efa3c7SJed Brown 
1389f7efa3c7SJed Brown   PetscFunctionBegin;
1390f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1391f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1392f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1393f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1394f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1395f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1396f7efa3c7SJed Brown     cnt += m;
1397f7efa3c7SJed Brown   }
1398785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1399f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1400f7efa3c7SJed Brown     const PetscInt *subidx;
1401f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1402f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1403f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1404f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1405f7efa3c7SJed Brown     cnt += m;
1406f7efa3c7SJed Brown   }
1407f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1408f7efa3c7SJed Brown   PetscFunctionReturn(0);
1409f7efa3c7SJed Brown }
141004a59952SBarry Smith 
141104a59952SBarry Smith 
1412