xref: /petsc/src/vec/is/utils/isltog.c (revision 73107ff1babc248481eafc1deee82c9703b7a0a0)
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;
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);
1416006e8d2SBarry 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);
1456006e8d2SBarry Smith   } else {
1466006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
147f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
14828bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
149f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1506006e8d2SBarry 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;
226cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
22745b6f7e9SBarry Smith   *bs = mapping->bs;
22845b6f7e9SBarry Smith   PetscFunctionReturn(0);
22945b6f7e9SBarry Smith }
23045b6f7e9SBarry Smith 
23145b6f7e9SBarry Smith #undef __FUNCT__
2324a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
233ba5bb76aSSatish Balay /*@
23490f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
23590f02eecSBarry Smith     ordering and a global parallel ordering.
2362362add9SBarry Smith 
23789d82c54SBarry Smith     Not Collective, but communicator may have more than one process
238b9cd556bSLois Curfman McInnes 
2392362add9SBarry Smith     Input Parameters:
24089d82c54SBarry Smith +   comm - MPI communicator
241f0413b6fSBarry Smith .   bs - the block size
24228bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
24328bc9809SBarry 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
244d5ad8652SBarry Smith -   mode - see PetscCopyMode
2452362add9SBarry Smith 
246a997ad1aSLois Curfman McInnes     Output Parameter:
24790f02eecSBarry Smith .   mapping - new mapping data structure
2482362add9SBarry Smith 
249f0413b6fSBarry 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
250a997ad1aSLois Curfman McInnes     Level: advanced
251a997ad1aSLois Curfman McInnes 
252273d9f13SBarry Smith     Concepts: mapping^local to global
2532362add9SBarry Smith 
254d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2552362add9SBarry Smith @*/
256f0413b6fSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2572362add9SBarry Smith {
2586849ba73SBarry Smith   PetscErrorCode ierr;
25932dcc486SBarry Smith   PetscInt       *in;
260b46b645bSBarry Smith 
261b46b645bSBarry Smith   PetscFunctionBegin;
26273911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2634482741eSBarry Smith   PetscValidPointer(mapping,4);
264b46b645bSBarry Smith 
2650298fd71SBarry Smith   *mapping = NULL;
266607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2672362add9SBarry Smith 
268*73107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
26952e6d16bSBarry Smith                            cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
270d4bb536fSBarry Smith   (*mapping)->n  = n;
271f0413b6fSBarry Smith   (*mapping)->bs = bs;
272d4bb536fSBarry Smith   /*
273d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
274d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
275d4bb536fSBarry Smith   */
276d4bb536fSBarry Smith   (*mapping)->globals = 0;
277d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
278785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
279d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
280d5ad8652SBarry Smith     (*mapping)->indices = in;
2816389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2826389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
2836389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
2846389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2856389a1a1SBarry Smith   }
286f6e5521dSKarl Rupp   else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
287d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
2883a40ed3dSBarry Smith   PetscFunctionReturn(0);
2892362add9SBarry Smith }
2902362add9SBarry Smith 
2914a2ae208SSatish Balay #undef __FUNCT__
2924a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
29390f02eecSBarry Smith /*@
29490f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
29590f02eecSBarry Smith    ordering and a global parallel ordering.
29690f02eecSBarry Smith 
2970f5bd95cSBarry Smith    Note Collective
298b9cd556bSLois Curfman McInnes 
29990f02eecSBarry Smith    Input Parameters:
30090f02eecSBarry Smith .  mapping - mapping data structure
30190f02eecSBarry Smith 
302a997ad1aSLois Curfman McInnes    Level: advanced
303a997ad1aSLois Curfman McInnes 
3043acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
30590f02eecSBarry Smith @*/
3066bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
30790f02eecSBarry Smith {
308dfbe8321SBarry Smith   PetscErrorCode ierr;
3095fd66863SKarl Rupp 
3103a40ed3dSBarry Smith   PetscFunctionBegin;
3116bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3126bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
313997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3146bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3156bf464f9SBarry Smith   ierr     = PetscFree((*mapping)->globals);CHKERRQ(ierr);
316d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
317992144d0SBarry Smith   *mapping = 0;
3183a40ed3dSBarry Smith   PetscFunctionReturn(0);
31990f02eecSBarry Smith }
32090f02eecSBarry Smith 
3214a2ae208SSatish Balay #undef __FUNCT__
3224a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
32390f02eecSBarry Smith /*@
3243acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3253acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3263acfe500SLois Curfman McInnes     context.
32790f02eecSBarry Smith 
328b9cd556bSLois Curfman McInnes     Not collective
329b9cd556bSLois Curfman McInnes 
33090f02eecSBarry Smith     Input Parameters:
331b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
332b9cd556bSLois Curfman McInnes -   is - index set in local numbering
33390f02eecSBarry Smith 
33490f02eecSBarry Smith     Output Parameters:
33590f02eecSBarry Smith .   newis - index set in global numbering
33690f02eecSBarry Smith 
337a997ad1aSLois Curfman McInnes     Level: advanced
338a997ad1aSLois Curfman McInnes 
339273d9f13SBarry Smith     Concepts: mapping^local to global
3403acfe500SLois Curfman McInnes 
34190f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
342d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
34390f02eecSBarry Smith @*/
3447087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
34590f02eecSBarry Smith {
3466849ba73SBarry Smith   PetscErrorCode ierr;
347e24637baSBarry Smith   PetscInt       n,*idxout;
3485d0c19d7SBarry Smith   const PetscInt *idxin;
3493a40ed3dSBarry Smith 
3503a40ed3dSBarry Smith   PetscFunctionBegin;
3510700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3520700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3534482741eSBarry Smith   PetscValidPointer(newis,3);
35490f02eecSBarry Smith 
3553b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
35690f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
357785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
358e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
3593b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
360543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
3613a40ed3dSBarry Smith   PetscFunctionReturn(0);
36290f02eecSBarry Smith }
36390f02eecSBarry Smith 
364afcb2eb5SJed Brown #undef __FUNCT__
365afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
366b89cb25eSSatish Balay /*@
3673acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3683acfe500SLois Curfman McInnes    and converts them to the global numbering.
36990f02eecSBarry Smith 
370b9cd556bSLois Curfman McInnes    Not collective
371b9cd556bSLois Curfman McInnes 
372bb25748dSBarry Smith    Input Parameters:
373b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
374bb25748dSBarry Smith .  N - number of integers
375b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
376bb25748dSBarry Smith 
377bb25748dSBarry Smith    Output Parameter:
378bb25748dSBarry Smith .  out - indices in global numbering
379bb25748dSBarry Smith 
380b9cd556bSLois Curfman McInnes    Notes:
381b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
382d4bb536fSBarry Smith 
383a997ad1aSLois Curfman McInnes    Level: advanced
384a997ad1aSLois Curfman McInnes 
38545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3860752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
387d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
388bb25748dSBarry Smith 
389273d9f13SBarry Smith     Concepts: mapping^local to global
390afcb2eb5SJed Brown @*/
391afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
392afcb2eb5SJed Brown {
393cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
39445b6f7e9SBarry Smith 
39545b6f7e9SBarry Smith   PetscFunctionBegin;
396cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
397cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
398cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
39945b6f7e9SBarry Smith   if (bs == 1) {
400cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
40145b6f7e9SBarry Smith     for (i=0; i<N; i++) {
40245b6f7e9SBarry Smith       if (in[i] < 0) {
40345b6f7e9SBarry Smith         out[i] = in[i];
40445b6f7e9SBarry Smith         continue;
40545b6f7e9SBarry Smith       }
406e24637baSBarry 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);
40745b6f7e9SBarry Smith       out[i] = idx[in[i]];
40845b6f7e9SBarry Smith     }
40945b6f7e9SBarry Smith   } else {
410cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
41145b6f7e9SBarry Smith     for (i=0; i<N; i++) {
41245b6f7e9SBarry Smith       if (in[i] < 0) {
41345b6f7e9SBarry Smith         out[i] = in[i];
41445b6f7e9SBarry Smith         continue;
41545b6f7e9SBarry Smith       }
416e24637baSBarry 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);
41745b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
41845b6f7e9SBarry Smith     }
41945b6f7e9SBarry Smith   }
42045b6f7e9SBarry Smith   PetscFunctionReturn(0);
42145b6f7e9SBarry Smith }
42245b6f7e9SBarry Smith 
42345b6f7e9SBarry Smith #undef __FUNCT__
42445b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
42545b6f7e9SBarry Smith /*@
4266006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
42745b6f7e9SBarry Smith 
42845b6f7e9SBarry Smith    Not collective
42945b6f7e9SBarry Smith 
43045b6f7e9SBarry Smith    Input Parameters:
43145b6f7e9SBarry Smith +  mapping - the local to global mapping context
43245b6f7e9SBarry Smith .  N - number of integers
4336006e8d2SBarry Smith -  in - input indices in local block numbering
43445b6f7e9SBarry Smith 
43545b6f7e9SBarry Smith    Output Parameter:
4366006e8d2SBarry Smith .  out - indices in global block numbering
43745b6f7e9SBarry Smith 
43845b6f7e9SBarry Smith    Notes:
43945b6f7e9SBarry Smith    The in and out array parameters may be identical.
44045b6f7e9SBarry Smith 
4416006e8d2SBarry Smith    Example:
4426006e8d2SBarry 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
4436006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
4446006e8d2SBarry Smith 
44545b6f7e9SBarry Smith    Level: advanced
44645b6f7e9SBarry Smith 
44745b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
44845b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
44945b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
45045b6f7e9SBarry Smith 
45145b6f7e9SBarry Smith     Concepts: mapping^local to global
45245b6f7e9SBarry Smith @*/
45345b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
45445b6f7e9SBarry Smith {
455cbc1caf0SMatthew G. Knepley 
456cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
457cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
458cbc1caf0SMatthew G. Knepley   {
459afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
460afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
461d4bb536fSBarry Smith 
462afcb2eb5SJed Brown     for (i=0; i<N; i++) {
463afcb2eb5SJed Brown       if (in[i] < 0) {
464afcb2eb5SJed Brown         out[i] = in[i];
465afcb2eb5SJed Brown         continue;
466afcb2eb5SJed Brown       }
467e24637baSBarry 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);
468afcb2eb5SJed Brown       out[i] = idx[in[i]];
469afcb2eb5SJed Brown     }
470cbc1caf0SMatthew G. Knepley   }
471afcb2eb5SJed Brown   PetscFunctionReturn(0);
472afcb2eb5SJed Brown }
473d4bb536fSBarry Smith 
474d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
475d4bb536fSBarry Smith 
4764a2ae208SSatish Balay #undef __FUNCT__
4774a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
478d4bb536fSBarry Smith /*
479d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
480d4bb536fSBarry Smith */
4816849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
482d4bb536fSBarry Smith {
4836849ba73SBarry Smith   PetscErrorCode ierr;
48432dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
485d4bb536fSBarry Smith 
4863a40ed3dSBarry Smith   PetscFunctionBegin;
487d4bb536fSBarry Smith   end   = 0;
488ec268f7cSJed Brown   start = PETSC_MAX_INT;
489d4bb536fSBarry Smith 
490d4bb536fSBarry Smith   for (i=0; i<n; i++) {
491d4bb536fSBarry Smith     if (idx[i] < 0) continue;
492d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
493d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
494d4bb536fSBarry Smith   }
495d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
496d4bb536fSBarry Smith   mapping->globalstart = start;
497d4bb536fSBarry Smith   mapping->globalend   = end;
498d4bb536fSBarry Smith 
499854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
500b0a32e0cSBarry Smith   mapping->globals = globals;
501f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
502d4bb536fSBarry Smith   for (i=0; i<n; i++) {
503d4bb536fSBarry Smith     if (idx[i] < 0) continue;
504d4bb536fSBarry Smith     globals[idx[i] - start] = i;
505d4bb536fSBarry Smith   }
506d4bb536fSBarry Smith 
5073bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5083a40ed3dSBarry Smith   PetscFunctionReturn(0);
509d4bb536fSBarry Smith }
510d4bb536fSBarry Smith 
5114a2ae208SSatish Balay #undef __FUNCT__
5124a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
513d4bb536fSBarry Smith /*@
514a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
515a997ad1aSLois Curfman McInnes     specified with a global numbering.
516d4bb536fSBarry Smith 
517b9cd556bSLois Curfman McInnes     Not collective
518b9cd556bSLois Curfman McInnes 
519d4bb536fSBarry Smith     Input Parameters:
520b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
521d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
522d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
523d4bb536fSBarry Smith .   n - number of global indices to map
524b9cd556bSLois Curfman McInnes -   idx - global indices to map
525d4bb536fSBarry Smith 
526d4bb536fSBarry Smith     Output Parameters:
527b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
528b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
529e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5300298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
531e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
532e182c471SBarry Smith              a second time to set the values.
533d4bb536fSBarry Smith 
534b9cd556bSLois Curfman McInnes     Notes:
5350298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
536d4bb536fSBarry Smith 
5370f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5380f5bd95cSBarry Smith     array to compute these.
5390f5bd95cSBarry Smith 
540a997ad1aSLois Curfman McInnes     Level: advanced
541a997ad1aSLois Curfman McInnes 
54232fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
54332fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
54432fd6b96SBarry Smith 
545273d9f13SBarry Smith     Concepts: mapping^global to local
546d4bb536fSBarry Smith 
5479d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
548d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
549d4bb536fSBarry Smith @*/
5507087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
55132dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
552d4bb536fSBarry Smith {
5539d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
5549d90f715SBarry Smith   PetscErrorCode ierr;
5559d90f715SBarry Smith 
5569d90f715SBarry Smith   PetscFunctionBegin;
5579d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
5589d90f715SBarry Smith   if (!mapping->globals) {
5599d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
5609d90f715SBarry Smith   }
5619d90f715SBarry Smith   globals = mapping->globals;
5629d90f715SBarry Smith   start   = mapping->globalstart;
5639d90f715SBarry Smith   end     = mapping->globalend;
5649d90f715SBarry Smith   bs      = mapping->bs;
5659d90f715SBarry Smith 
5669d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
5679d90f715SBarry Smith     if (idxout) {
5689d90f715SBarry Smith       for (i=0; i<n; i++) {
5699d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
5709d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
571663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
5729d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5739d90f715SBarry Smith       }
5749d90f715SBarry Smith     }
5759d90f715SBarry Smith     if (nout) *nout = n;
5769d90f715SBarry Smith   } else {
5779d90f715SBarry Smith     if (idxout) {
5789d90f715SBarry Smith       for (i=0; i<n; i++) {
5799d90f715SBarry Smith         if (idx[i] < 0) continue;
5809d90f715SBarry Smith         if (idx[i] < bs*start) continue;
581663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
5829d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5839d90f715SBarry Smith         if (tmp < 0) continue;
5849d90f715SBarry Smith         idxout[nf++] = tmp;
5859d90f715SBarry Smith       }
5869d90f715SBarry Smith     } else {
5879d90f715SBarry Smith       for (i=0; i<n; i++) {
5889d90f715SBarry Smith         if (idx[i] < 0) continue;
5899d90f715SBarry Smith         if (idx[i] < bs*start) continue;
590663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
5919d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5929d90f715SBarry Smith         if (tmp < 0) continue;
5939d90f715SBarry Smith         nf++;
5949d90f715SBarry Smith       }
5959d90f715SBarry Smith     }
5969d90f715SBarry Smith     if (nout) *nout = nf;
5979d90f715SBarry Smith   }
5989d90f715SBarry Smith   PetscFunctionReturn(0);
5999d90f715SBarry Smith }
6009d90f715SBarry Smith 
6019d90f715SBarry Smith #undef __FUNCT__
602d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
603d4fe737eSStefano Zampini /*@
604d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
605d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
606d4fe737eSStefano Zampini     context.
607d4fe737eSStefano Zampini 
608d4fe737eSStefano Zampini     Not collective
609d4fe737eSStefano Zampini 
610d4fe737eSStefano Zampini     Input Parameters:
611d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
612d4fe737eSStefano Zampini -   is - index set in global numbering
613d4fe737eSStefano Zampini 
614d4fe737eSStefano Zampini     Output Parameters:
615d4fe737eSStefano Zampini .   newis - index set in local numbering
616d4fe737eSStefano Zampini 
617d4fe737eSStefano Zampini     Level: advanced
618d4fe737eSStefano Zampini 
619d4fe737eSStefano Zampini     Concepts: mapping^local to global
620d4fe737eSStefano Zampini 
621d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
622d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
623d4fe737eSStefano Zampini @*/
624d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
625d4fe737eSStefano Zampini {
626d4fe737eSStefano Zampini   PetscErrorCode ierr;
627d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
628d4fe737eSStefano Zampini   const PetscInt *idxin;
629d4fe737eSStefano Zampini 
630d4fe737eSStefano Zampini   PetscFunctionBegin;
631d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
632d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
633d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
634d4fe737eSStefano Zampini 
635d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
636d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
637d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
638d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
639d4fe737eSStefano Zampini   } else {
640d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
641d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
642d4fe737eSStefano Zampini   }
643d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
644d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
645d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
646d4fe737eSStefano Zampini   PetscFunctionReturn(0);
647d4fe737eSStefano Zampini }
648d4fe737eSStefano Zampini 
649d4fe737eSStefano Zampini #undef __FUNCT__
6509d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
6519d90f715SBarry Smith /*@
6529d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
6539d90f715SBarry Smith     specified with a block global numbering.
6549d90f715SBarry Smith 
6559d90f715SBarry Smith     Not collective
6569d90f715SBarry Smith 
6579d90f715SBarry Smith     Input Parameters:
6589d90f715SBarry Smith +   mapping - mapping between local and global numbering
6599d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
6609d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
6619d90f715SBarry Smith .   n - number of global indices to map
6629d90f715SBarry Smith -   idx - global indices to map
6639d90f715SBarry Smith 
6649d90f715SBarry Smith     Output Parameters:
6659d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
6669d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
6679d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
6689d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
6699d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
6709d90f715SBarry Smith              a second time to set the values.
6719d90f715SBarry Smith 
6729d90f715SBarry Smith     Notes:
6739d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
6749d90f715SBarry Smith 
6759d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6769d90f715SBarry Smith     array to compute these.
6779d90f715SBarry Smith 
6789d90f715SBarry Smith     Level: advanced
6799d90f715SBarry Smith 
6809d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
6819d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
6829d90f715SBarry Smith 
6839d90f715SBarry Smith     Concepts: mapping^global to local
6849d90f715SBarry Smith 
6859d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
6869d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
6879d90f715SBarry Smith @*/
6889d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
6899d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
6909d90f715SBarry Smith {
69132dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
6926849ba73SBarry Smith   PetscErrorCode ierr;
693d4bb536fSBarry Smith 
6943a40ed3dSBarry Smith   PetscFunctionBegin;
6950700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
696d4bb536fSBarry Smith   if (!mapping->globals) {
697d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
698d4bb536fSBarry Smith   }
699d4bb536fSBarry Smith   globals = mapping->globals;
700d4bb536fSBarry Smith   start   = mapping->globalstart;
701d4bb536fSBarry Smith   end     = mapping->globalend;
702d4bb536fSBarry Smith 
703d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
704d4bb536fSBarry Smith     if (idxout) {
705d4bb536fSBarry Smith       for (i=0; i<n; i++) {
706d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
707d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
708d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
709d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
710d4bb536fSBarry Smith       }
711d4bb536fSBarry Smith     }
712d4bb536fSBarry Smith     if (nout) *nout = n;
713d4bb536fSBarry Smith   } else {
714d4bb536fSBarry Smith     if (idxout) {
715d4bb536fSBarry Smith       for (i=0; i<n; i++) {
716d4bb536fSBarry Smith         if (idx[i] < 0) continue;
717d4bb536fSBarry Smith         if (idx[i] < start) continue;
718d4bb536fSBarry Smith         if (idx[i] > end) continue;
719d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
720d4bb536fSBarry Smith         if (tmp < 0) continue;
721d4bb536fSBarry Smith         idxout[nf++] = tmp;
722d4bb536fSBarry Smith       }
723d4bb536fSBarry Smith     } else {
724d4bb536fSBarry Smith       for (i=0; i<n; i++) {
725d4bb536fSBarry Smith         if (idx[i] < 0) continue;
726d4bb536fSBarry Smith         if (idx[i] < start) continue;
727d4bb536fSBarry Smith         if (idx[i] > end) continue;
728d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
729d4bb536fSBarry Smith         if (tmp < 0) continue;
730d4bb536fSBarry Smith         nf++;
731d4bb536fSBarry Smith       }
732d4bb536fSBarry Smith     }
733d4bb536fSBarry Smith     if (nout) *nout = nf;
734d4bb536fSBarry Smith   }
7353a40ed3dSBarry Smith   PetscFunctionReturn(0);
736d4bb536fSBarry Smith }
73790f02eecSBarry Smith 
7384a2ae208SSatish Balay #undef __FUNCT__
7396a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
74089d82c54SBarry Smith /*@C
7416a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
74289d82c54SBarry Smith      each index shared by more than one processor
74389d82c54SBarry Smith 
74489d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
74589d82c54SBarry Smith 
74689d82c54SBarry Smith     Input Parameters:
74789d82c54SBarry Smith .   mapping - the mapping from local to global indexing
74889d82c54SBarry Smith 
74989d82c54SBarry Smith     Output Parameter:
75089d82c54SBarry Smith +   nproc - number of processors that are connected to this one
75189d82c54SBarry Smith .   proc - neighboring processors
75207b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
7533463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
75489d82c54SBarry Smith 
75589d82c54SBarry Smith     Level: advanced
75689d82c54SBarry Smith 
757273d9f13SBarry Smith     Concepts: mapping^local to global
75889d82c54SBarry Smith 
7592cfcea29SBarry Smith     Fortran Usage:
7602cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
7612cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
7622cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
7632cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
7642cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
7652cfcea29SBarry Smith 
7662cfcea29SBarry Smith 
76707b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
76807b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
76989d82c54SBarry Smith @*/
7706a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
77189d82c54SBarry Smith {
7726849ba73SBarry Smith   PetscErrorCode ierr;
77397f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
77432dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
77532dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
77697f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
77732dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
77832dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
77989d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
78030dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
781ce94432eSBarry Smith   MPI_Comm       comm;
782ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
78389d82c54SBarry Smith 
78489d82c54SBarry Smith   PetscFunctionBegin;
7850700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
786ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
78724cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
78824cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
78924cf384cSBarry Smith   if (size == 1) {
79024cf384cSBarry Smith     *nproc         = 0;
7910298fd71SBarry Smith     *procs         = NULL;
79232dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
7931e2105dcSBarry Smith     (*numprocs)[0] = 0;
79432dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
7950298fd71SBarry Smith     (*indices)[0]  = NULL;
79624cf384cSBarry Smith     PetscFunctionReturn(0);
79724cf384cSBarry Smith   }
79824cf384cSBarry Smith 
7990298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
80007b52d57SBarry Smith 
8013677ff5aSBarry Smith   /*
8026a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
8033677ff5aSBarry Smith 
8043677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
8053677ff5aSBarry Smith            numbering, just for this routine.
8063677ff5aSBarry Smith 
8073677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
8083677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
8093677ff5aSBarry Smith 
8103677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
8113677ff5aSBarry Smith 
8123677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
8133677ff5aSBarry Smith            local subdomain
8143677ff5aSBarry Smith   */
81524cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
81624cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
81724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
81889d82c54SBarry Smith 
81989d82c54SBarry Smith   for (i=0; i<n; i++) {
82089d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
82189d82c54SBarry Smith   }
82232dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
82378058e43SBarry Smith   Ng++;
82489d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
82589d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
826bc8ff85bSBarry Smith   scale  = Ng/size + 1;
827a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
828caba0dd0SBarry Smith   rstart = scale*rank;
82989d82c54SBarry Smith 
83089d82c54SBarry Smith   /* determine ownership ranges of global indices */
831785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
83232dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
83389d82c54SBarry Smith 
83489d82c54SBarry Smith   /* determine owners of each local node  */
835785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
83689d82c54SBarry Smith   for (i=0; i<n; i++) {
8373677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
83827c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
8393677ff5aSBarry Smith     owner[i]         = proc;
84027c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
84189d82c54SBarry Smith   }
84227c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
8437904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
84489d82c54SBarry Smith 
84589d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
84627c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
8477904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
84889d82c54SBarry Smith 
84989d82c54SBarry Smith   /* post receives for owned rows */
850785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
851854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
85289d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
85332dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
85489d82c54SBarry Smith   }
85589d82c54SBarry Smith 
85689d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
857854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
858854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
85989d82c54SBarry Smith   starts[0] = 0;
860f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
86189d82c54SBarry Smith   for (i=0; i<n; i++) {
86289d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
86330dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
86489d82c54SBarry Smith   }
86589d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
86689d82c54SBarry Smith   starts[0] = 0;
867f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
86889d82c54SBarry Smith 
86989d82c54SBarry Smith   /* send the messages */
870854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
871854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
87289d82c54SBarry Smith   cnt = 0;
87389d82c54SBarry Smith   for (i=0; i<size; i++) {
87427c402fcSBarry Smith     if (nprocs[2*i]) {
87532dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
87630dcb7c9SBarry Smith       dest[cnt] = i;
87789d82c54SBarry Smith       cnt++;
87889d82c54SBarry Smith     }
87989d82c54SBarry Smith   }
88089d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
88189d82c54SBarry Smith 
88289d82c54SBarry Smith   /* wait on receives */
883854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
884854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
88589d82c54SBarry Smith   cnt  = nrecvs;
886854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
88732dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
88889d82c54SBarry Smith   while (cnt) {
88989d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
89089d82c54SBarry Smith     /* unpack receives into our local space */
89132dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
89289d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
89330dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
894caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
89530dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
89689d82c54SBarry Smith     cnt--;
89789d82c54SBarry Smith   }
89889d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
89989d82c54SBarry Smith 
90030dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
901bc8ff85bSBarry Smith   nowned  = 0;
902bc8ff85bSBarry Smith   nownedm = 0;
903bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
904bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
905bc8ff85bSBarry Smith   }
906bc8ff85bSBarry Smith 
907bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
908854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
909854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
910bc8ff85bSBarry Smith   starts[0] = 0;
911bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
912bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
913bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
914bc8ff85bSBarry Smith   }
915bc8ff85bSBarry Smith 
91630dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
917bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
918bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
91930dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
920f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
921bc8ff85bSBarry Smith     }
922bc8ff85bSBarry Smith   }
923bc8ff85bSBarry Smith 
92407b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
92530dcb7c9SBarry Smith     starts[0] = 0;
92630dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
92730dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
92830dcb7c9SBarry Smith       else starts[i] = starts[i-1];
92930dcb7c9SBarry Smith     }
93030dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
93130dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
9327904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
93330dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
9347904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
93530dcb7c9SBarry Smith         }
93630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
93730dcb7c9SBarry Smith       }
93830dcb7c9SBarry Smith     }
9390ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
94007b52d57SBarry Smith   } /* -----------------------------------  */
94130dcb7c9SBarry Smith 
9423677ff5aSBarry Smith   /* wait on original sends */
9433a96401aSBarry Smith   if (nsends) {
944785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
9453a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
9463a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
9473a96401aSBarry Smith   }
94889d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
9493a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
9503677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
9513677ff5aSBarry Smith 
9523677ff5aSBarry Smith   /* pack messages to send back to local owners */
95330dcb7c9SBarry Smith   starts[0] = 0;
95430dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
95530dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
95630dcb7c9SBarry Smith     else starts[i] = starts[i-1];
95730dcb7c9SBarry Smith   }
95830dcb7c9SBarry Smith   nsends2 = nrecvs;
959854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
96030dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
96130dcb7c9SBarry Smith     nprocs[i] = 1;
96230dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
96330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
964f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
96530dcb7c9SBarry Smith     }
96630dcb7c9SBarry Smith   }
967f6e5521dSKarl Rupp   nt = 0;
968f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
969f6e5521dSKarl Rupp 
970854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
971854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
972f6e5521dSKarl Rupp 
973f6e5521dSKarl Rupp   starts2[0] = 0;
974f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
97530dcb7c9SBarry Smith   /*
97630dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
97730dcb7c9SBarry Smith        (0) the number of nodes being sent back
97830dcb7c9SBarry Smith        (1) the local node number,
97930dcb7c9SBarry Smith        (2) the number of processors sharing it,
98030dcb7c9SBarry Smith        (3) the processors sharing it
98130dcb7c9SBarry Smith   */
98230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
98330dcb7c9SBarry Smith     cnt = 1;
98430dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
98530dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
98630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
98730dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
98830dcb7c9SBarry Smith         sends2[starts2[i]]++;
98930dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
99030dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
99132dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
99230dcb7c9SBarry Smith         cnt += nownedsenders[node];
99330dcb7c9SBarry Smith       }
99430dcb7c9SBarry Smith     }
99530dcb7c9SBarry Smith   }
99630dcb7c9SBarry Smith 
99730dcb7c9SBarry Smith   /* receive the message lengths */
99830dcb7c9SBarry Smith   nrecvs2 = nsends;
999854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1000854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1001854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
100230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1003d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
100430dcb7c9SBarry Smith   }
1005d44834fbSBarry Smith 
10068a8e0b3aSBarry Smith   /* send the message lengths */
10078a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
10088a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
10098a8e0b3aSBarry Smith   }
10108a8e0b3aSBarry Smith 
1011d44834fbSBarry Smith   /* wait on receives of lens */
10120c468ba9SBarry Smith   if (nrecvs2) {
1013785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1014d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1015d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10160c468ba9SBarry Smith   }
1017a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1018d44834fbSBarry Smith 
101930dcb7c9SBarry Smith   starts3[0] = 0;
1020d44834fbSBarry Smith   nt         = 0;
102130dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
102230dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1023d44834fbSBarry Smith     nt          += lens2[i];
102430dcb7c9SBarry Smith   }
102576466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1026d44834fbSBarry Smith 
1027854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1028854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
102952b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
103032dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
103130dcb7c9SBarry Smith   }
103230dcb7c9SBarry Smith 
103330dcb7c9SBarry Smith   /* send the messages */
1034854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
103530dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
103632dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
103730dcb7c9SBarry Smith   }
103830dcb7c9SBarry Smith 
103930dcb7c9SBarry Smith   /* wait on receives */
10400c468ba9SBarry Smith   if (nrecvs2) {
1041785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
104230dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
104330dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10440c468ba9SBarry Smith   }
104530dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
104630dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
104730dcb7c9SBarry Smith 
104807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
104930dcb7c9SBarry Smith     cnt = 0;
105030dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
105130dcb7c9SBarry Smith       nt = recvs2[cnt++];
105230dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
10537904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
105430dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
10557904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
105630dcb7c9SBarry Smith         }
105730dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
105830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
105930dcb7c9SBarry Smith       }
106030dcb7c9SBarry Smith     }
10610ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
106207b52d57SBarry Smith   } /* -----------------------------------  */
106330dcb7c9SBarry Smith 
106430dcb7c9SBarry Smith   /* count number subdomains for each local node */
1065785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
106632dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
106730dcb7c9SBarry Smith   cnt  = 0;
106830dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
106930dcb7c9SBarry Smith     nt = recvs2[cnt++];
107030dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1071f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
107230dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
107330dcb7c9SBarry Smith     }
107430dcb7c9SBarry Smith   }
107530dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
107630dcb7c9SBarry Smith   *nproc    = nt;
1077854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1078854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1079854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
10800298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1081785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
108230dcb7c9SBarry Smith   cnt       = 0;
108330dcb7c9SBarry Smith   for (i=0; i<size; i++) {
108430dcb7c9SBarry Smith     if (nprocs[i] > 0) {
108530dcb7c9SBarry Smith       bprocs[i]        = cnt;
108630dcb7c9SBarry Smith       (*procs)[cnt]    = i;
108730dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1088785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
108930dcb7c9SBarry Smith       cnt++;
109030dcb7c9SBarry Smith     }
109130dcb7c9SBarry Smith   }
109230dcb7c9SBarry Smith 
109330dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
109432dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
109530dcb7c9SBarry Smith   cnt  = 0;
109630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
109730dcb7c9SBarry Smith     nt = recvs2[cnt++];
109830dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1099f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
110030dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
110130dcb7c9SBarry Smith     }
110230dcb7c9SBarry Smith   }
110330dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
110407b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
110530dcb7c9SBarry Smith 
110607b52d57SBarry Smith   /* sort the node indexing by their global numbers */
110707b52d57SBarry Smith   nt = *nproc;
110807b52d57SBarry Smith   for (i=0; i<nt; i++) {
1109854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1110f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
111107b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
111207b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
111307b52d57SBarry Smith   }
111407b52d57SBarry Smith 
111507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
111630dcb7c9SBarry Smith     nt = *nproc;
111730dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
11187904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
111930dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
11207904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
112130dcb7c9SBarry Smith       }
112230dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
112330dcb7c9SBarry Smith     }
11240ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
112507b52d57SBarry Smith   } /* -----------------------------------  */
112630dcb7c9SBarry Smith 
112730dcb7c9SBarry Smith   /* wait on sends */
112830dcb7c9SBarry Smith   if (nsends2) {
1129785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
113030dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
113130dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
113230dcb7c9SBarry Smith   }
113330dcb7c9SBarry Smith 
113430dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
113530dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
113630dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
11373677ff5aSBarry Smith 
1138bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1139bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1140bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
114130dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
114230dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
114389d82c54SBarry Smith 
114489d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
114597f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
114689d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
11473a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
114830dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
114924cf384cSBarry Smith 
115024cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
115124cf384cSBarry Smith   first_procs    = (*procs)[0];
115224cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
115324cf384cSBarry Smith   first_indices  = (*indices)[0];
115424cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
115524cf384cSBarry Smith     if ((*procs)[i] == rank) {
115624cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
115724cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
115824cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
115924cf384cSBarry Smith       (*procs)[i]    = first_procs;
116024cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
116124cf384cSBarry Smith       (*indices)[i]  = first_indices;
116224cf384cSBarry Smith       break;
116324cf384cSBarry Smith     }
116424cf384cSBarry Smith   }
116589d82c54SBarry Smith   PetscFunctionReturn(0);
116689d82c54SBarry Smith }
116789d82c54SBarry Smith 
11684a2ae208SSatish Balay #undef __FUNCT__
11696a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
11706a818285SBarry Smith /*@C
11716a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
11726a818285SBarry Smith 
11736a818285SBarry Smith     Collective on ISLocalToGlobalMapping
11746a818285SBarry Smith 
11756a818285SBarry Smith     Input Parameters:
11766a818285SBarry Smith .   mapping - the mapping from local to global indexing
11776a818285SBarry Smith 
11786a818285SBarry Smith     Output Parameter:
11796a818285SBarry Smith +   nproc - number of processors that are connected to this one
11806a818285SBarry Smith .   proc - neighboring processors
11816a818285SBarry Smith .   numproc - number of indices for each processor
11826a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
11836a818285SBarry Smith 
11846a818285SBarry Smith     Level: advanced
11856a818285SBarry Smith 
11866a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
11876a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
11886a818285SBarry Smith @*/
11896a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
11906a818285SBarry Smith {
11916a818285SBarry Smith   PetscErrorCode ierr;
11926a818285SBarry Smith   PetscInt       i;
11936a818285SBarry Smith 
11946a818285SBarry Smith   PetscFunctionBegin;
1195cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
11966a818285SBarry Smith   ierr = PetscFree(*procs);CHKERRQ(ierr);
11976a818285SBarry Smith   ierr = PetscFree(*numprocs);CHKERRQ(ierr);
11986a818285SBarry Smith   if (*indices) {
11996a818285SBarry Smith     ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
12006a818285SBarry Smith     for (i=1; i<*nproc; i++) {
12016a818285SBarry Smith       ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
12026a818285SBarry Smith     }
12036a818285SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
12046a818285SBarry Smith   }
12056a818285SBarry Smith   PetscFunctionReturn(0);
12066a818285SBarry Smith }
12076a818285SBarry Smith 
12086a818285SBarry Smith #undef __FUNCT__
12096a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
12106a818285SBarry Smith /*@C
12116a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
12126a818285SBarry Smith      each index shared by more than one processor
12136a818285SBarry Smith 
12146a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12156a818285SBarry Smith 
12166a818285SBarry Smith     Input Parameters:
12176a818285SBarry Smith .   mapping - the mapping from local to global indexing
12186a818285SBarry Smith 
12196a818285SBarry Smith     Output Parameter:
12206a818285SBarry Smith +   nproc - number of processors that are connected to this one
12216a818285SBarry Smith .   proc - neighboring processors
12226a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
12236a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
12246a818285SBarry Smith 
12256a818285SBarry Smith     Level: advanced
12266a818285SBarry Smith 
12276a818285SBarry Smith     Concepts: mapping^local to global
12286a818285SBarry Smith 
12296a818285SBarry Smith     Fortran Usage:
12306a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
12316a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
12326a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
12336a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
12346a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
12356a818285SBarry Smith 
12366a818285SBarry Smith 
12376a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12386a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
12396a818285SBarry Smith @*/
12406a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12416a818285SBarry Smith {
12426a818285SBarry Smith   PetscErrorCode ierr;
12436a818285SBarry Smith   PetscInt       **bindices = NULL,bs = mapping->bs,i,j,k;
12446a818285SBarry Smith 
12456a818285SBarry Smith   PetscFunctionBegin;
12466a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
12476a818285SBarry Smith   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,numprocs,&bindices);CHKERRQ(ierr);
1248732f65e3SBarry Smith   ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
12496a818285SBarry Smith   for (i=0; i<*nproc; i++) {
12506a818285SBarry Smith     ierr = PetscMalloc1(bs*(*numprocs)[i],&(*indices)[i]);CHKERRQ(ierr);
12516a818285SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
12526a818285SBarry Smith       for (k=0; k<bs; k++) {
12536a818285SBarry Smith         (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
12546a818285SBarry Smith       }
12556a818285SBarry Smith     }
12566a818285SBarry Smith     (*numprocs)[i] *= bs;
12576a818285SBarry Smith   }
12586a818285SBarry Smith   if (bindices) {
12596a818285SBarry Smith     ierr = PetscFree(bindices[0]);CHKERRQ(ierr);
12606a818285SBarry Smith     for (i=1; i<*nproc; i++) {
12616a818285SBarry Smith       ierr = PetscFree(bindices[i]);CHKERRQ(ierr);
12626a818285SBarry Smith     }
12636a818285SBarry Smith     ierr = PetscFree(bindices);CHKERRQ(ierr);
12646a818285SBarry Smith   }
12656a818285SBarry Smith   PetscFunctionReturn(0);
12666a818285SBarry Smith }
12676a818285SBarry Smith 
12686a818285SBarry Smith #undef __FUNCT__
12694a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
127007b52d57SBarry Smith /*@C
127107b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
127289d82c54SBarry Smith 
127307b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
127407b52d57SBarry Smith 
127507b52d57SBarry Smith     Input Parameters:
127607b52d57SBarry Smith .   mapping - the mapping from local to global indexing
127707b52d57SBarry Smith 
127807b52d57SBarry Smith     Output Parameter:
127907b52d57SBarry Smith +   nproc - number of processors that are connected to this one
128007b52d57SBarry Smith .   proc - neighboring processors
128107b52d57SBarry Smith .   numproc - number of indices for each processor
128207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
128307b52d57SBarry Smith 
128407b52d57SBarry Smith     Level: advanced
128507b52d57SBarry Smith 
128607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
128707b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
128807b52d57SBarry Smith @*/
12897087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
129007b52d57SBarry Smith {
12916849ba73SBarry Smith   PetscErrorCode ierr;
129207b52d57SBarry Smith 
129307b52d57SBarry Smith   PetscFunctionBegin;
12946a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
129507b52d57SBarry Smith   PetscFunctionReturn(0);
129607b52d57SBarry Smith }
129786994e45SJed Brown 
129886994e45SJed Brown #undef __FUNCT__
129986994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
130086994e45SJed Brown /*@C
1301107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
130286994e45SJed Brown 
130386994e45SJed Brown    Not Collective
130486994e45SJed Brown 
130586994e45SJed Brown    Input Arguments:
130686994e45SJed Brown . ltog - local to global mapping
130786994e45SJed Brown 
130886994e45SJed Brown    Output Arguments:
1309565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
131086994e45SJed Brown 
131186994e45SJed Brown    Level: advanced
131286994e45SJed Brown 
1313107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1314107e9a97SBarry Smith 
1315107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
131686994e45SJed Brown @*/
13177087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
131886994e45SJed Brown {
131986994e45SJed Brown   PetscFunctionBegin;
132086994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
132186994e45SJed Brown   PetscValidPointer(array,2);
132245b6f7e9SBarry Smith   if (ltog->bs == 1) {
132386994e45SJed Brown     *array = ltog->indices;
132445b6f7e9SBarry Smith   } else {
132545b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
132645b6f7e9SBarry Smith     const PetscInt *ii;
132745b6f7e9SBarry Smith     PetscErrorCode ierr;
132845b6f7e9SBarry Smith 
132945b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
133045b6f7e9SBarry Smith     *array = jj;
133145b6f7e9SBarry Smith     k    = 0;
133245b6f7e9SBarry Smith     ii   = ltog->indices;
133345b6f7e9SBarry Smith     for (i=0; i<n; i++)
133445b6f7e9SBarry Smith       for (j=0; j<bs; j++)
133545b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
133645b6f7e9SBarry Smith   }
133786994e45SJed Brown   PetscFunctionReturn(0);
133886994e45SJed Brown }
133986994e45SJed Brown 
134086994e45SJed Brown #undef __FUNCT__
134186994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
134286994e45SJed Brown /*@C
134386994e45SJed Brown    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingRestoreIndices()
134486994e45SJed Brown 
134586994e45SJed Brown    Not Collective
134686994e45SJed Brown 
134786994e45SJed Brown    Input Arguments:
134886994e45SJed Brown + ltog - local to global mapping
134986994e45SJed Brown - array - array of indices
135086994e45SJed Brown 
135186994e45SJed Brown    Level: advanced
135286994e45SJed Brown 
135386994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
135486994e45SJed Brown @*/
13557087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
135686994e45SJed Brown {
135786994e45SJed Brown   PetscFunctionBegin;
135886994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
135986994e45SJed Brown   PetscValidPointer(array,2);
136045b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
136145b6f7e9SBarry Smith 
136245b6f7e9SBarry Smith   if (ltog->bs > 1) {
136345b6f7e9SBarry Smith     PetscErrorCode ierr;
136445b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
136545b6f7e9SBarry Smith   }
136645b6f7e9SBarry Smith   PetscFunctionReturn(0);
136745b6f7e9SBarry Smith }
136845b6f7e9SBarry Smith 
136945b6f7e9SBarry Smith #undef __FUNCT__
137045b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
137145b6f7e9SBarry Smith /*@C
137245b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
137345b6f7e9SBarry Smith 
137445b6f7e9SBarry Smith    Not Collective
137545b6f7e9SBarry Smith 
137645b6f7e9SBarry Smith    Input Arguments:
137745b6f7e9SBarry Smith . ltog - local to global mapping
137845b6f7e9SBarry Smith 
137945b6f7e9SBarry Smith    Output Arguments:
138045b6f7e9SBarry Smith . array - array of indices
138145b6f7e9SBarry Smith 
138245b6f7e9SBarry Smith    Level: advanced
138345b6f7e9SBarry Smith 
138445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
138545b6f7e9SBarry Smith @*/
138645b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
138745b6f7e9SBarry Smith {
138845b6f7e9SBarry Smith   PetscFunctionBegin;
138945b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
139045b6f7e9SBarry Smith   PetscValidPointer(array,2);
139145b6f7e9SBarry Smith   *array = ltog->indices;
139245b6f7e9SBarry Smith   PetscFunctionReturn(0);
139345b6f7e9SBarry Smith }
139445b6f7e9SBarry Smith 
139545b6f7e9SBarry Smith #undef __FUNCT__
139645b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
139745b6f7e9SBarry Smith /*@C
139845b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
139945b6f7e9SBarry Smith 
140045b6f7e9SBarry Smith    Not Collective
140145b6f7e9SBarry Smith 
140245b6f7e9SBarry Smith    Input Arguments:
140345b6f7e9SBarry Smith + ltog - local to global mapping
140445b6f7e9SBarry Smith - array - array of indices
140545b6f7e9SBarry Smith 
140645b6f7e9SBarry Smith    Level: advanced
140745b6f7e9SBarry Smith 
140845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
140945b6f7e9SBarry Smith @*/
141045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
141145b6f7e9SBarry Smith {
141245b6f7e9SBarry Smith   PetscFunctionBegin;
141345b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
141445b6f7e9SBarry Smith   PetscValidPointer(array,2);
141586994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
14160298fd71SBarry Smith   *array = NULL;
141786994e45SJed Brown   PetscFunctionReturn(0);
141886994e45SJed Brown }
1419f7efa3c7SJed Brown 
1420f7efa3c7SJed Brown #undef __FUNCT__
1421f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1422f7efa3c7SJed Brown /*@C
1423f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1424f7efa3c7SJed Brown 
1425f7efa3c7SJed Brown    Not Collective
1426f7efa3c7SJed Brown 
1427f7efa3c7SJed Brown    Input Arguments:
1428f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1429f7efa3c7SJed Brown . n - number of mappings to concatenate
1430f7efa3c7SJed Brown - ltogs - local to global mappings
1431f7efa3c7SJed Brown 
1432f7efa3c7SJed Brown    Output Arguments:
1433f7efa3c7SJed Brown . ltogcat - new mapping
1434f7efa3c7SJed Brown 
14359d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
14369d90f715SBarry Smith 
14379d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
14389d90f715SBarry Smith 
1439f7efa3c7SJed Brown    Level: advanced
1440f7efa3c7SJed Brown 
1441f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1442f7efa3c7SJed Brown @*/
1443f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1444f7efa3c7SJed Brown {
1445f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1446f7efa3c7SJed Brown   PetscErrorCode ierr;
1447f7efa3c7SJed Brown 
1448f7efa3c7SJed Brown   PetscFunctionBegin;
1449f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1450f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1451f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1452f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1453f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1454f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1455f7efa3c7SJed Brown     cnt += m;
1456f7efa3c7SJed Brown   }
1457785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1458f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1459f7efa3c7SJed Brown     const PetscInt *subidx;
1460f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1461f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1462f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1463f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1464f7efa3c7SJed Brown     cnt += m;
1465f7efa3c7SJed Brown   }
1466f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1467f7efa3c7SJed Brown   PetscFunctionReturn(0);
1468f7efa3c7SJed Brown }
146904a59952SBarry Smith 
147004a59952SBarry Smith 
1471