xref: /petsc/src/vec/is/utils/isltog.c (revision 63fa5c835b8b49e9f15e3fd165175a1a102ac62d)
12362add9SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>    /*I "petscis.h"  I*/
30c312b8eSJed Brown #include <petscsf.h>
4665c2dedSJed Brown #include <petscviewer.h>
52362add9SBarry Smith 
67087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID;
7268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***);
88e58c17dSMatthew Knepley 
9186d4ecdSBarry Smith #undef __FUNCT__
104a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
11565245c5SBarry Smith /*@
12107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
133b9aefa3SBarry Smith 
143b9aefa3SBarry Smith     Not Collective
153b9aefa3SBarry Smith 
163b9aefa3SBarry Smith     Input Parameter:
173b9aefa3SBarry Smith .   ltog - local to global mapping
183b9aefa3SBarry Smith 
193b9aefa3SBarry Smith     Output Parameter:
20107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
213b9aefa3SBarry Smith 
223b9aefa3SBarry Smith     Level: advanced
233b9aefa3SBarry Smith 
24273d9f13SBarry Smith     Concepts: mapping^local to global
253b9aefa3SBarry Smith 
263b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
273b9aefa3SBarry Smith @*/
287087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
293b9aefa3SBarry Smith {
303b9aefa3SBarry Smith   PetscFunctionBegin;
310700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
324482741eSBarry Smith   PetscValidIntPointer(n,2);
33107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
343b9aefa3SBarry Smith   PetscFunctionReturn(0);
353b9aefa3SBarry Smith }
363b9aefa3SBarry Smith 
374a2ae208SSatish Balay #undef __FUNCT__
384a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
395a5d4f66SBarry Smith /*@C
405a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
415a5d4f66SBarry Smith 
42b9cd556bSLois Curfman McInnes     Not Collective
43b9cd556bSLois Curfman McInnes 
445a5d4f66SBarry Smith     Input Parameters:
453b9aefa3SBarry Smith +   ltog - local to global mapping
463b9aefa3SBarry Smith -   viewer - viewer
475a5d4f66SBarry Smith 
48a997ad1aSLois Curfman McInnes     Level: advanced
49a997ad1aSLois Curfman McInnes 
50273d9f13SBarry Smith     Concepts: mapping^local to global
515a5d4f66SBarry Smith 
525a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
535a5d4f66SBarry Smith @*/
547087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
555a5d4f66SBarry Smith {
5632dcc486SBarry Smith   PetscInt       i;
5732dcc486SBarry Smith   PetscMPIInt    rank;
58ace3abfcSBarry Smith   PetscBool      iascii;
596849ba73SBarry Smith   PetscErrorCode ierr;
605a5d4f66SBarry Smith 
615a5d4f66SBarry Smith   PetscFunctionBegin;
620700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
633050cee2SBarry Smith   if (!viewer) {
64ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
653050cee2SBarry Smith   }
660700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
675a5d4f66SBarry Smith 
68ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
69251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
7032077d6dSBarry Smith   if (iascii) {
7198c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
721575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
735a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
747904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
756831982aSBarry Smith     }
76b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
771575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
781575c14dSBarry Smith   }
795a5d4f66SBarry Smith   PetscFunctionReturn(0);
805a5d4f66SBarry Smith }
815a5d4f66SBarry Smith 
824a2ae208SSatish Balay #undef __FUNCT__
834a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
841f428162SBarry Smith /*@
852bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
862bdab257SBarry Smith     ordering and a global parallel ordering.
872bdab257SBarry Smith 
880f5bd95cSBarry Smith     Not collective
89b9cd556bSLois Curfman McInnes 
90a997ad1aSLois Curfman McInnes     Input Parameter:
918c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
922bdab257SBarry Smith 
93a997ad1aSLois Curfman McInnes     Output Parameter:
942bdab257SBarry Smith .   mapping - new mapping data structure
952bdab257SBarry Smith 
96f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
97a997ad1aSLois Curfman McInnes     Level: advanced
98a997ad1aSLois Curfman McInnes 
99273d9f13SBarry Smith     Concepts: mapping^local to global
1002bdab257SBarry Smith 
1012bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1022bdab257SBarry Smith @*/
1037087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1042bdab257SBarry Smith {
1056849ba73SBarry Smith   PetscErrorCode ierr;
1063bbf0e92SBarry Smith   PetscInt       n,bs;
1075d0c19d7SBarry Smith   const PetscInt *indices;
1082bdab257SBarry Smith   MPI_Comm       comm;
1093bbf0e92SBarry Smith   PetscBool      isblock;
1103a40ed3dSBarry Smith 
1113a40ed3dSBarry Smith   PetscFunctionBegin;
1120700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1134482741eSBarry Smith   PetscValidPointer(mapping,2);
1142bdab257SBarry Smith 
1152bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1163b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1173bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1186006e8d2SBarry Smith   if (!isblock) {
119f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
120f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1212bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1226006e8d2SBarry Smith   } else {
1236006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
124f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
12528bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
126f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1276006e8d2SBarry Smith   }
1283a40ed3dSBarry Smith   PetscFunctionReturn(0);
1292bdab257SBarry Smith }
1305a5d4f66SBarry Smith 
131a4d96a55SJed Brown #undef __FUNCT__
132a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
133a4d96a55SJed Brown /*@C
134a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
135a4d96a55SJed Brown     ordering and a global parallel ordering.
136a4d96a55SJed Brown 
137a4d96a55SJed Brown     Collective
138a4d96a55SJed Brown 
139a4d96a55SJed Brown     Input Parameter:
140a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
141a4d96a55SJed Brown -   start - first global index on this process
142a4d96a55SJed Brown 
143a4d96a55SJed Brown     Output Parameter:
144a4d96a55SJed Brown .   mapping - new mapping data structure
145a4d96a55SJed Brown 
146a4d96a55SJed Brown     Level: advanced
147a4d96a55SJed Brown 
148a4d96a55SJed Brown     Concepts: mapping^local to global
149a4d96a55SJed Brown 
150a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
151a4d96a55SJed Brown @*/
152a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
153a4d96a55SJed Brown {
154a4d96a55SJed Brown   PetscErrorCode ierr;
155a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
156a4d96a55SJed Brown   const PetscInt *ilocal;
157a4d96a55SJed Brown   MPI_Comm       comm;
158a4d96a55SJed Brown 
159a4d96a55SJed Brown   PetscFunctionBegin;
160a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
161a4d96a55SJed Brown   PetscValidPointer(mapping,3);
162a4d96a55SJed Brown 
163a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1640298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
165f6e5521dSKarl Rupp   if (ilocal) {
166f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
167f6e5521dSKarl Rupp   }
168a4d96a55SJed Brown   else maxlocal = nleaves;
169785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
170785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
171a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
172a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
173a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
174a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
175f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
176a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
177a4d96a55SJed Brown   PetscFunctionReturn(0);
178a4d96a55SJed Brown }
179b46b645bSBarry Smith 
1804a2ae208SSatish Balay #undef __FUNCT__
181*63fa5c83Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingSetBlockSize"
182*63fa5c83Sstefano_zampini /*@
183*63fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
184*63fa5c83Sstefano_zampini 
185*63fa5c83Sstefano_zampini     Not collective
186*63fa5c83Sstefano_zampini 
187*63fa5c83Sstefano_zampini     Input Parameters:
188*63fa5c83Sstefano_zampini .   mapping - mapping data structure
189*63fa5c83Sstefano_zampini .   bs - the blocksize
190*63fa5c83Sstefano_zampini 
191*63fa5c83Sstefano_zampini     Level: advanced
192*63fa5c83Sstefano_zampini 
193*63fa5c83Sstefano_zampini     Concepts: mapping^local to global
194*63fa5c83Sstefano_zampini 
195*63fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
196*63fa5c83Sstefano_zampini @*/
197*63fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
198*63fa5c83Sstefano_zampini {
199*63fa5c83Sstefano_zampini   PetscInt       *nid,*oid;
200*63fa5c83Sstefano_zampini   PetscInt       i,on,obs,nn,cum;
201*63fa5c83Sstefano_zampini   PetscErrorCode ierr;
202*63fa5c83Sstefano_zampini 
203*63fa5c83Sstefano_zampini   PetscFunctionBegin;
204*63fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
205*63fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
206*63fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
207*63fa5c83Sstefano_zampini   on  = mapping->n;
208*63fa5c83Sstefano_zampini   obs = mapping->bs;
209*63fa5c83Sstefano_zampini   oid = mapping->indices;
210*63fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
211*63fa5c83Sstefano_zampini   if ((on*obs)%bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D and number of block indices %D",bs,obs,on);
212*63fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
213*63fa5c83Sstefano_zampini   for (i=0,cum=0;i<on;i++) {
214*63fa5c83Sstefano_zampini     if (!((oid[i]*obs)%bs)) {
215*63fa5c83Sstefano_zampini       if (cum==nn) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices",bs,obs);
216*63fa5c83Sstefano_zampini       nid[cum++] = (oid[i]*obs)/bs;
217*63fa5c83Sstefano_zampini     }
218*63fa5c83Sstefano_zampini   }
219*63fa5c83Sstefano_zampini   if (cum != nn) {
220*63fa5c83Sstefano_zampini     ierr = PetscFree(nid);CHKERRQ(ierr);
221*63fa5c83Sstefano_zampini     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Incompatible block sizes %D and %D (new block indices found %D != %D)",bs,obs,cum,nn);
222*63fa5c83Sstefano_zampini   }
223*63fa5c83Sstefano_zampini   mapping->n       = nn;
224*63fa5c83Sstefano_zampini   mapping->bs      = bs;
225*63fa5c83Sstefano_zampini   ierr             = PetscFree(mapping->indices);CHKERRQ(ierr);
226*63fa5c83Sstefano_zampini   mapping->indices = nid;
227*63fa5c83Sstefano_zampini   PetscFunctionReturn(0);
228*63fa5c83Sstefano_zampini }
229*63fa5c83Sstefano_zampini 
230*63fa5c83Sstefano_zampini #undef __FUNCT__
23145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
23245b6f7e9SBarry Smith /*@
23345b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
23445b6f7e9SBarry Smith     ordering and a global parallel ordering.
23545b6f7e9SBarry Smith 
23645b6f7e9SBarry Smith     Not Collective
23745b6f7e9SBarry Smith 
23845b6f7e9SBarry Smith     Input Parameters:
23945b6f7e9SBarry Smith .   mapping - mapping data structure
24045b6f7e9SBarry Smith 
24145b6f7e9SBarry Smith     Output Parameter:
24245b6f7e9SBarry Smith .   bs - the blocksize
24345b6f7e9SBarry Smith 
24445b6f7e9SBarry Smith     Level: advanced
24545b6f7e9SBarry Smith 
24645b6f7e9SBarry Smith     Concepts: mapping^local to global
24745b6f7e9SBarry Smith 
24845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
24945b6f7e9SBarry Smith @*/
25045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
25145b6f7e9SBarry Smith {
25245b6f7e9SBarry Smith   PetscFunctionBegin;
253cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
25445b6f7e9SBarry Smith   *bs = mapping->bs;
25545b6f7e9SBarry Smith   PetscFunctionReturn(0);
25645b6f7e9SBarry Smith }
25745b6f7e9SBarry Smith 
25845b6f7e9SBarry Smith #undef __FUNCT__
2594a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
260ba5bb76aSSatish Balay /*@
26190f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
26290f02eecSBarry Smith     ordering and a global parallel ordering.
2632362add9SBarry Smith 
26489d82c54SBarry Smith     Not Collective, but communicator may have more than one process
265b9cd556bSLois Curfman McInnes 
2662362add9SBarry Smith     Input Parameters:
26789d82c54SBarry Smith +   comm - MPI communicator
268f0413b6fSBarry Smith .   bs - the block size
26928bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
27028bc9809SBarry 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
271d5ad8652SBarry Smith -   mode - see PetscCopyMode
2722362add9SBarry Smith 
273a997ad1aSLois Curfman McInnes     Output Parameter:
27490f02eecSBarry Smith .   mapping - new mapping data structure
2752362add9SBarry Smith 
276f0413b6fSBarry 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
277a997ad1aSLois Curfman McInnes     Level: advanced
278a997ad1aSLois Curfman McInnes 
279273d9f13SBarry Smith     Concepts: mapping^local to global
2802362add9SBarry Smith 
281d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2822362add9SBarry Smith @*/
28360c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2842362add9SBarry Smith {
2856849ba73SBarry Smith   PetscErrorCode ierr;
28632dcc486SBarry Smith   PetscInt       *in;
287b46b645bSBarry Smith 
288b46b645bSBarry Smith   PetscFunctionBegin;
28973911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2904482741eSBarry Smith   PetscValidPointer(mapping,4);
291b46b645bSBarry Smith 
2920298fd71SBarry Smith   *mapping = NULL;
293607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2942362add9SBarry Smith 
29573107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
29660c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
297d4bb536fSBarry Smith   (*mapping)->n             = n;
298f0413b6fSBarry Smith   (*mapping)->bs            = bs;
299268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
300268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
301268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
302268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
303268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
304d4bb536fSBarry Smith   /*
305d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
306d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
307d4bb536fSBarry Smith   */
308d4bb536fSBarry Smith   (*mapping)->globals = 0;
309d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
310785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
311d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
312d5ad8652SBarry Smith     (*mapping)->indices = in;
3136389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3146389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
3156389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
3166389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3176389a1a1SBarry Smith   }
31860c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
319d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
3203a40ed3dSBarry Smith   PetscFunctionReturn(0);
3212362add9SBarry Smith }
3222362add9SBarry Smith 
3234a2ae208SSatish Balay #undef __FUNCT__
3244a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
32590f02eecSBarry Smith /*@
32690f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
32790f02eecSBarry Smith    ordering and a global parallel ordering.
32890f02eecSBarry Smith 
3290f5bd95cSBarry Smith    Note Collective
330b9cd556bSLois Curfman McInnes 
33190f02eecSBarry Smith    Input Parameters:
33290f02eecSBarry Smith .  mapping - mapping data structure
33390f02eecSBarry Smith 
334a997ad1aSLois Curfman McInnes    Level: advanced
335a997ad1aSLois Curfman McInnes 
3363acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
33790f02eecSBarry Smith @*/
3386bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
33990f02eecSBarry Smith {
340dfbe8321SBarry Smith   PetscErrorCode ierr;
3415fd66863SKarl Rupp 
3423a40ed3dSBarry Smith   PetscFunctionBegin;
3436bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3446bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
345997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
3466bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
3476bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
348268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
349268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
350268a049cSStefano Zampini   if ((*mapping)->info_indices) {
351268a049cSStefano Zampini     PetscInt i;
352268a049cSStefano Zampini 
353268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
354268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
355268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
356268a049cSStefano Zampini     }
357268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
358268a049cSStefano Zampini   }
359d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
360992144d0SBarry Smith   *mapping = 0;
3613a40ed3dSBarry Smith   PetscFunctionReturn(0);
36290f02eecSBarry Smith }
36390f02eecSBarry Smith 
3644a2ae208SSatish Balay #undef __FUNCT__
3654a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
36690f02eecSBarry Smith /*@
3673acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3683acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3693acfe500SLois Curfman McInnes     context.
37090f02eecSBarry Smith 
371b9cd556bSLois Curfman McInnes     Not collective
372b9cd556bSLois Curfman McInnes 
37390f02eecSBarry Smith     Input Parameters:
374b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
375b9cd556bSLois Curfman McInnes -   is - index set in local numbering
37690f02eecSBarry Smith 
37790f02eecSBarry Smith     Output Parameters:
37890f02eecSBarry Smith .   newis - index set in global numbering
37990f02eecSBarry Smith 
380a997ad1aSLois Curfman McInnes     Level: advanced
381a997ad1aSLois Curfman McInnes 
382273d9f13SBarry Smith     Concepts: mapping^local to global
3833acfe500SLois Curfman McInnes 
38490f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
385d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
38690f02eecSBarry Smith @*/
3877087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
38890f02eecSBarry Smith {
3896849ba73SBarry Smith   PetscErrorCode ierr;
390e24637baSBarry Smith   PetscInt       n,*idxout;
3915d0c19d7SBarry Smith   const PetscInt *idxin;
3923a40ed3dSBarry Smith 
3933a40ed3dSBarry Smith   PetscFunctionBegin;
3940700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3950700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3964482741eSBarry Smith   PetscValidPointer(newis,3);
39790f02eecSBarry Smith 
3983b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
39990f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
400785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
401e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
4023b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
403543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4043a40ed3dSBarry Smith   PetscFunctionReturn(0);
40590f02eecSBarry Smith }
40690f02eecSBarry Smith 
407afcb2eb5SJed Brown #undef __FUNCT__
408afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
409b89cb25eSSatish Balay /*@
4103acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4113acfe500SLois Curfman McInnes    and converts them to the global numbering.
41290f02eecSBarry Smith 
413b9cd556bSLois Curfman McInnes    Not collective
414b9cd556bSLois Curfman McInnes 
415bb25748dSBarry Smith    Input Parameters:
416b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
417bb25748dSBarry Smith .  N - number of integers
418b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
419bb25748dSBarry Smith 
420bb25748dSBarry Smith    Output Parameter:
421bb25748dSBarry Smith .  out - indices in global numbering
422bb25748dSBarry Smith 
423b9cd556bSLois Curfman McInnes    Notes:
424b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
425d4bb536fSBarry Smith 
426a997ad1aSLois Curfman McInnes    Level: advanced
427a997ad1aSLois Curfman McInnes 
42845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4290752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
430d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
431bb25748dSBarry Smith 
432273d9f13SBarry Smith     Concepts: mapping^local to global
433afcb2eb5SJed Brown @*/
434afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
435afcb2eb5SJed Brown {
436cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
43745b6f7e9SBarry Smith 
43845b6f7e9SBarry Smith   PetscFunctionBegin;
439cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
440cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
441cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
44245b6f7e9SBarry Smith   if (bs == 1) {
443cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
44445b6f7e9SBarry Smith     for (i=0; i<N; i++) {
44545b6f7e9SBarry Smith       if (in[i] < 0) {
44645b6f7e9SBarry Smith         out[i] = in[i];
44745b6f7e9SBarry Smith         continue;
44845b6f7e9SBarry Smith       }
449e24637baSBarry 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);
45045b6f7e9SBarry Smith       out[i] = idx[in[i]];
45145b6f7e9SBarry Smith     }
45245b6f7e9SBarry Smith   } else {
453cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
45445b6f7e9SBarry Smith     for (i=0; i<N; i++) {
45545b6f7e9SBarry Smith       if (in[i] < 0) {
45645b6f7e9SBarry Smith         out[i] = in[i];
45745b6f7e9SBarry Smith         continue;
45845b6f7e9SBarry Smith       }
459e24637baSBarry 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);
46045b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
46145b6f7e9SBarry Smith     }
46245b6f7e9SBarry Smith   }
46345b6f7e9SBarry Smith   PetscFunctionReturn(0);
46445b6f7e9SBarry Smith }
46545b6f7e9SBarry Smith 
46645b6f7e9SBarry Smith #undef __FUNCT__
46745b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
46845b6f7e9SBarry Smith /*@
4696006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
47045b6f7e9SBarry Smith 
47145b6f7e9SBarry Smith    Not collective
47245b6f7e9SBarry Smith 
47345b6f7e9SBarry Smith    Input Parameters:
47445b6f7e9SBarry Smith +  mapping - the local to global mapping context
47545b6f7e9SBarry Smith .  N - number of integers
4766006e8d2SBarry Smith -  in - input indices in local block numbering
47745b6f7e9SBarry Smith 
47845b6f7e9SBarry Smith    Output Parameter:
4796006e8d2SBarry Smith .  out - indices in global block numbering
48045b6f7e9SBarry Smith 
48145b6f7e9SBarry Smith    Notes:
48245b6f7e9SBarry Smith    The in and out array parameters may be identical.
48345b6f7e9SBarry Smith 
4846006e8d2SBarry Smith    Example:
4856006e8d2SBarry 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
4866006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
4876006e8d2SBarry Smith 
48845b6f7e9SBarry Smith    Level: advanced
48945b6f7e9SBarry Smith 
49045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
49145b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
49245b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
49345b6f7e9SBarry Smith 
49445b6f7e9SBarry Smith     Concepts: mapping^local to global
49545b6f7e9SBarry Smith @*/
49645b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
49745b6f7e9SBarry Smith {
498cbc1caf0SMatthew G. Knepley 
499cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
500cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
501cbc1caf0SMatthew G. Knepley   {
502afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
503afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
504d4bb536fSBarry Smith 
505afcb2eb5SJed Brown     for (i=0; i<N; i++) {
506afcb2eb5SJed Brown       if (in[i] < 0) {
507afcb2eb5SJed Brown         out[i] = in[i];
508afcb2eb5SJed Brown         continue;
509afcb2eb5SJed Brown       }
510e24637baSBarry 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);
511afcb2eb5SJed Brown       out[i] = idx[in[i]];
512afcb2eb5SJed Brown     }
513cbc1caf0SMatthew G. Knepley   }
514afcb2eb5SJed Brown   PetscFunctionReturn(0);
515afcb2eb5SJed Brown }
516d4bb536fSBarry Smith 
517d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
518d4bb536fSBarry Smith 
5194a2ae208SSatish Balay #undef __FUNCT__
5204a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
521d4bb536fSBarry Smith /*
522d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
523d4bb536fSBarry Smith */
5246849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
525d4bb536fSBarry Smith {
5266849ba73SBarry Smith   PetscErrorCode ierr;
52732dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
528d4bb536fSBarry Smith 
5293a40ed3dSBarry Smith   PetscFunctionBegin;
530d4bb536fSBarry Smith   end   = 0;
531ec268f7cSJed Brown   start = PETSC_MAX_INT;
532d4bb536fSBarry Smith 
533d4bb536fSBarry Smith   for (i=0; i<n; i++) {
534d4bb536fSBarry Smith     if (idx[i] < 0) continue;
535d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
536d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
537d4bb536fSBarry Smith   }
538d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
539d4bb536fSBarry Smith   mapping->globalstart = start;
540d4bb536fSBarry Smith   mapping->globalend   = end;
541d4bb536fSBarry Smith 
542854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
543b0a32e0cSBarry Smith   mapping->globals = globals;
544f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
545d4bb536fSBarry Smith   for (i=0; i<n; i++) {
546d4bb536fSBarry Smith     if (idx[i] < 0) continue;
547d4bb536fSBarry Smith     globals[idx[i] - start] = i;
548d4bb536fSBarry Smith   }
549d4bb536fSBarry Smith 
5503bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5513a40ed3dSBarry Smith   PetscFunctionReturn(0);
552d4bb536fSBarry Smith }
553d4bb536fSBarry Smith 
5544a2ae208SSatish Balay #undef __FUNCT__
5554a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
556d4bb536fSBarry Smith /*@
557a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
558a997ad1aSLois Curfman McInnes     specified with a global numbering.
559d4bb536fSBarry Smith 
560b9cd556bSLois Curfman McInnes     Not collective
561b9cd556bSLois Curfman McInnes 
562d4bb536fSBarry Smith     Input Parameters:
563b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
564d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
565d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
566d4bb536fSBarry Smith .   n - number of global indices to map
567b9cd556bSLois Curfman McInnes -   idx - global indices to map
568d4bb536fSBarry Smith 
569d4bb536fSBarry Smith     Output Parameters:
570b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
571b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
572e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5730298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
574e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
575e182c471SBarry Smith              a second time to set the values.
576d4bb536fSBarry Smith 
577b9cd556bSLois Curfman McInnes     Notes:
5780298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
579d4bb536fSBarry Smith 
5800f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5810f5bd95cSBarry Smith     array to compute these.
5820f5bd95cSBarry Smith 
583a997ad1aSLois Curfman McInnes     Level: advanced
584a997ad1aSLois Curfman McInnes 
58532fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
58632fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
58732fd6b96SBarry Smith 
588273d9f13SBarry Smith     Concepts: mapping^global to local
589d4bb536fSBarry Smith 
5909d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
591d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
592d4bb536fSBarry Smith @*/
5937087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
59432dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
595d4bb536fSBarry Smith {
5969d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
5979d90f715SBarry Smith   PetscErrorCode ierr;
5989d90f715SBarry Smith 
5999d90f715SBarry Smith   PetscFunctionBegin;
6009d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6019d90f715SBarry Smith   if (!mapping->globals) {
6029d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
6039d90f715SBarry Smith   }
6049d90f715SBarry Smith   globals = mapping->globals;
6059d90f715SBarry Smith   start   = mapping->globalstart;
6069d90f715SBarry Smith   end     = mapping->globalend;
6079d90f715SBarry Smith   bs      = mapping->bs;
6089d90f715SBarry Smith 
6099d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
6109d90f715SBarry Smith     if (idxout) {
6119d90f715SBarry Smith       for (i=0; i<n; i++) {
6129d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
6139d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
614663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
6159d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6169d90f715SBarry Smith       }
6179d90f715SBarry Smith     }
6189d90f715SBarry Smith     if (nout) *nout = n;
6199d90f715SBarry Smith   } else {
6209d90f715SBarry Smith     if (idxout) {
6219d90f715SBarry Smith       for (i=0; i<n; i++) {
6229d90f715SBarry Smith         if (idx[i] < 0) continue;
6239d90f715SBarry Smith         if (idx[i] < bs*start) continue;
624663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6259d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6269d90f715SBarry Smith         if (tmp < 0) continue;
6279d90f715SBarry Smith         idxout[nf++] = tmp;
6289d90f715SBarry Smith       }
6299d90f715SBarry Smith     } else {
6309d90f715SBarry Smith       for (i=0; i<n; i++) {
6319d90f715SBarry Smith         if (idx[i] < 0) continue;
6329d90f715SBarry Smith         if (idx[i] < bs*start) continue;
633663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6349d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6359d90f715SBarry Smith         if (tmp < 0) continue;
6369d90f715SBarry Smith         nf++;
6379d90f715SBarry Smith       }
6389d90f715SBarry Smith     }
6399d90f715SBarry Smith     if (nout) *nout = nf;
6409d90f715SBarry Smith   }
6419d90f715SBarry Smith   PetscFunctionReturn(0);
6429d90f715SBarry Smith }
6439d90f715SBarry Smith 
6449d90f715SBarry Smith #undef __FUNCT__
645d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
646d4fe737eSStefano Zampini /*@
647d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
648d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
649d4fe737eSStefano Zampini     context.
650d4fe737eSStefano Zampini 
651d4fe737eSStefano Zampini     Not collective
652d4fe737eSStefano Zampini 
653d4fe737eSStefano Zampini     Input Parameters:
654d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
655d4fe737eSStefano Zampini -   is - index set in global numbering
656d4fe737eSStefano Zampini 
657d4fe737eSStefano Zampini     Output Parameters:
658d4fe737eSStefano Zampini .   newis - index set in local numbering
659d4fe737eSStefano Zampini 
660d4fe737eSStefano Zampini     Level: advanced
661d4fe737eSStefano Zampini 
662d4fe737eSStefano Zampini     Concepts: mapping^local to global
663d4fe737eSStefano Zampini 
664d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
665d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
666d4fe737eSStefano Zampini @*/
667d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
668d4fe737eSStefano Zampini {
669d4fe737eSStefano Zampini   PetscErrorCode ierr;
670d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
671d4fe737eSStefano Zampini   const PetscInt *idxin;
672d4fe737eSStefano Zampini 
673d4fe737eSStefano Zampini   PetscFunctionBegin;
674d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
675d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
676d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
677d4fe737eSStefano Zampini 
678d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
679d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
680d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
681d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
682d4fe737eSStefano Zampini   } else {
683d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
684d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
685d4fe737eSStefano Zampini   }
686d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
687d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
688d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
689d4fe737eSStefano Zampini   PetscFunctionReturn(0);
690d4fe737eSStefano Zampini }
691d4fe737eSStefano Zampini 
692d4fe737eSStefano Zampini #undef __FUNCT__
6939d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
6949d90f715SBarry Smith /*@
6959d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
6969d90f715SBarry Smith     specified with a block global numbering.
6979d90f715SBarry Smith 
6989d90f715SBarry Smith     Not collective
6999d90f715SBarry Smith 
7009d90f715SBarry Smith     Input Parameters:
7019d90f715SBarry Smith +   mapping - mapping between local and global numbering
7029d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
7039d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
7049d90f715SBarry Smith .   n - number of global indices to map
7059d90f715SBarry Smith -   idx - global indices to map
7069d90f715SBarry Smith 
7079d90f715SBarry Smith     Output Parameters:
7089d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
7099d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
7109d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
7119d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
7129d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
7139d90f715SBarry Smith              a second time to set the values.
7149d90f715SBarry Smith 
7159d90f715SBarry Smith     Notes:
7169d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
7179d90f715SBarry Smith 
7189d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
7199d90f715SBarry Smith     array to compute these.
7209d90f715SBarry Smith 
7219d90f715SBarry Smith     Level: advanced
7229d90f715SBarry Smith 
7239d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
7249d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
7259d90f715SBarry Smith 
7269d90f715SBarry Smith     Concepts: mapping^global to local
7279d90f715SBarry Smith 
7289d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7299d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7309d90f715SBarry Smith @*/
7319d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7329d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7339d90f715SBarry Smith {
73432dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
7356849ba73SBarry Smith   PetscErrorCode ierr;
736d4bb536fSBarry Smith 
7373a40ed3dSBarry Smith   PetscFunctionBegin;
7380700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
739d4bb536fSBarry Smith   if (!mapping->globals) {
740d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
741d4bb536fSBarry Smith   }
742d4bb536fSBarry Smith   globals = mapping->globals;
743d4bb536fSBarry Smith   start   = mapping->globalstart;
744d4bb536fSBarry Smith   end     = mapping->globalend;
745d4bb536fSBarry Smith 
746d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
747d4bb536fSBarry Smith     if (idxout) {
748d4bb536fSBarry Smith       for (i=0; i<n; i++) {
749d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
750d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
751d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
752d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
753d4bb536fSBarry Smith       }
754d4bb536fSBarry Smith     }
755d4bb536fSBarry Smith     if (nout) *nout = n;
756d4bb536fSBarry Smith   } else {
757d4bb536fSBarry Smith     if (idxout) {
758d4bb536fSBarry Smith       for (i=0; i<n; i++) {
759d4bb536fSBarry Smith         if (idx[i] < 0) continue;
760d4bb536fSBarry Smith         if (idx[i] < start) continue;
761d4bb536fSBarry Smith         if (idx[i] > end) continue;
762d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
763d4bb536fSBarry Smith         if (tmp < 0) continue;
764d4bb536fSBarry Smith         idxout[nf++] = tmp;
765d4bb536fSBarry Smith       }
766d4bb536fSBarry Smith     } else {
767d4bb536fSBarry Smith       for (i=0; i<n; i++) {
768d4bb536fSBarry Smith         if (idx[i] < 0) continue;
769d4bb536fSBarry Smith         if (idx[i] < start) continue;
770d4bb536fSBarry Smith         if (idx[i] > end) continue;
771d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
772d4bb536fSBarry Smith         if (tmp < 0) continue;
773d4bb536fSBarry Smith         nf++;
774d4bb536fSBarry Smith       }
775d4bb536fSBarry Smith     }
776d4bb536fSBarry Smith     if (nout) *nout = nf;
777d4bb536fSBarry Smith   }
7783a40ed3dSBarry Smith   PetscFunctionReturn(0);
779d4bb536fSBarry Smith }
78090f02eecSBarry Smith 
7814a2ae208SSatish Balay #undef __FUNCT__
7826a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
78389d82c54SBarry Smith /*@C
7846a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
78589d82c54SBarry Smith      each index shared by more than one processor
78689d82c54SBarry Smith 
78789d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
78889d82c54SBarry Smith 
78989d82c54SBarry Smith     Input Parameters:
79089d82c54SBarry Smith .   mapping - the mapping from local to global indexing
79189d82c54SBarry Smith 
79289d82c54SBarry Smith     Output Parameter:
79389d82c54SBarry Smith +   nproc - number of processors that are connected to this one
79489d82c54SBarry Smith .   proc - neighboring processors
79507b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
7963463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
79789d82c54SBarry Smith 
79889d82c54SBarry Smith     Level: advanced
79989d82c54SBarry Smith 
800273d9f13SBarry Smith     Concepts: mapping^local to global
80189d82c54SBarry Smith 
8022cfcea29SBarry Smith     Fortran Usage:
8032cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
8042cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
8052cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
8062cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
8072cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
8082cfcea29SBarry Smith 
8092cfcea29SBarry Smith 
81007b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
81107b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
81289d82c54SBarry Smith @*/
8136a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
81489d82c54SBarry Smith {
8156849ba73SBarry Smith   PetscErrorCode ierr;
816268a049cSStefano Zampini 
817268a049cSStefano Zampini   PetscFunctionBegin;
818268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
819268a049cSStefano Zampini   if (mapping->info_cached) {
820268a049cSStefano Zampini     *nproc = mapping->info_nproc;
821268a049cSStefano Zampini     *procs = mapping->info_procs;
822268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
823268a049cSStefano Zampini     *indices = mapping->info_indices;
824268a049cSStefano Zampini   } else {
825268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
826268a049cSStefano Zampini   }
827268a049cSStefano Zampini   PetscFunctionReturn(0);
828268a049cSStefano Zampini }
829268a049cSStefano Zampini 
830268a049cSStefano Zampini #undef __FUNCT__
831268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
832268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
833268a049cSStefano Zampini {
834268a049cSStefano Zampini   PetscErrorCode ierr;
83597f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
83632dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
83732dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
83897f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
83932dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
84032dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
84189d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
84230dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
843ce94432eSBarry Smith   MPI_Comm       comm;
844ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
84589d82c54SBarry Smith 
84689d82c54SBarry Smith   PetscFunctionBegin;
847ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
84824cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
84924cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
85024cf384cSBarry Smith   if (size == 1) {
85124cf384cSBarry Smith     *nproc         = 0;
8520298fd71SBarry Smith     *procs         = NULL;
85395dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
8541e2105dcSBarry Smith     (*numprocs)[0] = 0;
85595dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
8560298fd71SBarry Smith     (*indices)[0]  = NULL;
857268a049cSStefano Zampini     /* save info for reuse */
858268a049cSStefano Zampini     mapping->info_nproc = *nproc;
859268a049cSStefano Zampini     mapping->info_procs = *procs;
860268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
861268a049cSStefano Zampini     mapping->info_indices = *indices;
862268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
86324cf384cSBarry Smith     PetscFunctionReturn(0);
86424cf384cSBarry Smith   }
86524cf384cSBarry Smith 
866c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
86707b52d57SBarry Smith 
8683677ff5aSBarry Smith   /*
8696a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
8703677ff5aSBarry Smith 
8713677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
8723677ff5aSBarry Smith            numbering, just for this routine.
8733677ff5aSBarry Smith 
8743677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
8753677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
8763677ff5aSBarry Smith 
8773677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
8783677ff5aSBarry Smith 
8793677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
8803677ff5aSBarry Smith            local subdomain
8813677ff5aSBarry Smith   */
88224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
88324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
88424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
88589d82c54SBarry Smith 
88689d82c54SBarry Smith   for (i=0; i<n; i++) {
88789d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
88889d82c54SBarry Smith   }
889b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
89078058e43SBarry Smith   Ng++;
89189d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
89289d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
893bc8ff85bSBarry Smith   scale  = Ng/size + 1;
894a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
895caba0dd0SBarry Smith   rstart = scale*rank;
89689d82c54SBarry Smith 
89789d82c54SBarry Smith   /* determine ownership ranges of global indices */
898785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
89932dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
90089d82c54SBarry Smith 
90189d82c54SBarry Smith   /* determine owners of each local node  */
902785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
90389d82c54SBarry Smith   for (i=0; i<n; i++) {
9043677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
90527c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
9063677ff5aSBarry Smith     owner[i]         = proc;
90727c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
90889d82c54SBarry Smith   }
90927c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
9107904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
91189d82c54SBarry Smith 
91289d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
91327c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9147904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
91589d82c54SBarry Smith 
91689d82c54SBarry Smith   /* post receives for owned rows */
917785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
918854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
91989d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
92032dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
92189d82c54SBarry Smith   }
92289d82c54SBarry Smith 
92389d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
924854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
925854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
92689d82c54SBarry Smith   starts[0] = 0;
927f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
92889d82c54SBarry Smith   for (i=0; i<n; i++) {
92989d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
93030dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
93189d82c54SBarry Smith   }
93289d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
93389d82c54SBarry Smith   starts[0] = 0;
934f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
93589d82c54SBarry Smith 
93689d82c54SBarry Smith   /* send the messages */
937854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
938854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
93989d82c54SBarry Smith   cnt = 0;
94089d82c54SBarry Smith   for (i=0; i<size; i++) {
94127c402fcSBarry Smith     if (nprocs[2*i]) {
94232dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
94330dcb7c9SBarry Smith       dest[cnt] = i;
94489d82c54SBarry Smith       cnt++;
94589d82c54SBarry Smith     }
94689d82c54SBarry Smith   }
94789d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
94889d82c54SBarry Smith 
94989d82c54SBarry Smith   /* wait on receives */
950854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
951854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
95289d82c54SBarry Smith   cnt  = nrecvs;
953854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
95432dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
95589d82c54SBarry Smith   while (cnt) {
95689d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
95789d82c54SBarry Smith     /* unpack receives into our local space */
95832dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
95989d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
96030dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
961caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
96230dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
96389d82c54SBarry Smith     cnt--;
96489d82c54SBarry Smith   }
96589d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
96689d82c54SBarry Smith 
96730dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
968bc8ff85bSBarry Smith   nowned  = 0;
969bc8ff85bSBarry Smith   nownedm = 0;
970bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
971bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
972bc8ff85bSBarry Smith   }
973bc8ff85bSBarry Smith 
974bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
975854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
976854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
977bc8ff85bSBarry Smith   starts[0] = 0;
978bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
979bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
980bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
981bc8ff85bSBarry Smith   }
982bc8ff85bSBarry Smith 
98330dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
984bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
985bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
98630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
987f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
988bc8ff85bSBarry Smith     }
989bc8ff85bSBarry Smith   }
990bc8ff85bSBarry Smith 
99107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
99230dcb7c9SBarry Smith     starts[0] = 0;
99330dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
99430dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
99530dcb7c9SBarry Smith       else starts[i] = starts[i-1];
99630dcb7c9SBarry Smith     }
99730dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
99830dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
9997904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
100030dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
10017904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
100230dcb7c9SBarry Smith         }
100330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
100430dcb7c9SBarry Smith       }
100530dcb7c9SBarry Smith     }
10060ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
100707b52d57SBarry Smith   } /* -----------------------------------  */
100830dcb7c9SBarry Smith 
10093677ff5aSBarry Smith   /* wait on original sends */
10103a96401aSBarry Smith   if (nsends) {
1011785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
10123a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10133a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10143a96401aSBarry Smith   }
101589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10163a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
10173677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
10183677ff5aSBarry Smith 
10193677ff5aSBarry Smith   /* pack messages to send back to local owners */
102030dcb7c9SBarry Smith   starts[0] = 0;
102130dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
102230dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
102330dcb7c9SBarry Smith     else starts[i] = starts[i-1];
102430dcb7c9SBarry Smith   }
102530dcb7c9SBarry Smith   nsends2 = nrecvs;
1026854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
102730dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
102830dcb7c9SBarry Smith     nprocs[i] = 1;
102930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
103030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1031f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
103230dcb7c9SBarry Smith     }
103330dcb7c9SBarry Smith   }
1034f6e5521dSKarl Rupp   nt = 0;
1035f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1036f6e5521dSKarl Rupp 
1037854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1038854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1039f6e5521dSKarl Rupp 
1040f6e5521dSKarl Rupp   starts2[0] = 0;
1041f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
104230dcb7c9SBarry Smith   /*
104330dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
104430dcb7c9SBarry Smith        (0) the number of nodes being sent back
104530dcb7c9SBarry Smith        (1) the local node number,
104630dcb7c9SBarry Smith        (2) the number of processors sharing it,
104730dcb7c9SBarry Smith        (3) the processors sharing it
104830dcb7c9SBarry Smith   */
104930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
105030dcb7c9SBarry Smith     cnt = 1;
105130dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
105230dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
105330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
105430dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
105530dcb7c9SBarry Smith         sends2[starts2[i]]++;
105630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
105730dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
105832dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
105930dcb7c9SBarry Smith         cnt += nownedsenders[node];
106030dcb7c9SBarry Smith       }
106130dcb7c9SBarry Smith     }
106230dcb7c9SBarry Smith   }
106330dcb7c9SBarry Smith 
106430dcb7c9SBarry Smith   /* receive the message lengths */
106530dcb7c9SBarry Smith   nrecvs2 = nsends;
1066854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1067854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1068854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
106930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1070d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
107130dcb7c9SBarry Smith   }
1072d44834fbSBarry Smith 
10738a8e0b3aSBarry Smith   /* send the message lengths */
10748a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
10758a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
10768a8e0b3aSBarry Smith   }
10778a8e0b3aSBarry Smith 
1078d44834fbSBarry Smith   /* wait on receives of lens */
10790c468ba9SBarry Smith   if (nrecvs2) {
1080785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1081d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1082d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10830c468ba9SBarry Smith   }
1084a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1085d44834fbSBarry Smith 
108630dcb7c9SBarry Smith   starts3[0] = 0;
1087d44834fbSBarry Smith   nt         = 0;
108830dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
108930dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1090d44834fbSBarry Smith     nt          += lens2[i];
109130dcb7c9SBarry Smith   }
109276466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1093d44834fbSBarry Smith 
1094854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1095854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
109652b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
109732dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
109830dcb7c9SBarry Smith   }
109930dcb7c9SBarry Smith 
110030dcb7c9SBarry Smith   /* send the messages */
1101854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
110230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
110332dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
110430dcb7c9SBarry Smith   }
110530dcb7c9SBarry Smith 
110630dcb7c9SBarry Smith   /* wait on receives */
11070c468ba9SBarry Smith   if (nrecvs2) {
1108785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
110930dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
111030dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11110c468ba9SBarry Smith   }
111230dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
111330dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
111430dcb7c9SBarry Smith 
111507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
111630dcb7c9SBarry Smith     cnt = 0;
111730dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
111830dcb7c9SBarry Smith       nt = recvs2[cnt++];
111930dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
11207904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
112130dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
11227904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
112330dcb7c9SBarry Smith         }
112430dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
112530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
112630dcb7c9SBarry Smith       }
112730dcb7c9SBarry Smith     }
11280ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
112907b52d57SBarry Smith   } /* -----------------------------------  */
113030dcb7c9SBarry Smith 
113130dcb7c9SBarry Smith   /* count number subdomains for each local node */
1132785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
113332dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
113430dcb7c9SBarry Smith   cnt  = 0;
113530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
113630dcb7c9SBarry Smith     nt = recvs2[cnt++];
113730dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1138f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
113930dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
114030dcb7c9SBarry Smith     }
114130dcb7c9SBarry Smith   }
114230dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
114330dcb7c9SBarry Smith   *nproc    = nt;
1144854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1145854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1146854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
11470298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1148785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
114930dcb7c9SBarry Smith   cnt  = 0;
115030dcb7c9SBarry Smith   for (i=0; i<size; i++) {
115130dcb7c9SBarry Smith     if (nprocs[i] > 0) {
115230dcb7c9SBarry Smith       bprocs[i]        = cnt;
115330dcb7c9SBarry Smith       (*procs)[cnt]    = i;
115430dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1155785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
115630dcb7c9SBarry Smith       cnt++;
115730dcb7c9SBarry Smith     }
115830dcb7c9SBarry Smith   }
115930dcb7c9SBarry Smith 
116030dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
116132dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
116230dcb7c9SBarry Smith   cnt  = 0;
116330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
116430dcb7c9SBarry Smith     nt = recvs2[cnt++];
116530dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1166f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
116730dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
116830dcb7c9SBarry Smith     }
116930dcb7c9SBarry Smith   }
117030dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
117107b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
117230dcb7c9SBarry Smith 
117307b52d57SBarry Smith   /* sort the node indexing by their global numbers */
117407b52d57SBarry Smith   nt = *nproc;
117507b52d57SBarry Smith   for (i=0; i<nt; i++) {
1176854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1177f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
117807b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
117907b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
118007b52d57SBarry Smith   }
118107b52d57SBarry Smith 
118207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
118330dcb7c9SBarry Smith     nt = *nproc;
118430dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
11857904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
118630dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
11877904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
118830dcb7c9SBarry Smith       }
118930dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
119030dcb7c9SBarry Smith     }
11910ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
119207b52d57SBarry Smith   } /* -----------------------------------  */
119330dcb7c9SBarry Smith 
119430dcb7c9SBarry Smith   /* wait on sends */
119530dcb7c9SBarry Smith   if (nsends2) {
1196785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
119730dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
119830dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
119930dcb7c9SBarry Smith   }
120030dcb7c9SBarry Smith 
120130dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
120230dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
120330dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12043677ff5aSBarry Smith 
1205bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1206bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1207bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
120830dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
120930dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
121089d82c54SBarry Smith 
121189d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
121297f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
121389d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
12143a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
121530dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
121624cf384cSBarry Smith 
121724cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
121824cf384cSBarry Smith   first_procs    = (*procs)[0];
121924cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
122024cf384cSBarry Smith   first_indices  = (*indices)[0];
122124cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
122224cf384cSBarry Smith     if ((*procs)[i] == rank) {
122324cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
122424cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
122524cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
122624cf384cSBarry Smith       (*procs)[i]    = first_procs;
122724cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
122824cf384cSBarry Smith       (*indices)[i]  = first_indices;
122924cf384cSBarry Smith       break;
123024cf384cSBarry Smith     }
123124cf384cSBarry Smith   }
1232268a049cSStefano Zampini 
1233268a049cSStefano Zampini   /* save info for reuse */
1234268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1235268a049cSStefano Zampini   mapping->info_procs = *procs;
1236268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1237268a049cSStefano Zampini   mapping->info_indices = *indices;
1238268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
123989d82c54SBarry Smith   PetscFunctionReturn(0);
124089d82c54SBarry Smith }
124189d82c54SBarry Smith 
12424a2ae208SSatish Balay #undef __FUNCT__
12436a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
12446a818285SBarry Smith /*@C
12456a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
12466a818285SBarry Smith 
12476a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12486a818285SBarry Smith 
12496a818285SBarry Smith     Input Parameters:
12506a818285SBarry Smith .   mapping - the mapping from local to global indexing
12516a818285SBarry Smith 
12526a818285SBarry Smith     Output Parameter:
12536a818285SBarry Smith +   nproc - number of processors that are connected to this one
12546a818285SBarry Smith .   proc - neighboring processors
12556a818285SBarry Smith .   numproc - number of indices for each processor
12566a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12576a818285SBarry Smith 
12586a818285SBarry Smith     Level: advanced
12596a818285SBarry Smith 
12606a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12616a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
12626a818285SBarry Smith @*/
12636a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12646a818285SBarry Smith {
12656a818285SBarry Smith   PetscErrorCode ierr;
12666a818285SBarry Smith 
12676a818285SBarry Smith   PetscFunctionBegin;
1268cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1269268a049cSStefano Zampini   if (mapping->info_free) {
12706a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
12716a818285SBarry Smith     if (*indices) {
1272268a049cSStefano Zampini       PetscInt i;
1273268a049cSStefano Zampini 
12746a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
12756a818285SBarry Smith       for (i=1; i<*nproc; i++) {
12766a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
12776a818285SBarry Smith       }
12786a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
12796a818285SBarry Smith     }
1280268a049cSStefano Zampini   }
1281268a049cSStefano Zampini   *nproc = 0;
1282268a049cSStefano Zampini   *procs = NULL;
1283268a049cSStefano Zampini   *numprocs = NULL;
1284268a049cSStefano Zampini   *indices = NULL;
12856a818285SBarry Smith   PetscFunctionReturn(0);
12866a818285SBarry Smith }
12876a818285SBarry Smith 
12886a818285SBarry Smith #undef __FUNCT__
12896a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
12906a818285SBarry Smith /*@C
12916a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
12926a818285SBarry Smith      each index shared by more than one processor
12936a818285SBarry Smith 
12946a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12956a818285SBarry Smith 
12966a818285SBarry Smith     Input Parameters:
12976a818285SBarry Smith .   mapping - the mapping from local to global indexing
12986a818285SBarry Smith 
12996a818285SBarry Smith     Output Parameter:
13006a818285SBarry Smith +   nproc - number of processors that are connected to this one
13016a818285SBarry Smith .   proc - neighboring processors
13026a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
13036a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
13046a818285SBarry Smith 
13056a818285SBarry Smith     Level: advanced
13066a818285SBarry Smith 
13076a818285SBarry Smith     Concepts: mapping^local to global
13086a818285SBarry Smith 
13096a818285SBarry Smith     Fortran Usage:
13106a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
13116a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
13126a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
13136a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
13146a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
13156a818285SBarry Smith 
13166a818285SBarry Smith 
13176a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13186a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
13196a818285SBarry Smith @*/
13206a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13216a818285SBarry Smith {
13226a818285SBarry Smith   PetscErrorCode ierr;
1323268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
13246a818285SBarry Smith 
13256a818285SBarry Smith   PetscFunctionBegin;
13266a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1327268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1328268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1329732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1330268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13316a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1332268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1333268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13346a818285SBarry Smith         for (k=0; k<bs; k++) {
13356a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13366a818285SBarry Smith         }
13376a818285SBarry Smith       }
1338268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13396a818285SBarry Smith     }
1340268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1341268a049cSStefano Zampini   } else {
1342268a049cSStefano Zampini     *numprocs = bnumprocs;
1343268a049cSStefano Zampini     *indices  = bindices;
13446a818285SBarry Smith   }
13456a818285SBarry Smith   PetscFunctionReturn(0);
13466a818285SBarry Smith }
13476a818285SBarry Smith 
13486a818285SBarry Smith #undef __FUNCT__
13494a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
135007b52d57SBarry Smith /*@C
135107b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
135289d82c54SBarry Smith 
135307b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
135407b52d57SBarry Smith 
135507b52d57SBarry Smith     Input Parameters:
135607b52d57SBarry Smith .   mapping - the mapping from local to global indexing
135707b52d57SBarry Smith 
135807b52d57SBarry Smith     Output Parameter:
135907b52d57SBarry Smith +   nproc - number of processors that are connected to this one
136007b52d57SBarry Smith .   proc - neighboring processors
136107b52d57SBarry Smith .   numproc - number of indices for each processor
136207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
136307b52d57SBarry Smith 
136407b52d57SBarry Smith     Level: advanced
136507b52d57SBarry Smith 
136607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
136707b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
136807b52d57SBarry Smith @*/
13697087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
137007b52d57SBarry Smith {
13716849ba73SBarry Smith   PetscErrorCode ierr;
137207b52d57SBarry Smith 
137307b52d57SBarry Smith   PetscFunctionBegin;
13746a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
137507b52d57SBarry Smith   PetscFunctionReturn(0);
137607b52d57SBarry Smith }
137786994e45SJed Brown 
137886994e45SJed Brown #undef __FUNCT__
137986994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
138086994e45SJed Brown /*@C
1381107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
138286994e45SJed Brown 
138386994e45SJed Brown    Not Collective
138486994e45SJed Brown 
138586994e45SJed Brown    Input Arguments:
138686994e45SJed Brown . ltog - local to global mapping
138786994e45SJed Brown 
138886994e45SJed Brown    Output Arguments:
1389565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
139086994e45SJed Brown 
139186994e45SJed Brown    Level: advanced
139286994e45SJed Brown 
1393107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1394107e9a97SBarry Smith 
1395107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
139686994e45SJed Brown @*/
13977087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
139886994e45SJed Brown {
139986994e45SJed Brown   PetscFunctionBegin;
140086994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
140186994e45SJed Brown   PetscValidPointer(array,2);
140245b6f7e9SBarry Smith   if (ltog->bs == 1) {
140386994e45SJed Brown     *array = ltog->indices;
140445b6f7e9SBarry Smith   } else {
140545b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
140645b6f7e9SBarry Smith     const PetscInt *ii;
140745b6f7e9SBarry Smith     PetscErrorCode ierr;
140845b6f7e9SBarry Smith 
140945b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
141045b6f7e9SBarry Smith     *array = jj;
141145b6f7e9SBarry Smith     k    = 0;
141245b6f7e9SBarry Smith     ii   = ltog->indices;
141345b6f7e9SBarry Smith     for (i=0; i<n; i++)
141445b6f7e9SBarry Smith       for (j=0; j<bs; j++)
141545b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
141645b6f7e9SBarry Smith   }
141786994e45SJed Brown   PetscFunctionReturn(0);
141886994e45SJed Brown }
141986994e45SJed Brown 
142086994e45SJed Brown #undef __FUNCT__
142186994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
142286994e45SJed Brown /*@C
1423193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
142486994e45SJed Brown 
142586994e45SJed Brown    Not Collective
142686994e45SJed Brown 
142786994e45SJed Brown    Input Arguments:
142886994e45SJed Brown + ltog - local to global mapping
142986994e45SJed Brown - array - array of indices
143086994e45SJed Brown 
143186994e45SJed Brown    Level: advanced
143286994e45SJed Brown 
143386994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
143486994e45SJed Brown @*/
14357087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
143686994e45SJed Brown {
143786994e45SJed Brown   PetscFunctionBegin;
143886994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
143986994e45SJed Brown   PetscValidPointer(array,2);
144045b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
144145b6f7e9SBarry Smith 
144245b6f7e9SBarry Smith   if (ltog->bs > 1) {
144345b6f7e9SBarry Smith     PetscErrorCode ierr;
144445b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
144545b6f7e9SBarry Smith   }
144645b6f7e9SBarry Smith   PetscFunctionReturn(0);
144745b6f7e9SBarry Smith }
144845b6f7e9SBarry Smith 
144945b6f7e9SBarry Smith #undef __FUNCT__
145045b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
145145b6f7e9SBarry Smith /*@C
145245b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
145345b6f7e9SBarry Smith 
145445b6f7e9SBarry Smith    Not Collective
145545b6f7e9SBarry Smith 
145645b6f7e9SBarry Smith    Input Arguments:
145745b6f7e9SBarry Smith . ltog - local to global mapping
145845b6f7e9SBarry Smith 
145945b6f7e9SBarry Smith    Output Arguments:
146045b6f7e9SBarry Smith . array - array of indices
146145b6f7e9SBarry Smith 
146245b6f7e9SBarry Smith    Level: advanced
146345b6f7e9SBarry Smith 
146445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
146545b6f7e9SBarry Smith @*/
146645b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
146745b6f7e9SBarry Smith {
146845b6f7e9SBarry Smith   PetscFunctionBegin;
146945b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
147045b6f7e9SBarry Smith   PetscValidPointer(array,2);
147145b6f7e9SBarry Smith   *array = ltog->indices;
147245b6f7e9SBarry Smith   PetscFunctionReturn(0);
147345b6f7e9SBarry Smith }
147445b6f7e9SBarry Smith 
147545b6f7e9SBarry Smith #undef __FUNCT__
147645b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
147745b6f7e9SBarry Smith /*@C
147845b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
147945b6f7e9SBarry Smith 
148045b6f7e9SBarry Smith    Not Collective
148145b6f7e9SBarry Smith 
148245b6f7e9SBarry Smith    Input Arguments:
148345b6f7e9SBarry Smith + ltog - local to global mapping
148445b6f7e9SBarry Smith - array - array of indices
148545b6f7e9SBarry Smith 
148645b6f7e9SBarry Smith    Level: advanced
148745b6f7e9SBarry Smith 
148845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
148945b6f7e9SBarry Smith @*/
149045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
149145b6f7e9SBarry Smith {
149245b6f7e9SBarry Smith   PetscFunctionBegin;
149345b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
149445b6f7e9SBarry Smith   PetscValidPointer(array,2);
149586994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
14960298fd71SBarry Smith   *array = NULL;
149786994e45SJed Brown   PetscFunctionReturn(0);
149886994e45SJed Brown }
1499f7efa3c7SJed Brown 
1500f7efa3c7SJed Brown #undef __FUNCT__
1501f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1502f7efa3c7SJed Brown /*@C
1503f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1504f7efa3c7SJed Brown 
1505f7efa3c7SJed Brown    Not Collective
1506f7efa3c7SJed Brown 
1507f7efa3c7SJed Brown    Input Arguments:
1508f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1509f7efa3c7SJed Brown . n - number of mappings to concatenate
1510f7efa3c7SJed Brown - ltogs - local to global mappings
1511f7efa3c7SJed Brown 
1512f7efa3c7SJed Brown    Output Arguments:
1513f7efa3c7SJed Brown . ltogcat - new mapping
1514f7efa3c7SJed Brown 
15159d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
15169d90f715SBarry Smith 
15179d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
15189d90f715SBarry Smith 
1519f7efa3c7SJed Brown    Level: advanced
1520f7efa3c7SJed Brown 
1521f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1522f7efa3c7SJed Brown @*/
1523f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1524f7efa3c7SJed Brown {
1525f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1526f7efa3c7SJed Brown   PetscErrorCode ierr;
1527f7efa3c7SJed Brown 
1528f7efa3c7SJed Brown   PetscFunctionBegin;
1529f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1530f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1531f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1532f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1533f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1534f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1535f7efa3c7SJed Brown     cnt += m;
1536f7efa3c7SJed Brown   }
1537785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1538f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1539f7efa3c7SJed Brown     const PetscInt *subidx;
1540f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1541f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1542f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1543f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1544f7efa3c7SJed Brown     cnt += m;
1545f7efa3c7SJed Brown   }
1546f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1547f7efa3c7SJed Brown   PetscFunctionReturn(0);
1548f7efa3c7SJed Brown }
154904a59952SBarry Smith 
155004a59952SBarry Smith 
1551