xref: /petsc/src/vec/is/utils/isltog.c (revision 268a049cce80ea6fdc8c45e49a2e08bb30487ea9)
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;
7*268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***);
88e58c17dSMatthew Knepley 
904a59952SBarry Smith 
104a2ae208SSatish Balay #undef __FUNCT__
11743c9b42SStefano Zampini #define __FUNCT__ "ISG2LMapApply"
12186d4ecdSBarry Smith PetscErrorCode ISG2LMapApply(ISLocalToGlobalMapping mapping,PetscInt n,const PetscInt in[],PetscInt out[])
13186d4ecdSBarry Smith {
14186d4ecdSBarry Smith   PetscErrorCode ierr;
15743c9b42SStefano Zampini   PetscInt       i,start,end;
16186d4ecdSBarry Smith 
17186d4ecdSBarry Smith   PetscFunctionBegin;
18186d4ecdSBarry Smith   if (!mapping->globals) {
19186d4ecdSBarry Smith     ierr = ISGlobalToLocalMappingApply(mapping,IS_GTOLM_MASK,0,0,0,0);CHKERRQ(ierr);
20186d4ecdSBarry Smith   }
21743c9b42SStefano Zampini   start = mapping->globalstart;
22743c9b42SStefano Zampini   end = mapping->globalend;
23186d4ecdSBarry Smith   for (i=0; i<n; i++) {
24186d4ecdSBarry Smith     if (in[i] < 0)          out[i] = in[i];
25186d4ecdSBarry Smith     else if (in[i] < start) out[i] = -1;
26186d4ecdSBarry Smith     else if (in[i] > end)   out[i] = -1;
27743c9b42SStefano Zampini     else                    out[i] = mapping->globals[in[i] - start];
28186d4ecdSBarry Smith   }
29186d4ecdSBarry Smith   PetscFunctionReturn(0);
30186d4ecdSBarry Smith }
31186d4ecdSBarry Smith 
32186d4ecdSBarry Smith 
33186d4ecdSBarry Smith #undef __FUNCT__
344a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
35565245c5SBarry Smith /*@
36107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
373b9aefa3SBarry Smith 
383b9aefa3SBarry Smith     Not Collective
393b9aefa3SBarry Smith 
403b9aefa3SBarry Smith     Input Parameter:
413b9aefa3SBarry Smith .   ltog - local to global mapping
423b9aefa3SBarry Smith 
433b9aefa3SBarry Smith     Output Parameter:
44107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
453b9aefa3SBarry Smith 
463b9aefa3SBarry Smith     Level: advanced
473b9aefa3SBarry Smith 
48273d9f13SBarry Smith     Concepts: mapping^local to global
493b9aefa3SBarry Smith 
503b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
513b9aefa3SBarry Smith @*/
527087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
533b9aefa3SBarry Smith {
543b9aefa3SBarry Smith   PetscFunctionBegin;
550700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
564482741eSBarry Smith   PetscValidIntPointer(n,2);
57107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
583b9aefa3SBarry Smith   PetscFunctionReturn(0);
593b9aefa3SBarry Smith }
603b9aefa3SBarry Smith 
614a2ae208SSatish Balay #undef __FUNCT__
624a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
635a5d4f66SBarry Smith /*@C
645a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
655a5d4f66SBarry Smith 
66b9cd556bSLois Curfman McInnes     Not Collective
67b9cd556bSLois Curfman McInnes 
685a5d4f66SBarry Smith     Input Parameters:
693b9aefa3SBarry Smith +   ltog - local to global mapping
703b9aefa3SBarry Smith -   viewer - viewer
715a5d4f66SBarry Smith 
72a997ad1aSLois Curfman McInnes     Level: advanced
73a997ad1aSLois Curfman McInnes 
74273d9f13SBarry Smith     Concepts: mapping^local to global
755a5d4f66SBarry Smith 
765a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
775a5d4f66SBarry Smith @*/
787087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
795a5d4f66SBarry Smith {
8032dcc486SBarry Smith   PetscInt       i;
8132dcc486SBarry Smith   PetscMPIInt    rank;
82ace3abfcSBarry Smith   PetscBool      iascii;
836849ba73SBarry Smith   PetscErrorCode ierr;
845a5d4f66SBarry Smith 
855a5d4f66SBarry Smith   PetscFunctionBegin;
860700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
873050cee2SBarry Smith   if (!viewer) {
88ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
893050cee2SBarry Smith   }
900700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
915a5d4f66SBarry Smith 
92ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
93251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
9432077d6dSBarry Smith   if (iascii) {
9598c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
967b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
975a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
987904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
996831982aSBarry Smith     }
100b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1017b23a99aSBarry Smith     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
1027b23a99aSBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
1035a5d4f66SBarry Smith   PetscFunctionReturn(0);
1045a5d4f66SBarry Smith }
1055a5d4f66SBarry Smith 
1064a2ae208SSatish Balay #undef __FUNCT__
1074a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1081f428162SBarry Smith /*@
1092bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1102bdab257SBarry Smith     ordering and a global parallel ordering.
1112bdab257SBarry Smith 
1120f5bd95cSBarry Smith     Not collective
113b9cd556bSLois Curfman McInnes 
114a997ad1aSLois Curfman McInnes     Input Parameter:
1158c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1162bdab257SBarry Smith 
117a997ad1aSLois Curfman McInnes     Output Parameter:
1182bdab257SBarry Smith .   mapping - new mapping data structure
1192bdab257SBarry Smith 
120f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
121a997ad1aSLois Curfman McInnes     Level: advanced
122a997ad1aSLois Curfman McInnes 
123273d9f13SBarry Smith     Concepts: mapping^local to global
1242bdab257SBarry Smith 
1252bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1262bdab257SBarry Smith @*/
1277087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1282bdab257SBarry Smith {
1296849ba73SBarry Smith   PetscErrorCode ierr;
1303bbf0e92SBarry Smith   PetscInt       n,bs;
1315d0c19d7SBarry Smith   const PetscInt *indices;
1322bdab257SBarry Smith   MPI_Comm       comm;
1333bbf0e92SBarry Smith   PetscBool      isblock;
1343a40ed3dSBarry Smith 
1353a40ed3dSBarry Smith   PetscFunctionBegin;
1360700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1374482741eSBarry Smith   PetscValidPointer(mapping,2);
1382bdab257SBarry Smith 
1392bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1403b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1413bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1426006e8d2SBarry Smith   if (!isblock) {
143f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
144f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1452bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1466006e8d2SBarry Smith   } else {
1476006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
148f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
14928bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
150f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1516006e8d2SBarry Smith   }
1523a40ed3dSBarry Smith   PetscFunctionReturn(0);
1532bdab257SBarry Smith }
1545a5d4f66SBarry Smith 
155a4d96a55SJed Brown #undef __FUNCT__
156a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
157a4d96a55SJed Brown /*@C
158a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
159a4d96a55SJed Brown     ordering and a global parallel ordering.
160a4d96a55SJed Brown 
161a4d96a55SJed Brown     Collective
162a4d96a55SJed Brown 
163a4d96a55SJed Brown     Input Parameter:
164a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
165a4d96a55SJed Brown -   start - first global index on this process
166a4d96a55SJed Brown 
167a4d96a55SJed Brown     Output Parameter:
168a4d96a55SJed Brown .   mapping - new mapping data structure
169a4d96a55SJed Brown 
170a4d96a55SJed Brown     Level: advanced
171a4d96a55SJed Brown 
172a4d96a55SJed Brown     Concepts: mapping^local to global
173a4d96a55SJed Brown 
174a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
175a4d96a55SJed Brown @*/
176a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
177a4d96a55SJed Brown {
178a4d96a55SJed Brown   PetscErrorCode ierr;
179a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
180a4d96a55SJed Brown   const PetscInt *ilocal;
181a4d96a55SJed Brown   MPI_Comm       comm;
182a4d96a55SJed Brown 
183a4d96a55SJed Brown   PetscFunctionBegin;
184a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
185a4d96a55SJed Brown   PetscValidPointer(mapping,3);
186a4d96a55SJed Brown 
187a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1880298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
189f6e5521dSKarl Rupp   if (ilocal) {
190f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
191f6e5521dSKarl Rupp   }
192a4d96a55SJed Brown   else maxlocal = nleaves;
193785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
194785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
195a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
196a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
197a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
198a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
199f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
200a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
201a4d96a55SJed Brown   PetscFunctionReturn(0);
202a4d96a55SJed Brown }
203b46b645bSBarry Smith 
2044a2ae208SSatish Balay #undef __FUNCT__
20545b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
20645b6f7e9SBarry Smith /*@
20745b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
20845b6f7e9SBarry Smith     ordering and a global parallel ordering.
20945b6f7e9SBarry Smith 
21045b6f7e9SBarry Smith     Not Collective
21145b6f7e9SBarry Smith 
21245b6f7e9SBarry Smith     Input Parameters:
21345b6f7e9SBarry Smith .   mapping - mapping data structure
21445b6f7e9SBarry Smith 
21545b6f7e9SBarry Smith     Output Parameter:
21645b6f7e9SBarry Smith .   bs - the blocksize
21745b6f7e9SBarry Smith 
21845b6f7e9SBarry Smith     Level: advanced
21945b6f7e9SBarry Smith 
22045b6f7e9SBarry Smith     Concepts: mapping^local to global
22145b6f7e9SBarry Smith 
22245b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
22345b6f7e9SBarry Smith @*/
22445b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
22545b6f7e9SBarry Smith {
22645b6f7e9SBarry Smith   PetscFunctionBegin;
227cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
22845b6f7e9SBarry Smith   *bs = mapping->bs;
22945b6f7e9SBarry Smith   PetscFunctionReturn(0);
23045b6f7e9SBarry Smith }
23145b6f7e9SBarry Smith 
23245b6f7e9SBarry Smith #undef __FUNCT__
2334a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
234ba5bb76aSSatish Balay /*@
23590f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
23690f02eecSBarry Smith     ordering and a global parallel ordering.
2372362add9SBarry Smith 
23889d82c54SBarry Smith     Not Collective, but communicator may have more than one process
239b9cd556bSLois Curfman McInnes 
2402362add9SBarry Smith     Input Parameters:
24189d82c54SBarry Smith +   comm - MPI communicator
242f0413b6fSBarry Smith .   bs - the block size
24328bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
24428bc9809SBarry 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
245d5ad8652SBarry Smith -   mode - see PetscCopyMode
2462362add9SBarry Smith 
247a997ad1aSLois Curfman McInnes     Output Parameter:
24890f02eecSBarry Smith .   mapping - new mapping data structure
2492362add9SBarry Smith 
250f0413b6fSBarry 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
251a997ad1aSLois Curfman McInnes     Level: advanced
252a997ad1aSLois Curfman McInnes 
253273d9f13SBarry Smith     Concepts: mapping^local to global
2542362add9SBarry Smith 
255d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2562362add9SBarry Smith @*/
257f0413b6fSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2582362add9SBarry Smith {
2596849ba73SBarry Smith   PetscErrorCode ierr;
26032dcc486SBarry Smith   PetscInt       *in;
261b46b645bSBarry Smith 
262b46b645bSBarry Smith   PetscFunctionBegin;
26373911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2644482741eSBarry Smith   PetscValidPointer(mapping,4);
265b46b645bSBarry Smith 
2660298fd71SBarry Smith   *mapping = NULL;
267607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2682362add9SBarry Smith 
26973107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
27052e6d16bSBarry Smith                            cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
271d4bb536fSBarry Smith   (*mapping)->n             = n;
272f0413b6fSBarry Smith   (*mapping)->bs            = bs;
273*268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
274*268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
275*268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
276*268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
277*268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
278d4bb536fSBarry Smith   /*
279d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
280d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
281d4bb536fSBarry Smith   */
282d4bb536fSBarry Smith   (*mapping)->globals = 0;
283d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
284785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
285d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
286d5ad8652SBarry Smith     (*mapping)->indices = in;
2876389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2886389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
2896389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
2906389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2916389a1a1SBarry Smith   }
292f6e5521dSKarl Rupp   else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
293d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
2943a40ed3dSBarry Smith   PetscFunctionReturn(0);
2952362add9SBarry Smith }
2962362add9SBarry Smith 
2974a2ae208SSatish Balay #undef __FUNCT__
2984a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
29990f02eecSBarry Smith /*@
30090f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
30190f02eecSBarry Smith    ordering and a global parallel ordering.
30290f02eecSBarry Smith 
3030f5bd95cSBarry Smith    Note Collective
304b9cd556bSLois Curfman McInnes 
30590f02eecSBarry Smith    Input Parameters:
30690f02eecSBarry Smith .  mapping - mapping data structure
30790f02eecSBarry Smith 
308a997ad1aSLois Curfman McInnes    Level: advanced
309a997ad1aSLois Curfman McInnes 
3103acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
31190f02eecSBarry Smith @*/
3126bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
31390f02eecSBarry Smith {
314dfbe8321SBarry Smith   PetscErrorCode ierr;
3155fd66863SKarl Rupp 
3163a40ed3dSBarry Smith   PetscFunctionBegin;
3176bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3186bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
319997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3206bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3216bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
322*268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
323*268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
324*268a049cSStefano Zampini   if ((*mapping)->info_indices) {
325*268a049cSStefano Zampini     PetscInt i;
326*268a049cSStefano Zampini 
327*268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
328*268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
329*268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
330*268a049cSStefano Zampini     }
331*268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
332*268a049cSStefano Zampini   }
333d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
334992144d0SBarry Smith   *mapping = 0;
3353a40ed3dSBarry Smith   PetscFunctionReturn(0);
33690f02eecSBarry Smith }
33790f02eecSBarry Smith 
3384a2ae208SSatish Balay #undef __FUNCT__
3394a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
34090f02eecSBarry Smith /*@
3413acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3423acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3433acfe500SLois Curfman McInnes     context.
34490f02eecSBarry Smith 
345b9cd556bSLois Curfman McInnes     Not collective
346b9cd556bSLois Curfman McInnes 
34790f02eecSBarry Smith     Input Parameters:
348b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
349b9cd556bSLois Curfman McInnes -   is - index set in local numbering
35090f02eecSBarry Smith 
35190f02eecSBarry Smith     Output Parameters:
35290f02eecSBarry Smith .   newis - index set in global numbering
35390f02eecSBarry Smith 
354a997ad1aSLois Curfman McInnes     Level: advanced
355a997ad1aSLois Curfman McInnes 
356273d9f13SBarry Smith     Concepts: mapping^local to global
3573acfe500SLois Curfman McInnes 
35890f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
359d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
36090f02eecSBarry Smith @*/
3617087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
36290f02eecSBarry Smith {
3636849ba73SBarry Smith   PetscErrorCode ierr;
364e24637baSBarry Smith   PetscInt       n,*idxout;
3655d0c19d7SBarry Smith   const PetscInt *idxin;
3663a40ed3dSBarry Smith 
3673a40ed3dSBarry Smith   PetscFunctionBegin;
3680700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3690700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3704482741eSBarry Smith   PetscValidPointer(newis,3);
37190f02eecSBarry Smith 
3723b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
37390f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
374785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
375e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
3763b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
377543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
3783a40ed3dSBarry Smith   PetscFunctionReturn(0);
37990f02eecSBarry Smith }
38090f02eecSBarry Smith 
381afcb2eb5SJed Brown #undef __FUNCT__
382afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
383b89cb25eSSatish Balay /*@
3843acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3853acfe500SLois Curfman McInnes    and converts them to the global numbering.
38690f02eecSBarry Smith 
387b9cd556bSLois Curfman McInnes    Not collective
388b9cd556bSLois Curfman McInnes 
389bb25748dSBarry Smith    Input Parameters:
390b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
391bb25748dSBarry Smith .  N - number of integers
392b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
393bb25748dSBarry Smith 
394bb25748dSBarry Smith    Output Parameter:
395bb25748dSBarry Smith .  out - indices in global numbering
396bb25748dSBarry Smith 
397b9cd556bSLois Curfman McInnes    Notes:
398b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
399d4bb536fSBarry Smith 
400a997ad1aSLois Curfman McInnes    Level: advanced
401a997ad1aSLois Curfman McInnes 
40245b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4030752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
404d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
405bb25748dSBarry Smith 
406273d9f13SBarry Smith     Concepts: mapping^local to global
407afcb2eb5SJed Brown @*/
408afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
409afcb2eb5SJed Brown {
410cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
41145b6f7e9SBarry Smith 
41245b6f7e9SBarry Smith   PetscFunctionBegin;
413cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
414cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
415cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
41645b6f7e9SBarry Smith   if (bs == 1) {
417cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
41845b6f7e9SBarry Smith     for (i=0; i<N; i++) {
41945b6f7e9SBarry Smith       if (in[i] < 0) {
42045b6f7e9SBarry Smith         out[i] = in[i];
42145b6f7e9SBarry Smith         continue;
42245b6f7e9SBarry Smith       }
423e24637baSBarry 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);
42445b6f7e9SBarry Smith       out[i] = idx[in[i]];
42545b6f7e9SBarry Smith     }
42645b6f7e9SBarry Smith   } else {
427cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
42845b6f7e9SBarry Smith     for (i=0; i<N; i++) {
42945b6f7e9SBarry Smith       if (in[i] < 0) {
43045b6f7e9SBarry Smith         out[i] = in[i];
43145b6f7e9SBarry Smith         continue;
43245b6f7e9SBarry Smith       }
433e24637baSBarry 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);
43445b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
43545b6f7e9SBarry Smith     }
43645b6f7e9SBarry Smith   }
43745b6f7e9SBarry Smith   PetscFunctionReturn(0);
43845b6f7e9SBarry Smith }
43945b6f7e9SBarry Smith 
44045b6f7e9SBarry Smith #undef __FUNCT__
44145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
44245b6f7e9SBarry Smith /*@
4436006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
44445b6f7e9SBarry Smith 
44545b6f7e9SBarry Smith    Not collective
44645b6f7e9SBarry Smith 
44745b6f7e9SBarry Smith    Input Parameters:
44845b6f7e9SBarry Smith +  mapping - the local to global mapping context
44945b6f7e9SBarry Smith .  N - number of integers
4506006e8d2SBarry Smith -  in - input indices in local block numbering
45145b6f7e9SBarry Smith 
45245b6f7e9SBarry Smith    Output Parameter:
4536006e8d2SBarry Smith .  out - indices in global block numbering
45445b6f7e9SBarry Smith 
45545b6f7e9SBarry Smith    Notes:
45645b6f7e9SBarry Smith    The in and out array parameters may be identical.
45745b6f7e9SBarry Smith 
4586006e8d2SBarry Smith    Example:
4596006e8d2SBarry 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
4606006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
4616006e8d2SBarry Smith 
46245b6f7e9SBarry Smith    Level: advanced
46345b6f7e9SBarry Smith 
46445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
46545b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
46645b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
46745b6f7e9SBarry Smith 
46845b6f7e9SBarry Smith     Concepts: mapping^local to global
46945b6f7e9SBarry Smith @*/
47045b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
47145b6f7e9SBarry Smith {
472cbc1caf0SMatthew G. Knepley 
473cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
474cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
475cbc1caf0SMatthew G. Knepley   {
476afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
477afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
478d4bb536fSBarry Smith 
479afcb2eb5SJed Brown     for (i=0; i<N; i++) {
480afcb2eb5SJed Brown       if (in[i] < 0) {
481afcb2eb5SJed Brown         out[i] = in[i];
482afcb2eb5SJed Brown         continue;
483afcb2eb5SJed Brown       }
484e24637baSBarry 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);
485afcb2eb5SJed Brown       out[i] = idx[in[i]];
486afcb2eb5SJed Brown     }
487cbc1caf0SMatthew G. Knepley   }
488afcb2eb5SJed Brown   PetscFunctionReturn(0);
489afcb2eb5SJed Brown }
490d4bb536fSBarry Smith 
491d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
492d4bb536fSBarry Smith 
4934a2ae208SSatish Balay #undef __FUNCT__
4944a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
495d4bb536fSBarry Smith /*
496d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
497d4bb536fSBarry Smith */
4986849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
499d4bb536fSBarry Smith {
5006849ba73SBarry Smith   PetscErrorCode ierr;
50132dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
502d4bb536fSBarry Smith 
5033a40ed3dSBarry Smith   PetscFunctionBegin;
504d4bb536fSBarry Smith   end   = 0;
505ec268f7cSJed Brown   start = PETSC_MAX_INT;
506d4bb536fSBarry Smith 
507d4bb536fSBarry Smith   for (i=0; i<n; i++) {
508d4bb536fSBarry Smith     if (idx[i] < 0) continue;
509d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
510d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
511d4bb536fSBarry Smith   }
512d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
513d4bb536fSBarry Smith   mapping->globalstart = start;
514d4bb536fSBarry Smith   mapping->globalend   = end;
515d4bb536fSBarry Smith 
516854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
517b0a32e0cSBarry Smith   mapping->globals = globals;
518f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
519d4bb536fSBarry Smith   for (i=0; i<n; i++) {
520d4bb536fSBarry Smith     if (idx[i] < 0) continue;
521d4bb536fSBarry Smith     globals[idx[i] - start] = i;
522d4bb536fSBarry Smith   }
523d4bb536fSBarry Smith 
5243bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5253a40ed3dSBarry Smith   PetscFunctionReturn(0);
526d4bb536fSBarry Smith }
527d4bb536fSBarry Smith 
5284a2ae208SSatish Balay #undef __FUNCT__
5294a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
530d4bb536fSBarry Smith /*@
531a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
532a997ad1aSLois Curfman McInnes     specified with a global numbering.
533d4bb536fSBarry Smith 
534b9cd556bSLois Curfman McInnes     Not collective
535b9cd556bSLois Curfman McInnes 
536d4bb536fSBarry Smith     Input Parameters:
537b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
538d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
539d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
540d4bb536fSBarry Smith .   n - number of global indices to map
541b9cd556bSLois Curfman McInnes -   idx - global indices to map
542d4bb536fSBarry Smith 
543d4bb536fSBarry Smith     Output Parameters:
544b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
545b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
546e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5470298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
548e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
549e182c471SBarry Smith              a second time to set the values.
550d4bb536fSBarry Smith 
551b9cd556bSLois Curfman McInnes     Notes:
5520298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
553d4bb536fSBarry Smith 
5540f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5550f5bd95cSBarry Smith     array to compute these.
5560f5bd95cSBarry Smith 
557a997ad1aSLois Curfman McInnes     Level: advanced
558a997ad1aSLois Curfman McInnes 
55932fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
56032fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
56132fd6b96SBarry Smith 
562273d9f13SBarry Smith     Concepts: mapping^global to local
563d4bb536fSBarry Smith 
5649d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
565d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
566d4bb536fSBarry Smith @*/
5677087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
56832dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
569d4bb536fSBarry Smith {
5709d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
5719d90f715SBarry Smith   PetscErrorCode ierr;
5729d90f715SBarry Smith 
5739d90f715SBarry Smith   PetscFunctionBegin;
5749d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
5759d90f715SBarry Smith   if (!mapping->globals) {
5769d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
5779d90f715SBarry Smith   }
5789d90f715SBarry Smith   globals = mapping->globals;
5799d90f715SBarry Smith   start   = mapping->globalstart;
5809d90f715SBarry Smith   end     = mapping->globalend;
5819d90f715SBarry Smith   bs      = mapping->bs;
5829d90f715SBarry Smith 
5839d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
5849d90f715SBarry Smith     if (idxout) {
5859d90f715SBarry Smith       for (i=0; i<n; i++) {
5869d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
5879d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
588663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
5899d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5909d90f715SBarry Smith       }
5919d90f715SBarry Smith     }
5929d90f715SBarry Smith     if (nout) *nout = n;
5939d90f715SBarry Smith   } else {
5949d90f715SBarry Smith     if (idxout) {
5959d90f715SBarry Smith       for (i=0; i<n; i++) {
5969d90f715SBarry Smith         if (idx[i] < 0) continue;
5979d90f715SBarry Smith         if (idx[i] < bs*start) continue;
598663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
5999d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6009d90f715SBarry Smith         if (tmp < 0) continue;
6019d90f715SBarry Smith         idxout[nf++] = tmp;
6029d90f715SBarry Smith       }
6039d90f715SBarry Smith     } else {
6049d90f715SBarry Smith       for (i=0; i<n; i++) {
6059d90f715SBarry Smith         if (idx[i] < 0) continue;
6069d90f715SBarry Smith         if (idx[i] < bs*start) continue;
607663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6089d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6099d90f715SBarry Smith         if (tmp < 0) continue;
6109d90f715SBarry Smith         nf++;
6119d90f715SBarry Smith       }
6129d90f715SBarry Smith     }
6139d90f715SBarry Smith     if (nout) *nout = nf;
6149d90f715SBarry Smith   }
6159d90f715SBarry Smith   PetscFunctionReturn(0);
6169d90f715SBarry Smith }
6179d90f715SBarry Smith 
6189d90f715SBarry Smith #undef __FUNCT__
619d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
620d4fe737eSStefano Zampini /*@
621d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
622d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
623d4fe737eSStefano Zampini     context.
624d4fe737eSStefano Zampini 
625d4fe737eSStefano Zampini     Not collective
626d4fe737eSStefano Zampini 
627d4fe737eSStefano Zampini     Input Parameters:
628d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
629d4fe737eSStefano Zampini -   is - index set in global numbering
630d4fe737eSStefano Zampini 
631d4fe737eSStefano Zampini     Output Parameters:
632d4fe737eSStefano Zampini .   newis - index set in local numbering
633d4fe737eSStefano Zampini 
634d4fe737eSStefano Zampini     Level: advanced
635d4fe737eSStefano Zampini 
636d4fe737eSStefano Zampini     Concepts: mapping^local to global
637d4fe737eSStefano Zampini 
638d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
639d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
640d4fe737eSStefano Zampini @*/
641d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
642d4fe737eSStefano Zampini {
643d4fe737eSStefano Zampini   PetscErrorCode ierr;
644d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
645d4fe737eSStefano Zampini   const PetscInt *idxin;
646d4fe737eSStefano Zampini 
647d4fe737eSStefano Zampini   PetscFunctionBegin;
648d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
649d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
650d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
651d4fe737eSStefano Zampini 
652d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
653d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
654d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
655d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
656d4fe737eSStefano Zampini   } else {
657d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
658d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
659d4fe737eSStefano Zampini   }
660d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
661d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
662d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
663d4fe737eSStefano Zampini   PetscFunctionReturn(0);
664d4fe737eSStefano Zampini }
665d4fe737eSStefano Zampini 
666d4fe737eSStefano Zampini #undef __FUNCT__
6679d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
6689d90f715SBarry Smith /*@
6699d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
6709d90f715SBarry Smith     specified with a block global numbering.
6719d90f715SBarry Smith 
6729d90f715SBarry Smith     Not collective
6739d90f715SBarry Smith 
6749d90f715SBarry Smith     Input Parameters:
6759d90f715SBarry Smith +   mapping - mapping between local and global numbering
6769d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
6779d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
6789d90f715SBarry Smith .   n - number of global indices to map
6799d90f715SBarry Smith -   idx - global indices to map
6809d90f715SBarry Smith 
6819d90f715SBarry Smith     Output Parameters:
6829d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
6839d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
6849d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
6859d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
6869d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
6879d90f715SBarry Smith              a second time to set the values.
6889d90f715SBarry Smith 
6899d90f715SBarry Smith     Notes:
6909d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
6919d90f715SBarry Smith 
6929d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6939d90f715SBarry Smith     array to compute these.
6949d90f715SBarry Smith 
6959d90f715SBarry Smith     Level: advanced
6969d90f715SBarry Smith 
6979d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
6989d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
6999d90f715SBarry Smith 
7009d90f715SBarry Smith     Concepts: mapping^global to local
7019d90f715SBarry Smith 
7029d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7039d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7049d90f715SBarry Smith @*/
7059d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7069d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7079d90f715SBarry Smith {
70832dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
7096849ba73SBarry Smith   PetscErrorCode ierr;
710d4bb536fSBarry Smith 
7113a40ed3dSBarry Smith   PetscFunctionBegin;
7120700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
713d4bb536fSBarry Smith   if (!mapping->globals) {
714d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
715d4bb536fSBarry Smith   }
716d4bb536fSBarry Smith   globals = mapping->globals;
717d4bb536fSBarry Smith   start   = mapping->globalstart;
718d4bb536fSBarry Smith   end     = mapping->globalend;
719d4bb536fSBarry Smith 
720d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
721d4bb536fSBarry Smith     if (idxout) {
722d4bb536fSBarry Smith       for (i=0; i<n; i++) {
723d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
724d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
725d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
726d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
727d4bb536fSBarry Smith       }
728d4bb536fSBarry Smith     }
729d4bb536fSBarry Smith     if (nout) *nout = n;
730d4bb536fSBarry Smith   } else {
731d4bb536fSBarry Smith     if (idxout) {
732d4bb536fSBarry Smith       for (i=0; i<n; i++) {
733d4bb536fSBarry Smith         if (idx[i] < 0) continue;
734d4bb536fSBarry Smith         if (idx[i] < start) continue;
735d4bb536fSBarry Smith         if (idx[i] > end) continue;
736d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
737d4bb536fSBarry Smith         if (tmp < 0) continue;
738d4bb536fSBarry Smith         idxout[nf++] = tmp;
739d4bb536fSBarry Smith       }
740d4bb536fSBarry Smith     } else {
741d4bb536fSBarry Smith       for (i=0; i<n; i++) {
742d4bb536fSBarry Smith         if (idx[i] < 0) continue;
743d4bb536fSBarry Smith         if (idx[i] < start) continue;
744d4bb536fSBarry Smith         if (idx[i] > end) continue;
745d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
746d4bb536fSBarry Smith         if (tmp < 0) continue;
747d4bb536fSBarry Smith         nf++;
748d4bb536fSBarry Smith       }
749d4bb536fSBarry Smith     }
750d4bb536fSBarry Smith     if (nout) *nout = nf;
751d4bb536fSBarry Smith   }
7523a40ed3dSBarry Smith   PetscFunctionReturn(0);
753d4bb536fSBarry Smith }
75490f02eecSBarry Smith 
7554a2ae208SSatish Balay #undef __FUNCT__
7566a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
75789d82c54SBarry Smith /*@C
7586a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
75989d82c54SBarry Smith      each index shared by more than one processor
76089d82c54SBarry Smith 
76189d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
76289d82c54SBarry Smith 
76389d82c54SBarry Smith     Input Parameters:
76489d82c54SBarry Smith .   mapping - the mapping from local to global indexing
76589d82c54SBarry Smith 
76689d82c54SBarry Smith     Output Parameter:
76789d82c54SBarry Smith +   nproc - number of processors that are connected to this one
76889d82c54SBarry Smith .   proc - neighboring processors
76907b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
7703463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
77189d82c54SBarry Smith 
77289d82c54SBarry Smith     Level: advanced
77389d82c54SBarry Smith 
774273d9f13SBarry Smith     Concepts: mapping^local to global
77589d82c54SBarry Smith 
7762cfcea29SBarry Smith     Fortran Usage:
7772cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
7782cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
7792cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
7802cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
7812cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
7822cfcea29SBarry Smith 
7832cfcea29SBarry Smith 
78407b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
78507b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
78689d82c54SBarry Smith @*/
7876a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
78889d82c54SBarry Smith {
7896849ba73SBarry Smith   PetscErrorCode ierr;
790*268a049cSStefano Zampini 
791*268a049cSStefano Zampini   PetscFunctionBegin;
792*268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
793*268a049cSStefano Zampini   if (mapping->info_cached) {
794*268a049cSStefano Zampini     *nproc = mapping->info_nproc;
795*268a049cSStefano Zampini     *procs = mapping->info_procs;
796*268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
797*268a049cSStefano Zampini     *indices = mapping->info_indices;
798*268a049cSStefano Zampini   } else {
799*268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
800*268a049cSStefano Zampini   }
801*268a049cSStefano Zampini   PetscFunctionReturn(0);
802*268a049cSStefano Zampini }
803*268a049cSStefano Zampini 
804*268a049cSStefano Zampini #undef __FUNCT__
805*268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
806*268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
807*268a049cSStefano Zampini {
808*268a049cSStefano Zampini   PetscErrorCode ierr;
80997f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
81032dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
81132dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
81297f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
81332dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
81432dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
81589d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
81630dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
817ce94432eSBarry Smith   MPI_Comm       comm;
818ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
81989d82c54SBarry Smith 
82089d82c54SBarry Smith   PetscFunctionBegin;
821ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
82224cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
82324cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
82424cf384cSBarry Smith   if (size == 1) {
82524cf384cSBarry Smith     *nproc         = 0;
8260298fd71SBarry Smith     *procs         = NULL;
82732dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
8281e2105dcSBarry Smith     (*numprocs)[0] = 0;
82932dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
8300298fd71SBarry Smith     (*indices)[0]  = NULL;
831*268a049cSStefano Zampini     /* save info for reuse */
832*268a049cSStefano Zampini     mapping->info_nproc = *nproc;
833*268a049cSStefano Zampini     mapping->info_procs = *procs;
834*268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
835*268a049cSStefano Zampini     mapping->info_indices = *indices;
836*268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
83724cf384cSBarry Smith     PetscFunctionReturn(0);
83824cf384cSBarry Smith   }
83924cf384cSBarry Smith 
8400298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
84107b52d57SBarry Smith 
8423677ff5aSBarry Smith   /*
8436a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
8443677ff5aSBarry Smith 
8453677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
8463677ff5aSBarry Smith            numbering, just for this routine.
8473677ff5aSBarry Smith 
8483677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
8493677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
8503677ff5aSBarry Smith 
8513677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
8523677ff5aSBarry Smith 
8533677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
8543677ff5aSBarry Smith            local subdomain
8553677ff5aSBarry Smith   */
85624cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
85724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
85824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
85989d82c54SBarry Smith 
86089d82c54SBarry Smith   for (i=0; i<n; i++) {
86189d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
86289d82c54SBarry Smith   }
86332dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
86478058e43SBarry Smith   Ng++;
86589d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
86689d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
867bc8ff85bSBarry Smith   scale  = Ng/size + 1;
868a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
869caba0dd0SBarry Smith   rstart = scale*rank;
87089d82c54SBarry Smith 
87189d82c54SBarry Smith   /* determine ownership ranges of global indices */
872785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
87332dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
87489d82c54SBarry Smith 
87589d82c54SBarry Smith   /* determine owners of each local node  */
876785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
87789d82c54SBarry Smith   for (i=0; i<n; i++) {
8783677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
87927c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
8803677ff5aSBarry Smith     owner[i]         = proc;
88127c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
88289d82c54SBarry Smith   }
88327c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
8847904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
88589d82c54SBarry Smith 
88689d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
88727c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
8887904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
88989d82c54SBarry Smith 
89089d82c54SBarry Smith   /* post receives for owned rows */
891785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
892854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
89389d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
89432dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
89589d82c54SBarry Smith   }
89689d82c54SBarry Smith 
89789d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
898854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
899854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
90089d82c54SBarry Smith   starts[0] = 0;
901f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
90289d82c54SBarry Smith   for (i=0; i<n; i++) {
90389d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
90430dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
90589d82c54SBarry Smith   }
90689d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
90789d82c54SBarry Smith   starts[0] = 0;
908f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
90989d82c54SBarry Smith 
91089d82c54SBarry Smith   /* send the messages */
911854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
912854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
91389d82c54SBarry Smith   cnt = 0;
91489d82c54SBarry Smith   for (i=0; i<size; i++) {
91527c402fcSBarry Smith     if (nprocs[2*i]) {
91632dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
91730dcb7c9SBarry Smith       dest[cnt] = i;
91889d82c54SBarry Smith       cnt++;
91989d82c54SBarry Smith     }
92089d82c54SBarry Smith   }
92189d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
92289d82c54SBarry Smith 
92389d82c54SBarry Smith   /* wait on receives */
924854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
925854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
92689d82c54SBarry Smith   cnt  = nrecvs;
927854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
92832dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
92989d82c54SBarry Smith   while (cnt) {
93089d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
93189d82c54SBarry Smith     /* unpack receives into our local space */
93232dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
93389d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
93430dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
935caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
93630dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
93789d82c54SBarry Smith     cnt--;
93889d82c54SBarry Smith   }
93989d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
94089d82c54SBarry Smith 
94130dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
942bc8ff85bSBarry Smith   nowned  = 0;
943bc8ff85bSBarry Smith   nownedm = 0;
944bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
945bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
946bc8ff85bSBarry Smith   }
947bc8ff85bSBarry Smith 
948bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
949854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
950854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
951bc8ff85bSBarry Smith   starts[0] = 0;
952bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
953bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
954bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
955bc8ff85bSBarry Smith   }
956bc8ff85bSBarry Smith 
95730dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
958bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
959bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
96030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
961f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
962bc8ff85bSBarry Smith     }
963bc8ff85bSBarry Smith   }
964bc8ff85bSBarry Smith 
96507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
96630dcb7c9SBarry Smith     starts[0] = 0;
96730dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
96830dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
96930dcb7c9SBarry Smith       else starts[i] = starts[i-1];
97030dcb7c9SBarry Smith     }
97130dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
97230dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
9737904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
97430dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
9757904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
97630dcb7c9SBarry Smith         }
97730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
97830dcb7c9SBarry Smith       }
97930dcb7c9SBarry Smith     }
9800ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
98107b52d57SBarry Smith   } /* -----------------------------------  */
98230dcb7c9SBarry Smith 
9833677ff5aSBarry Smith   /* wait on original sends */
9843a96401aSBarry Smith   if (nsends) {
985785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
9863a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
9873a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
9883a96401aSBarry Smith   }
98989d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
9903a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
9913677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
9923677ff5aSBarry Smith 
9933677ff5aSBarry Smith   /* pack messages to send back to local owners */
99430dcb7c9SBarry Smith   starts[0] = 0;
99530dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
99630dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
99730dcb7c9SBarry Smith     else starts[i] = starts[i-1];
99830dcb7c9SBarry Smith   }
99930dcb7c9SBarry Smith   nsends2 = nrecvs;
1000854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
100130dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
100230dcb7c9SBarry Smith     nprocs[i] = 1;
100330dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
100430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1005f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
100630dcb7c9SBarry Smith     }
100730dcb7c9SBarry Smith   }
1008f6e5521dSKarl Rupp   nt = 0;
1009f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1010f6e5521dSKarl Rupp 
1011854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1012854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1013f6e5521dSKarl Rupp 
1014f6e5521dSKarl Rupp   starts2[0] = 0;
1015f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
101630dcb7c9SBarry Smith   /*
101730dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
101830dcb7c9SBarry Smith        (0) the number of nodes being sent back
101930dcb7c9SBarry Smith        (1) the local node number,
102030dcb7c9SBarry Smith        (2) the number of processors sharing it,
102130dcb7c9SBarry Smith        (3) the processors sharing it
102230dcb7c9SBarry Smith   */
102330dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
102430dcb7c9SBarry Smith     cnt = 1;
102530dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
102630dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
102730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
102830dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
102930dcb7c9SBarry Smith         sends2[starts2[i]]++;
103030dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
103130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
103232dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
103330dcb7c9SBarry Smith         cnt += nownedsenders[node];
103430dcb7c9SBarry Smith       }
103530dcb7c9SBarry Smith     }
103630dcb7c9SBarry Smith   }
103730dcb7c9SBarry Smith 
103830dcb7c9SBarry Smith   /* receive the message lengths */
103930dcb7c9SBarry Smith   nrecvs2 = nsends;
1040854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1041854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1042854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
104330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1044d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
104530dcb7c9SBarry Smith   }
1046d44834fbSBarry Smith 
10478a8e0b3aSBarry Smith   /* send the message lengths */
10488a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
10498a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
10508a8e0b3aSBarry Smith   }
10518a8e0b3aSBarry Smith 
1052d44834fbSBarry Smith   /* wait on receives of lens */
10530c468ba9SBarry Smith   if (nrecvs2) {
1054785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1055d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1056d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10570c468ba9SBarry Smith   }
1058a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1059d44834fbSBarry Smith 
106030dcb7c9SBarry Smith   starts3[0] = 0;
1061d44834fbSBarry Smith   nt         = 0;
106230dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
106330dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1064d44834fbSBarry Smith     nt          += lens2[i];
106530dcb7c9SBarry Smith   }
106676466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1067d44834fbSBarry Smith 
1068854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1069854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
107052b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
107132dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
107230dcb7c9SBarry Smith   }
107330dcb7c9SBarry Smith 
107430dcb7c9SBarry Smith   /* send the messages */
1075854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
107630dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
107732dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
107830dcb7c9SBarry Smith   }
107930dcb7c9SBarry Smith 
108030dcb7c9SBarry Smith   /* wait on receives */
10810c468ba9SBarry Smith   if (nrecvs2) {
1082785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
108330dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
108430dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10850c468ba9SBarry Smith   }
108630dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
108730dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
108830dcb7c9SBarry Smith 
108907b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
109030dcb7c9SBarry Smith     cnt = 0;
109130dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
109230dcb7c9SBarry Smith       nt = recvs2[cnt++];
109330dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
10947904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
109530dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
10967904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
109730dcb7c9SBarry Smith         }
109830dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
109930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
110030dcb7c9SBarry Smith       }
110130dcb7c9SBarry Smith     }
11020ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
110307b52d57SBarry Smith   } /* -----------------------------------  */
110430dcb7c9SBarry Smith 
110530dcb7c9SBarry Smith   /* count number subdomains for each local node */
1106785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
110732dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
110830dcb7c9SBarry Smith   cnt  = 0;
110930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
111030dcb7c9SBarry Smith     nt = recvs2[cnt++];
111130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1112f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
111330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
111430dcb7c9SBarry Smith     }
111530dcb7c9SBarry Smith   }
111630dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
111730dcb7c9SBarry Smith   *nproc    = nt;
1118854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1119854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1120854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
11210298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1122785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
112330dcb7c9SBarry Smith   cnt  = 0;
112430dcb7c9SBarry Smith   for (i=0; i<size; i++) {
112530dcb7c9SBarry Smith     if (nprocs[i] > 0) {
112630dcb7c9SBarry Smith       bprocs[i]        = cnt;
112730dcb7c9SBarry Smith       (*procs)[cnt]    = i;
112830dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1129785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
113030dcb7c9SBarry Smith       cnt++;
113130dcb7c9SBarry Smith     }
113230dcb7c9SBarry Smith   }
113330dcb7c9SBarry Smith 
113430dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
113532dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
113630dcb7c9SBarry Smith   cnt  = 0;
113730dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
113830dcb7c9SBarry Smith     nt = recvs2[cnt++];
113930dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1140f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
114130dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
114230dcb7c9SBarry Smith     }
114330dcb7c9SBarry Smith   }
114430dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
114507b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
114630dcb7c9SBarry Smith 
114707b52d57SBarry Smith   /* sort the node indexing by their global numbers */
114807b52d57SBarry Smith   nt = *nproc;
114907b52d57SBarry Smith   for (i=0; i<nt; i++) {
1150854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1151f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
115207b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
115307b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
115407b52d57SBarry Smith   }
115507b52d57SBarry Smith 
115607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
115730dcb7c9SBarry Smith     nt = *nproc;
115830dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
11597904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
116030dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
11617904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
116230dcb7c9SBarry Smith       }
116330dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
116430dcb7c9SBarry Smith     }
11650ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
116607b52d57SBarry Smith   } /* -----------------------------------  */
116730dcb7c9SBarry Smith 
116830dcb7c9SBarry Smith   /* wait on sends */
116930dcb7c9SBarry Smith   if (nsends2) {
1170785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
117130dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
117230dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
117330dcb7c9SBarry Smith   }
117430dcb7c9SBarry Smith 
117530dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
117630dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
117730dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
11783677ff5aSBarry Smith 
1179bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1180bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1181bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
118230dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
118330dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
118489d82c54SBarry Smith 
118589d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
118697f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
118789d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
11883a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
118930dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
119024cf384cSBarry Smith 
119124cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
119224cf384cSBarry Smith   first_procs    = (*procs)[0];
119324cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
119424cf384cSBarry Smith   first_indices  = (*indices)[0];
119524cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
119624cf384cSBarry Smith     if ((*procs)[i] == rank) {
119724cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
119824cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
119924cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
120024cf384cSBarry Smith       (*procs)[i]    = first_procs;
120124cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
120224cf384cSBarry Smith       (*indices)[i]  = first_indices;
120324cf384cSBarry Smith       break;
120424cf384cSBarry Smith     }
120524cf384cSBarry Smith   }
1206*268a049cSStefano Zampini 
1207*268a049cSStefano Zampini   /* save info for reuse */
1208*268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1209*268a049cSStefano Zampini   mapping->info_procs = *procs;
1210*268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1211*268a049cSStefano Zampini   mapping->info_indices = *indices;
1212*268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
121389d82c54SBarry Smith   PetscFunctionReturn(0);
121489d82c54SBarry Smith }
121589d82c54SBarry Smith 
12164a2ae208SSatish Balay #undef __FUNCT__
12176a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
12186a818285SBarry Smith /*@C
12196a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
12206a818285SBarry Smith 
12216a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12226a818285SBarry Smith 
12236a818285SBarry Smith     Input Parameters:
12246a818285SBarry Smith .   mapping - the mapping from local to global indexing
12256a818285SBarry Smith 
12266a818285SBarry Smith     Output Parameter:
12276a818285SBarry Smith +   nproc - number of processors that are connected to this one
12286a818285SBarry Smith .   proc - neighboring processors
12296a818285SBarry Smith .   numproc - number of indices for each processor
12306a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12316a818285SBarry Smith 
12326a818285SBarry Smith     Level: advanced
12336a818285SBarry Smith 
12346a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12356a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
12366a818285SBarry Smith @*/
12376a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12386a818285SBarry Smith {
12396a818285SBarry Smith   PetscErrorCode ierr;
12406a818285SBarry Smith 
12416a818285SBarry Smith   PetscFunctionBegin;
1242cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1243*268a049cSStefano Zampini   if (mapping->info_free) {
12446a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
12456a818285SBarry Smith     if (*indices) {
1246*268a049cSStefano Zampini       PetscInt i;
1247*268a049cSStefano Zampini 
12486a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
12496a818285SBarry Smith       for (i=1; i<*nproc; i++) {
12506a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
12516a818285SBarry Smith       }
12526a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
12536a818285SBarry Smith     }
1254*268a049cSStefano Zampini   }
1255*268a049cSStefano Zampini   *nproc = 0;
1256*268a049cSStefano Zampini   *procs = NULL;
1257*268a049cSStefano Zampini   *numprocs = NULL;
1258*268a049cSStefano Zampini   *indices = NULL;
12596a818285SBarry Smith   PetscFunctionReturn(0);
12606a818285SBarry Smith }
12616a818285SBarry Smith 
12626a818285SBarry Smith #undef __FUNCT__
12636a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
12646a818285SBarry Smith /*@C
12656a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
12666a818285SBarry Smith      each index shared by more than one processor
12676a818285SBarry Smith 
12686a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12696a818285SBarry Smith 
12706a818285SBarry Smith     Input Parameters:
12716a818285SBarry Smith .   mapping - the mapping from local to global indexing
12726a818285SBarry Smith 
12736a818285SBarry Smith     Output Parameter:
12746a818285SBarry Smith +   nproc - number of processors that are connected to this one
12756a818285SBarry Smith .   proc - neighboring processors
12766a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
12776a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
12786a818285SBarry Smith 
12796a818285SBarry Smith     Level: advanced
12806a818285SBarry Smith 
12816a818285SBarry Smith     Concepts: mapping^local to global
12826a818285SBarry Smith 
12836a818285SBarry Smith     Fortran Usage:
12846a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
12856a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
12866a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
12876a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
12886a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
12896a818285SBarry Smith 
12906a818285SBarry Smith 
12916a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12926a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
12936a818285SBarry Smith @*/
12946a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12956a818285SBarry Smith {
12966a818285SBarry Smith   PetscErrorCode ierr;
1297*268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
12986a818285SBarry Smith 
12996a818285SBarry Smith   PetscFunctionBegin;
13006a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1301*268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1302*268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1303732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1304*268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13056a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1306*268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1307*268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13086a818285SBarry Smith         for (k=0; k<bs; k++) {
13096a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13106a818285SBarry Smith         }
13116a818285SBarry Smith       }
1312*268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13136a818285SBarry Smith     }
1314*268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1315*268a049cSStefano Zampini   } else {
1316*268a049cSStefano Zampini     *numprocs = bnumprocs;
1317*268a049cSStefano Zampini     *indices  = bindices;
13186a818285SBarry Smith   }
13196a818285SBarry Smith   PetscFunctionReturn(0);
13206a818285SBarry Smith }
13216a818285SBarry Smith 
13226a818285SBarry Smith #undef __FUNCT__
13234a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
132407b52d57SBarry Smith /*@C
132507b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
132689d82c54SBarry Smith 
132707b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
132807b52d57SBarry Smith 
132907b52d57SBarry Smith     Input Parameters:
133007b52d57SBarry Smith .   mapping - the mapping from local to global indexing
133107b52d57SBarry Smith 
133207b52d57SBarry Smith     Output Parameter:
133307b52d57SBarry Smith +   nproc - number of processors that are connected to this one
133407b52d57SBarry Smith .   proc - neighboring processors
133507b52d57SBarry Smith .   numproc - number of indices for each processor
133607b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
133707b52d57SBarry Smith 
133807b52d57SBarry Smith     Level: advanced
133907b52d57SBarry Smith 
134007b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
134107b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
134207b52d57SBarry Smith @*/
13437087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
134407b52d57SBarry Smith {
13456849ba73SBarry Smith   PetscErrorCode ierr;
134607b52d57SBarry Smith 
134707b52d57SBarry Smith   PetscFunctionBegin;
13486a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
134907b52d57SBarry Smith   PetscFunctionReturn(0);
135007b52d57SBarry Smith }
135186994e45SJed Brown 
135286994e45SJed Brown #undef __FUNCT__
135386994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
135486994e45SJed Brown /*@C
1355107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
135686994e45SJed Brown 
135786994e45SJed Brown    Not Collective
135886994e45SJed Brown 
135986994e45SJed Brown    Input Arguments:
136086994e45SJed Brown . ltog - local to global mapping
136186994e45SJed Brown 
136286994e45SJed Brown    Output Arguments:
1363565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
136486994e45SJed Brown 
136586994e45SJed Brown    Level: advanced
136686994e45SJed Brown 
1367107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1368107e9a97SBarry Smith 
1369107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
137086994e45SJed Brown @*/
13717087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
137286994e45SJed Brown {
137386994e45SJed Brown   PetscFunctionBegin;
137486994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
137586994e45SJed Brown   PetscValidPointer(array,2);
137645b6f7e9SBarry Smith   if (ltog->bs == 1) {
137786994e45SJed Brown     *array = ltog->indices;
137845b6f7e9SBarry Smith   } else {
137945b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
138045b6f7e9SBarry Smith     const PetscInt *ii;
138145b6f7e9SBarry Smith     PetscErrorCode ierr;
138245b6f7e9SBarry Smith 
138345b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
138445b6f7e9SBarry Smith     *array = jj;
138545b6f7e9SBarry Smith     k    = 0;
138645b6f7e9SBarry Smith     ii   = ltog->indices;
138745b6f7e9SBarry Smith     for (i=0; i<n; i++)
138845b6f7e9SBarry Smith       for (j=0; j<bs; j++)
138945b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
139045b6f7e9SBarry Smith   }
139186994e45SJed Brown   PetscFunctionReturn(0);
139286994e45SJed Brown }
139386994e45SJed Brown 
139486994e45SJed Brown #undef __FUNCT__
139586994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
139686994e45SJed Brown /*@C
139786994e45SJed Brown    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingRestoreIndices()
139886994e45SJed Brown 
139986994e45SJed Brown    Not Collective
140086994e45SJed Brown 
140186994e45SJed Brown    Input Arguments:
140286994e45SJed Brown + ltog - local to global mapping
140386994e45SJed Brown - array - array of indices
140486994e45SJed Brown 
140586994e45SJed Brown    Level: advanced
140686994e45SJed Brown 
140786994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
140886994e45SJed Brown @*/
14097087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
141086994e45SJed Brown {
141186994e45SJed Brown   PetscFunctionBegin;
141286994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
141386994e45SJed Brown   PetscValidPointer(array,2);
141445b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
141545b6f7e9SBarry Smith 
141645b6f7e9SBarry Smith   if (ltog->bs > 1) {
141745b6f7e9SBarry Smith     PetscErrorCode ierr;
141845b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
141945b6f7e9SBarry Smith   }
142045b6f7e9SBarry Smith   PetscFunctionReturn(0);
142145b6f7e9SBarry Smith }
142245b6f7e9SBarry Smith 
142345b6f7e9SBarry Smith #undef __FUNCT__
142445b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
142545b6f7e9SBarry Smith /*@C
142645b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
142745b6f7e9SBarry Smith 
142845b6f7e9SBarry Smith    Not Collective
142945b6f7e9SBarry Smith 
143045b6f7e9SBarry Smith    Input Arguments:
143145b6f7e9SBarry Smith . ltog - local to global mapping
143245b6f7e9SBarry Smith 
143345b6f7e9SBarry Smith    Output Arguments:
143445b6f7e9SBarry Smith . array - array of indices
143545b6f7e9SBarry Smith 
143645b6f7e9SBarry Smith    Level: advanced
143745b6f7e9SBarry Smith 
143845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
143945b6f7e9SBarry Smith @*/
144045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
144145b6f7e9SBarry Smith {
144245b6f7e9SBarry Smith   PetscFunctionBegin;
144345b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
144445b6f7e9SBarry Smith   PetscValidPointer(array,2);
144545b6f7e9SBarry Smith   *array = ltog->indices;
144645b6f7e9SBarry Smith   PetscFunctionReturn(0);
144745b6f7e9SBarry Smith }
144845b6f7e9SBarry Smith 
144945b6f7e9SBarry Smith #undef __FUNCT__
145045b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
145145b6f7e9SBarry Smith /*@C
145245b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
145345b6f7e9SBarry Smith 
145445b6f7e9SBarry Smith    Not Collective
145545b6f7e9SBarry Smith 
145645b6f7e9SBarry Smith    Input Arguments:
145745b6f7e9SBarry Smith + ltog - local to global mapping
145845b6f7e9SBarry Smith - array - array of indices
145945b6f7e9SBarry Smith 
146045b6f7e9SBarry Smith    Level: advanced
146145b6f7e9SBarry Smith 
146245b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
146345b6f7e9SBarry Smith @*/
146445b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
146545b6f7e9SBarry Smith {
146645b6f7e9SBarry Smith   PetscFunctionBegin;
146745b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
146845b6f7e9SBarry Smith   PetscValidPointer(array,2);
146986994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
14700298fd71SBarry Smith   *array = NULL;
147186994e45SJed Brown   PetscFunctionReturn(0);
147286994e45SJed Brown }
1473f7efa3c7SJed Brown 
1474f7efa3c7SJed Brown #undef __FUNCT__
1475f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1476f7efa3c7SJed Brown /*@C
1477f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1478f7efa3c7SJed Brown 
1479f7efa3c7SJed Brown    Not Collective
1480f7efa3c7SJed Brown 
1481f7efa3c7SJed Brown    Input Arguments:
1482f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1483f7efa3c7SJed Brown . n - number of mappings to concatenate
1484f7efa3c7SJed Brown - ltogs - local to global mappings
1485f7efa3c7SJed Brown 
1486f7efa3c7SJed Brown    Output Arguments:
1487f7efa3c7SJed Brown . ltogcat - new mapping
1488f7efa3c7SJed Brown 
14899d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
14909d90f715SBarry Smith 
14919d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
14929d90f715SBarry Smith 
1493f7efa3c7SJed Brown    Level: advanced
1494f7efa3c7SJed Brown 
1495f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1496f7efa3c7SJed Brown @*/
1497f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1498f7efa3c7SJed Brown {
1499f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1500f7efa3c7SJed Brown   PetscErrorCode ierr;
1501f7efa3c7SJed Brown 
1502f7efa3c7SJed Brown   PetscFunctionBegin;
1503f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1504f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1505f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1506f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1507f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1508f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1509f7efa3c7SJed Brown     cnt += m;
1510f7efa3c7SJed Brown   }
1511785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1512f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1513f7efa3c7SJed Brown     const PetscInt *subidx;
1514f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1515f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1516f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1517f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1518f7efa3c7SJed Brown     cnt += m;
1519f7efa3c7SJed Brown   }
1520f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1521f7efa3c7SJed Brown   PetscFunctionReturn(0);
1522f7efa3c7SJed Brown }
152304a59952SBarry Smith 
152404a59952SBarry Smith 
1525