xref: /petsc/src/vec/is/utils/isltog.c (revision 6849ba73f22fecb8f92ef896a42e4e8bd4cd6965)
12362add9SBarry Smith 
2e090d566SSatish Balay #include "petscsys.h"   /*I "petscsys.h" I*/
3e090d566SSatish Balay #include "src/vec/is/isimpl.h"    /*I "petscis.h"  I*/
42362add9SBarry Smith 
5dfbe8321SBarry Smith EXTERN PetscErrorCode VecInitializePackage(char *);
6*6849ba73SBarry Smith PetscCookie IS_LTOGM_COOKIE = -1;
78e58c17dSMatthew Knepley 
84a2ae208SSatish Balay #undef __FUNCT__
94a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
103b9aefa3SBarry Smith /*@C
113b9aefa3SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping.
123b9aefa3SBarry Smith 
133b9aefa3SBarry Smith     Not Collective
143b9aefa3SBarry Smith 
153b9aefa3SBarry Smith     Input Parameter:
163b9aefa3SBarry Smith .   ltog - local to global mapping
173b9aefa3SBarry Smith 
183b9aefa3SBarry Smith     Output Parameter:
193b9aefa3SBarry Smith .   n - the number of entries in the local mapping
203b9aefa3SBarry Smith 
213b9aefa3SBarry Smith     Level: advanced
223b9aefa3SBarry Smith 
23273d9f13SBarry Smith     Concepts: mapping^local to global
243b9aefa3SBarry Smith 
253b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
263b9aefa3SBarry Smith @*/
27dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,int *n)
283b9aefa3SBarry Smith {
293b9aefa3SBarry Smith   PetscFunctionBegin;
304482741eSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE,1);
314482741eSBarry Smith   PetscValidIntPointer(n,2);
323b9aefa3SBarry Smith   *n = mapping->n;
333b9aefa3SBarry Smith   PetscFunctionReturn(0);
343b9aefa3SBarry Smith }
353b9aefa3SBarry Smith 
364a2ae208SSatish Balay #undef __FUNCT__
374a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
385a5d4f66SBarry Smith /*@C
395a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
405a5d4f66SBarry Smith 
41b9cd556bSLois Curfman McInnes     Not Collective
42b9cd556bSLois Curfman McInnes 
435a5d4f66SBarry Smith     Input Parameters:
443b9aefa3SBarry Smith +   ltog - local to global mapping
453b9aefa3SBarry Smith -   viewer - viewer
465a5d4f66SBarry Smith 
47a997ad1aSLois Curfman McInnes     Level: advanced
48a997ad1aSLois Curfman McInnes 
49273d9f13SBarry Smith     Concepts: mapping^local to global
505a5d4f66SBarry Smith 
515a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
525a5d4f66SBarry Smith @*/
53dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
545a5d4f66SBarry Smith {
55*6849ba73SBarry Smith   int        i,rank;
5632077d6dSBarry Smith   PetscTruth iascii;
57*6849ba73SBarry Smith   PetscErrorCode ierr;
585a5d4f66SBarry Smith 
595a5d4f66SBarry Smith   PetscFunctionBegin;
604482741eSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE,1);
61b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
624482741eSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
635a5d4f66SBarry Smith 
64f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
6532077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
6632077d6dSBarry Smith   if (iascii) {
675a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
68b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
696831982aSBarry Smith     }
70b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
716831982aSBarry Smith   } else {
72958c9bccSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
735a5d4f66SBarry Smith   }
745a5d4f66SBarry Smith 
755a5d4f66SBarry Smith   PetscFunctionReturn(0);
765a5d4f66SBarry Smith }
775a5d4f66SBarry Smith 
784a2ae208SSatish Balay #undef __FUNCT__
794a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
802bdab257SBarry Smith /*@C
812bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
822bdab257SBarry Smith     ordering and a global parallel ordering.
832bdab257SBarry Smith 
840f5bd95cSBarry Smith     Not collective
85b9cd556bSLois Curfman McInnes 
86a997ad1aSLois Curfman McInnes     Input Parameter:
872bdab257SBarry Smith .   is - index set containing the global numbers for each local
882bdab257SBarry Smith 
89a997ad1aSLois Curfman McInnes     Output Parameter:
902bdab257SBarry Smith .   mapping - new mapping data structure
912bdab257SBarry Smith 
92a997ad1aSLois Curfman McInnes     Level: advanced
93a997ad1aSLois Curfman McInnes 
94273d9f13SBarry Smith     Concepts: mapping^local to global
952bdab257SBarry Smith 
962bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
972bdab257SBarry Smith @*/
98dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
992bdab257SBarry Smith {
100*6849ba73SBarry Smith   PetscErrorCode ierr;
101*6849ba73SBarry Smith   int      n,*indices;
1022bdab257SBarry Smith   MPI_Comm comm;
1033a40ed3dSBarry Smith 
1043a40ed3dSBarry Smith   PetscFunctionBegin;
1054482741eSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE,1);
1064482741eSBarry Smith   PetscValidPointer(mapping,2);
1072bdab257SBarry Smith 
1082bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1093b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1102bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1112bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
1122bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1132bdab257SBarry Smith 
1143a40ed3dSBarry Smith   PetscFunctionReturn(0);
1152bdab257SBarry Smith }
1165a5d4f66SBarry Smith 
117b46b645bSBarry Smith 
1184a2ae208SSatish Balay #undef __FUNCT__
1194a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
120dd7157adSSatish Balay /*@C
12190f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
12290f02eecSBarry Smith     ordering and a global parallel ordering.
1232362add9SBarry Smith 
12489d82c54SBarry Smith     Not Collective, but communicator may have more than one process
125b9cd556bSLois Curfman McInnes 
1262362add9SBarry Smith     Input Parameters:
12789d82c54SBarry Smith +   comm - MPI communicator
12890f02eecSBarry Smith .   n - the number of local elements
129b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
1302362add9SBarry Smith 
131a997ad1aSLois Curfman McInnes     Output Parameter:
13290f02eecSBarry Smith .   mapping - new mapping data structure
1332362add9SBarry Smith 
134a997ad1aSLois Curfman McInnes     Level: advanced
135a997ad1aSLois Curfman McInnes 
136273d9f13SBarry Smith     Concepts: mapping^local to global
1372362add9SBarry Smith 
138b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreateNC()
1392362add9SBarry Smith @*/
140dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1412362add9SBarry Smith {
142*6849ba73SBarry Smith   PetscErrorCode ierr;
143*6849ba73SBarry Smith   int *in;
144b46b645bSBarry Smith 
145b46b645bSBarry Smith   PetscFunctionBegin;
1464482741eSBarry Smith   PetscValidIntPointer(indices,3);
1474482741eSBarry Smith   PetscValidPointer(mapping,4);
148b46b645bSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&in);CHKERRQ(ierr);
149b46b645bSBarry Smith   ierr = PetscMemcpy(in,indices,n*sizeof(int));CHKERRQ(ierr);
150b46b645bSBarry Smith   ierr = ISLocalToGlobalMappingCreateNC(cm,n,in,mapping);CHKERRQ(ierr);
151b46b645bSBarry Smith   PetscFunctionReturn(0);
152b46b645bSBarry Smith }
153b46b645bSBarry Smith 
154b46b645bSBarry Smith #undef __FUNCT__
155b46b645bSBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingCreateNC"
156b46b645bSBarry Smith /*@C
157b46b645bSBarry Smith     ISLocalToGlobalMappingCreateNC - Creates a mapping between a local (0 to n)
158b46b645bSBarry Smith     ordering and a global parallel ordering.
159b46b645bSBarry Smith 
160b46b645bSBarry Smith     Not Collective, but communicator may have more than one process
161b46b645bSBarry Smith 
162b46b645bSBarry Smith     Input Parameters:
163b46b645bSBarry Smith +   comm - MPI communicator
164b46b645bSBarry Smith .   n - the number of local elements
165b46b645bSBarry Smith -   indices - the global index for each local element
166b46b645bSBarry Smith 
167b46b645bSBarry Smith     Output Parameter:
168b46b645bSBarry Smith .   mapping - new mapping data structure
169b46b645bSBarry Smith 
170b46b645bSBarry Smith     Level: developer
171b46b645bSBarry Smith 
172b46b645bSBarry Smith     Notes: Does not copy the indices, just keeps the pointer to the indices. The ISLocalToGlobalMappingDestroy()
173b46b645bSBarry Smith     will free the space so it must be obtained with PetscMalloc() and it must not be freed elsewhere.
174b46b645bSBarry Smith 
175b46b645bSBarry Smith     Concepts: mapping^local to global
176b46b645bSBarry Smith 
177b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate()
178b46b645bSBarry Smith @*/
179dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingCreateNC(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
180b46b645bSBarry Smith {
181dfbe8321SBarry Smith   PetscErrorCode ierr;
18223f7533aSBarry Smith 
1833a40ed3dSBarry Smith   PetscFunctionBegin;
1844482741eSBarry Smith   PetscValidIntPointer(indices,3);
1854482741eSBarry Smith   PetscValidPointer(mapping,4);
1868e58c17dSMatthew Knepley   *mapping = PETSC_NULL;
1878e58c17dSMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
18823f7533aSBarry Smith   ierr = VecInitializePackage(PETSC_NULL);CHKERRQ(ierr);
1898e58c17dSMatthew Knepley #endif
19023f7533aSBarry Smith   if (IS_LTOGM_COOKIE == -1) {
19123f7533aSBarry Smith     ierr = PetscLogClassRegister(&IS_LTOGM_COOKIE,"IS Local to global mapping");CHKERRQ(ierr);
19223f7533aSBarry Smith   }
1932362add9SBarry Smith 
1943f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1953f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
196b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
197b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
198d4bb536fSBarry Smith 
199d4bb536fSBarry Smith   (*mapping)->n       = n;
200b46b645bSBarry Smith   (*mapping)->indices = (int*)indices;
201d4bb536fSBarry Smith 
202d4bb536fSBarry Smith   /*
203d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
204d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
205d4bb536fSBarry Smith   */
206d4bb536fSBarry Smith   (*mapping)->globals = 0;
2073a40ed3dSBarry Smith   PetscFunctionReturn(0);
2082362add9SBarry Smith }
2092362add9SBarry Smith 
2104a2ae208SSatish Balay #undef __FUNCT__
2114a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
212323b833fSBarry Smith /*@C
213323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
214323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
215323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
216323b833fSBarry Smith 
217323b833fSBarry Smith     Not Collective, but communicator may have more than one process
218323b833fSBarry Smith 
219323b833fSBarry Smith     Input Parameters:
220323b833fSBarry Smith +    inmap - original point-wise mapping
221323b833fSBarry Smith -    bs - block size
222323b833fSBarry Smith 
223323b833fSBarry Smith     Output Parameter:
224323b833fSBarry Smith .   outmap - block based mapping
225323b833fSBarry Smith 
226323b833fSBarry Smith     Level: advanced
227323b833fSBarry Smith 
228323b833fSBarry Smith     Concepts: mapping^local to global
229323b833fSBarry Smith 
230323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
231323b833fSBarry Smith @*/
232dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
233323b833fSBarry Smith {
234*6849ba73SBarry Smith   PetscErrorCode ierr;
235*6849ba73SBarry Smith   int            *ii,i,n;
236323b833fSBarry Smith 
237323b833fSBarry Smith   PetscFunctionBegin;
238323b833fSBarry Smith   if (bs > 1) {
239323b833fSBarry Smith     n    = inmap->n/bs;
240323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
241323b833fSBarry Smith     for (i=0; i<n; i++) {
242b8ee7809SBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
243323b833fSBarry Smith     }
244323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
245323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
246323b833fSBarry Smith   } else {
247323b833fSBarry Smith     *outmap = inmap;
248323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
249323b833fSBarry Smith   }
250323b833fSBarry Smith   PetscFunctionReturn(0);
251323b833fSBarry Smith }
252323b833fSBarry Smith 
2534a2ae208SSatish Balay #undef __FUNCT__
2544a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
25590f02eecSBarry Smith /*@
25690f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
25790f02eecSBarry Smith    ordering and a global parallel ordering.
25890f02eecSBarry Smith 
2590f5bd95cSBarry Smith    Note Collective
260b9cd556bSLois Curfman McInnes 
26190f02eecSBarry Smith    Input Parameters:
26290f02eecSBarry Smith .  mapping - mapping data structure
26390f02eecSBarry Smith 
264a997ad1aSLois Curfman McInnes    Level: advanced
265a997ad1aSLois Curfman McInnes 
2663acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
26790f02eecSBarry Smith @*/
268dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
26990f02eecSBarry Smith {
270dfbe8321SBarry Smith   PetscErrorCode ierr;
2713a40ed3dSBarry Smith   PetscFunctionBegin;
2724482741eSBarry Smith   PetscValidPointer(mapping,1);
2733a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
27485614651SBarry Smith   if (mapping->refct < 0) {
275634064b4SBarry Smith     SETERRQ(PETSC_ERR_PLIB,"Mapping already destroyed");
27685614651SBarry Smith   }
27790f02eecSBarry Smith 
278606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
279606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
280b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
281d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2823a40ed3dSBarry Smith   PetscFunctionReturn(0);
28390f02eecSBarry Smith }
28490f02eecSBarry Smith 
2854a2ae208SSatish Balay #undef __FUNCT__
2864a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
28790f02eecSBarry Smith /*@
2883acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2893acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2903acfe500SLois Curfman McInnes     context.
29190f02eecSBarry Smith 
292b9cd556bSLois Curfman McInnes     Not collective
293b9cd556bSLois Curfman McInnes 
29490f02eecSBarry Smith     Input Parameters:
295b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
296b9cd556bSLois Curfman McInnes -   is - index set in local numbering
29790f02eecSBarry Smith 
29890f02eecSBarry Smith     Output Parameters:
29990f02eecSBarry Smith .   newis - index set in global numbering
30090f02eecSBarry Smith 
301a997ad1aSLois Curfman McInnes     Level: advanced
302a997ad1aSLois Curfman McInnes 
303273d9f13SBarry Smith     Concepts: mapping^local to global
3043acfe500SLois Curfman McInnes 
30590f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
306d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
30790f02eecSBarry Smith @*/
308dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
30990f02eecSBarry Smith {
310*6849ba73SBarry Smith   PetscErrorCode ierr;
311*6849ba73SBarry Smith   int            n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
3123a40ed3dSBarry Smith 
3133a40ed3dSBarry Smith   PetscFunctionBegin;
3144482741eSBarry Smith   PetscValidPointer(mapping,1);
3154482741eSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE,2);
3164482741eSBarry Smith   PetscValidPointer(newis,3);
31790f02eecSBarry Smith 
3183b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
31990f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
32090f02eecSBarry Smith   idxmap = mapping->indices;
32190f02eecSBarry Smith 
322b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
32390f02eecSBarry Smith   for (i=0; i<n; i++) {
324590ac198SBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax-1,i);
32590f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
32690f02eecSBarry Smith   }
3273b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
328029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
329606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
3303a40ed3dSBarry Smith   PetscFunctionReturn(0);
33190f02eecSBarry Smith }
33290f02eecSBarry Smith 
33389d82c54SBarry Smith /*MC
3343acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3353acfe500SLois Curfman McInnes    and converts them to the global numbering.
33690f02eecSBarry Smith 
337b9cd556bSLois Curfman McInnes    Not collective
338b9cd556bSLois Curfman McInnes 
339bb25748dSBarry Smith    Input Parameters:
340b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
341bb25748dSBarry Smith .  N - number of integers
342b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
343bb25748dSBarry Smith 
344bb25748dSBarry Smith    Output Parameter:
345bb25748dSBarry Smith .  out - indices in global numbering
346bb25748dSBarry Smith 
3473b9aefa3SBarry Smith    Synopsis:
348216e7ba4SBarry Smith    int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
3493b9aefa3SBarry Smith 
350b9cd556bSLois Curfman McInnes    Notes:
351b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
352d4bb536fSBarry Smith 
353a997ad1aSLois Curfman McInnes    Level: advanced
354a997ad1aSLois Curfman McInnes 
355bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3560752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
357d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
358bb25748dSBarry Smith 
359273d9f13SBarry Smith     Concepts: mapping^local to global
360d4bb536fSBarry Smith 
36189d82c54SBarry Smith M*/
362d4bb536fSBarry Smith 
363d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
364d4bb536fSBarry Smith 
3654a2ae208SSatish Balay #undef __FUNCT__
3664a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
367d4bb536fSBarry Smith /*
368d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
369d4bb536fSBarry Smith */
370*6849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
371d4bb536fSBarry Smith {
372*6849ba73SBarry Smith   PetscErrorCode ierr;
373*6849ba73SBarry Smith   int            i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
374d4bb536fSBarry Smith 
3753a40ed3dSBarry Smith   PetscFunctionBegin;
376d4bb536fSBarry Smith   end   = 0;
377d4bb536fSBarry Smith   start = 100000000;
378d4bb536fSBarry Smith 
379d4bb536fSBarry Smith   for (i=0; i<n; i++) {
380d4bb536fSBarry Smith     if (idx[i] < 0) continue;
381d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
382d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
383d4bb536fSBarry Smith   }
384d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
385d4bb536fSBarry Smith   mapping->globalstart = start;
386d4bb536fSBarry Smith   mapping->globalend   = end;
387d4bb536fSBarry Smith 
388b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
389b0a32e0cSBarry Smith   mapping->globals = globals;
390d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
391d4bb536fSBarry Smith     globals[i] = -1;
392d4bb536fSBarry Smith   }
393d4bb536fSBarry Smith   for (i=0; i<n; i++) {
394d4bb536fSBarry Smith     if (idx[i] < 0) continue;
395d4bb536fSBarry Smith     globals[idx[i] - start] = i;
396d4bb536fSBarry Smith   }
397d4bb536fSBarry Smith 
398b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3993a40ed3dSBarry Smith   PetscFunctionReturn(0);
400d4bb536fSBarry Smith }
401d4bb536fSBarry Smith 
4024a2ae208SSatish Balay #undef __FUNCT__
4034a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
404d4bb536fSBarry Smith /*@
405a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
406a997ad1aSLois Curfman McInnes     specified with a global numbering.
407d4bb536fSBarry Smith 
408b9cd556bSLois Curfman McInnes     Not collective
409b9cd556bSLois Curfman McInnes 
410d4bb536fSBarry Smith     Input Parameters:
411b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
412d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
413d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
414d4bb536fSBarry Smith .   n - number of global indices to map
415b9cd556bSLois Curfman McInnes -   idx - global indices to map
416d4bb536fSBarry Smith 
417d4bb536fSBarry Smith     Output Parameters:
418b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
419b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
420e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
421e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
422e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
423e182c471SBarry Smith              a second time to set the values.
424d4bb536fSBarry Smith 
425b9cd556bSLois Curfman McInnes     Notes:
426b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
427d4bb536fSBarry Smith 
4280f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
4290f5bd95cSBarry Smith     array to compute these.
4300f5bd95cSBarry Smith 
431a997ad1aSLois Curfman McInnes     Level: advanced
432a997ad1aSLois Curfman McInnes 
433273d9f13SBarry Smith     Concepts: mapping^global to local
434d4bb536fSBarry Smith 
435d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
436d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
437d4bb536fSBarry Smith @*/
438dfbe8321SBarry Smith PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
439987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
440d4bb536fSBarry Smith {
441*6849ba73SBarry Smith   int i,*globals,nf = 0,tmp,start,end;
442*6849ba73SBarry Smith   PetscErrorCode ierr;
443d4bb536fSBarry Smith 
4443a40ed3dSBarry Smith   PetscFunctionBegin;
445d4bb536fSBarry Smith   if (!mapping->globals) {
446d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
447d4bb536fSBarry Smith   }
448d4bb536fSBarry Smith   globals = mapping->globals;
449d4bb536fSBarry Smith   start   = mapping->globalstart;
450d4bb536fSBarry Smith   end     = mapping->globalend;
451d4bb536fSBarry Smith 
452d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
453d4bb536fSBarry Smith     if (idxout) {
454d4bb536fSBarry Smith       for (i=0; i<n; i++) {
455d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
456d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
457d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
458d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
459d4bb536fSBarry Smith       }
460d4bb536fSBarry Smith     }
461d4bb536fSBarry Smith     if (nout) *nout = n;
462d4bb536fSBarry Smith   } else {
463d4bb536fSBarry Smith     if (idxout) {
464d4bb536fSBarry Smith       for (i=0; i<n; i++) {
465d4bb536fSBarry Smith         if (idx[i] < 0) continue;
466d4bb536fSBarry Smith         if (idx[i] < start) continue;
467d4bb536fSBarry Smith         if (idx[i] > end) continue;
468d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
469d4bb536fSBarry Smith         if (tmp < 0) continue;
470d4bb536fSBarry Smith         idxout[nf++] = tmp;
471d4bb536fSBarry Smith       }
472d4bb536fSBarry Smith     } else {
473d4bb536fSBarry Smith       for (i=0; i<n; i++) {
474d4bb536fSBarry Smith         if (idx[i] < 0) continue;
475d4bb536fSBarry Smith         if (idx[i] < start) continue;
476d4bb536fSBarry Smith         if (idx[i] > end) continue;
477d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
478d4bb536fSBarry Smith         if (tmp < 0) continue;
479d4bb536fSBarry Smith         nf++;
480d4bb536fSBarry Smith       }
481d4bb536fSBarry Smith     }
482d4bb536fSBarry Smith     if (nout) *nout = nf;
483d4bb536fSBarry Smith   }
484d4bb536fSBarry Smith 
4853a40ed3dSBarry Smith   PetscFunctionReturn(0);
486d4bb536fSBarry Smith }
48790f02eecSBarry Smith 
4884a2ae208SSatish Balay #undef __FUNCT__
4894a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
49089d82c54SBarry Smith /*@C
49189d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
49289d82c54SBarry Smith      each index shared by more than one processor
49389d82c54SBarry Smith 
49489d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
49589d82c54SBarry Smith 
49689d82c54SBarry Smith     Input Parameters:
49789d82c54SBarry Smith .   mapping - the mapping from local to global indexing
49889d82c54SBarry Smith 
49989d82c54SBarry Smith     Output Parameter:
50089d82c54SBarry Smith +   nproc - number of processors that are connected to this one
50189d82c54SBarry Smith .   proc - neighboring processors
50207b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
50307b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
50489d82c54SBarry Smith 
50589d82c54SBarry Smith     Level: advanced
50689d82c54SBarry Smith 
507273d9f13SBarry Smith     Concepts: mapping^local to global
50889d82c54SBarry Smith 
50907b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
51007b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
51189d82c54SBarry Smith @*/
512dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int *procs[],int *numprocs[],int **indices[])
51389d82c54SBarry Smith {
514*6849ba73SBarry Smith   PetscErrorCode ierr;
515*6849ba73SBarry Smith   int         i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
51627c402fcSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
51724cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
51807b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
51924cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
52089d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
52130dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
52289d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
52307b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
52489d82c54SBarry Smith 
52589d82c54SBarry Smith   PetscFunctionBegin;
52624cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
52724cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
52824cf384cSBarry Smith   if (size == 1) {
52924cf384cSBarry Smith     *nproc         = 0;
53024cf384cSBarry Smith     *procs         = PETSC_NULL;
531b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
5321e2105dcSBarry Smith     (*numprocs)[0] = 0;
533b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
5341e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
53524cf384cSBarry Smith     PetscFunctionReturn(0);
53624cf384cSBarry Smith   }
53724cf384cSBarry Smith 
538b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
53907b52d57SBarry Smith 
5403677ff5aSBarry Smith   /*
5413677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
5423677ff5aSBarry Smith 
5433677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
5443677ff5aSBarry Smith            numbering, just for this routine.
5453677ff5aSBarry Smith 
5463677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
5473677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
5483677ff5aSBarry Smith 
5493677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
5503677ff5aSBarry Smith 
5513677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
5523677ff5aSBarry Smith            local subdomain
5533677ff5aSBarry Smith   */
55424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
55524cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
55624cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
55789d82c54SBarry Smith 
55889d82c54SBarry Smith   for (i=0; i<n; i++) {
55989d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
56089d82c54SBarry Smith   }
56189d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
56278058e43SBarry Smith   Ng++;
56389d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
56489d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
565bc8ff85bSBarry Smith   scale  = Ng/size + 1;
566a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
567caba0dd0SBarry Smith   rstart = scale*rank;
56889d82c54SBarry Smith 
56989d82c54SBarry Smith   /* determine ownership ranges of global indices */
570b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5712880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
57289d82c54SBarry Smith 
57389d82c54SBarry Smith   /* determine owners of each local node  */
574b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
57589d82c54SBarry Smith   for (i=0; i<n; i++) {
5763677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
57727c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
5783677ff5aSBarry Smith     owner[i]         = proc;
57927c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
58089d82c54SBarry Smith   }
58127c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
582b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
58389d82c54SBarry Smith 
58489d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
58527c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
586b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
58789d82c54SBarry Smith 
58889d82c54SBarry Smith   /* post receives for owned rows */
589b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
590b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
59189d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
59224cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
59389d82c54SBarry Smith   }
59489d82c54SBarry Smith 
59589d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
596b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
597b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
59889d82c54SBarry Smith   starts[0]  = 0;
59927c402fcSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];}
60089d82c54SBarry Smith   for (i=0; i<n; i++) {
60189d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
60230dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
60389d82c54SBarry Smith   }
60489d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
60589d82c54SBarry Smith   starts[0]  = 0;
60627c402fcSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];}
60789d82c54SBarry Smith 
60889d82c54SBarry Smith   /* send the messages */
609b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
610b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
61189d82c54SBarry Smith   cnt = 0;
61289d82c54SBarry Smith   for (i=0; i<size; i++) {
61327c402fcSBarry Smith     if (nprocs[2*i]) {
61427c402fcSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
61530dcb7c9SBarry Smith       dest[cnt] = i;
61689d82c54SBarry Smith       cnt++;
61789d82c54SBarry Smith     }
61889d82c54SBarry Smith   }
61989d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
62089d82c54SBarry Smith 
62189d82c54SBarry Smith   /* wait on receives */
622b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
62389d82c54SBarry Smith   len  = source + nrecvs;
62489d82c54SBarry Smith   cnt  = nrecvs;
625b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
626caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
62789d82c54SBarry Smith   while (cnt) {
62889d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
62989d82c54SBarry Smith     /* unpack receives into our local space */
63089d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
63189d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
63230dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
633caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
63430dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
63589d82c54SBarry Smith     cnt--;
63689d82c54SBarry Smith   }
63789d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
63889d82c54SBarry Smith 
63930dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
640bc8ff85bSBarry Smith   nowned  = 0;
641bc8ff85bSBarry Smith   nownedm = 0;
642bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
643bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
644bc8ff85bSBarry Smith   }
645bc8ff85bSBarry Smith 
646bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
647b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
648b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
649bc8ff85bSBarry Smith   starts[0] = 0;
650bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
651bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
652bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
653bc8ff85bSBarry Smith   }
654bc8ff85bSBarry Smith 
65530dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
656bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
657bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
65830dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
659bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
660bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
661bc8ff85bSBarry Smith       }
662bc8ff85bSBarry Smith     }
663bc8ff85bSBarry Smith   }
664bc8ff85bSBarry Smith 
66507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
66630dcb7c9SBarry Smith     starts[0]    = 0;
66730dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
66830dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
66930dcb7c9SBarry Smith       else starts[i] = starts[i-1];
67030dcb7c9SBarry Smith     }
67130dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
67230dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
67330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
67430dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
67530dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
67630dcb7c9SBarry Smith         }
67730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
67830dcb7c9SBarry Smith       }
67930dcb7c9SBarry Smith     }
68030dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
68107b52d57SBarry Smith   }/* -----------------------------------  */
68230dcb7c9SBarry Smith 
6833677ff5aSBarry Smith   /* wait on original sends */
6843a96401aSBarry Smith   if (nsends) {
685b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6863a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6873a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6883a96401aSBarry Smith   }
68989d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6903a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6913677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6923677ff5aSBarry Smith 
6933677ff5aSBarry Smith   /* pack messages to send back to local owners */
69430dcb7c9SBarry Smith   starts[0]    = 0;
69530dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
69630dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
69730dcb7c9SBarry Smith     else starts[i] = starts[i-1];
69830dcb7c9SBarry Smith   }
69930dcb7c9SBarry Smith   nsends2 = nrecvs;
700b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
70130dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
70230dcb7c9SBarry Smith     nprocs[i] = 1;
70330dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
70430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
70530dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
70630dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
70730dcb7c9SBarry Smith       }
70830dcb7c9SBarry Smith     }
70930dcb7c9SBarry Smith   }
71030dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
711b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
712b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
71330dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
71430dcb7c9SBarry Smith   /*
71530dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
71630dcb7c9SBarry Smith        (0) the number of nodes being sent back
71730dcb7c9SBarry Smith        (1) the local node number,
71830dcb7c9SBarry Smith        (2) the number of processors sharing it,
71930dcb7c9SBarry Smith        (3) the processors sharing it
72030dcb7c9SBarry Smith   */
72130dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
72230dcb7c9SBarry Smith     cnt = 1;
72330dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
72430dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
72530dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
72630dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
72730dcb7c9SBarry Smith         sends2[starts2[i]]++;
72830dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
72930dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
73030dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
73130dcb7c9SBarry Smith         cnt += nownedsenders[node];
73230dcb7c9SBarry Smith       }
73330dcb7c9SBarry Smith     }
73430dcb7c9SBarry Smith   }
73530dcb7c9SBarry Smith 
73630dcb7c9SBarry Smith   /* send the message lengths */
73730dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
73824cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
73930dcb7c9SBarry Smith   }
74030dcb7c9SBarry Smith 
74130dcb7c9SBarry Smith   /* receive the message lengths */
74230dcb7c9SBarry Smith   nrecvs2 = nsends;
743b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
744b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
74530dcb7c9SBarry Smith   nt      = 0;
74630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
74724cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
74830dcb7c9SBarry Smith     nt   += lens2[i];
74930dcb7c9SBarry Smith   }
75030dcb7c9SBarry Smith   starts3[0] = 0;
75130dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
75230dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
75330dcb7c9SBarry Smith   }
754b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
755b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
75652b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
75724cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
75830dcb7c9SBarry Smith   }
75930dcb7c9SBarry Smith 
76030dcb7c9SBarry Smith   /* send the messages */
761b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
76230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
76324cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
76430dcb7c9SBarry Smith   }
76530dcb7c9SBarry Smith 
76630dcb7c9SBarry Smith   /* wait on receives */
767b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
76830dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
76930dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
77030dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
77130dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
77230dcb7c9SBarry Smith 
77307b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
77430dcb7c9SBarry Smith     cnt = 0;
77530dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
77630dcb7c9SBarry Smith       nt = recvs2[cnt++];
77730dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
77830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
77930dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
78030dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
78130dcb7c9SBarry Smith         }
78230dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
78330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
78430dcb7c9SBarry Smith       }
78530dcb7c9SBarry Smith     }
78630dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
78707b52d57SBarry Smith   } /* -----------------------------------  */
78830dcb7c9SBarry Smith 
78930dcb7c9SBarry Smith   /* count number subdomains for each local node */
790b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
79130dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
79230dcb7c9SBarry Smith   cnt  = 0;
79330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
79430dcb7c9SBarry Smith     nt = recvs2[cnt++];
79530dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
79630dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
79730dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
79830dcb7c9SBarry Smith       }
79930dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
80030dcb7c9SBarry Smith     }
80130dcb7c9SBarry Smith   }
80230dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
80330dcb7c9SBarry Smith   *nproc    = nt;
804b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
805b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
806b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
807b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
80830dcb7c9SBarry Smith   cnt       = 0;
80930dcb7c9SBarry Smith   for (i=0; i<size; i++) {
81030dcb7c9SBarry Smith     if (nprocs[i] > 0) {
81130dcb7c9SBarry Smith       bprocs[i]        = cnt;
81230dcb7c9SBarry Smith       (*procs)[cnt]    = i;
81330dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
814b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
81530dcb7c9SBarry Smith       cnt++;
81630dcb7c9SBarry Smith     }
81730dcb7c9SBarry Smith   }
81830dcb7c9SBarry Smith 
81930dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
82030dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
82130dcb7c9SBarry Smith   cnt  = 0;
82230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
82330dcb7c9SBarry Smith     nt = recvs2[cnt++];
82430dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
82530dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
82630dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
82730dcb7c9SBarry Smith       }
82830dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
82930dcb7c9SBarry Smith     }
83030dcb7c9SBarry Smith   }
83130dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
83207b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
83330dcb7c9SBarry Smith 
83407b52d57SBarry Smith   /* sort the node indexing by their global numbers */
83507b52d57SBarry Smith   nt = *nproc;
83607b52d57SBarry Smith   for (i=0; i<nt; i++) {
837b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
83807b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
83907b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
84007b52d57SBarry Smith     }
84107b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
84207b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
84307b52d57SBarry Smith   }
84407b52d57SBarry Smith 
84507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
84630dcb7c9SBarry Smith     nt = *nproc;
84730dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
84830dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
84930dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
85030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
85130dcb7c9SBarry Smith       }
85230dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
85330dcb7c9SBarry Smith     }
85430dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
85507b52d57SBarry Smith   } /* -----------------------------------  */
85630dcb7c9SBarry Smith 
85730dcb7c9SBarry Smith   /* wait on sends */
85830dcb7c9SBarry Smith   if (nsends2) {
859b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
86030dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
86130dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
86230dcb7c9SBarry Smith   }
86330dcb7c9SBarry Smith 
86430dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
86530dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
86630dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8673677ff5aSBarry Smith 
868bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
869bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
870bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
87130dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
87230dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
87389d82c54SBarry Smith 
87489d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
87589d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8763a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
87730dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
87824cf384cSBarry Smith 
87924cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
88024cf384cSBarry Smith   first_procs    = (*procs)[0];
88124cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
88224cf384cSBarry Smith   first_indices  = (*indices)[0];
88324cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
88424cf384cSBarry Smith     if ((*procs)[i] == rank) {
88524cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
88624cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
88724cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
88824cf384cSBarry Smith       (*procs)[i]    = first_procs;
88924cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
89024cf384cSBarry Smith       (*indices)[i]  = first_indices;
89124cf384cSBarry Smith       break;
89224cf384cSBarry Smith     }
89324cf384cSBarry Smith   }
89424cf384cSBarry Smith 
89589d82c54SBarry Smith   PetscFunctionReturn(0);
89689d82c54SBarry Smith }
89789d82c54SBarry Smith 
8984a2ae208SSatish Balay #undef __FUNCT__
8994a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
90007b52d57SBarry Smith /*@C
90107b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
90289d82c54SBarry Smith 
90307b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
90407b52d57SBarry Smith 
90507b52d57SBarry Smith     Input Parameters:
90607b52d57SBarry Smith .   mapping - the mapping from local to global indexing
90707b52d57SBarry Smith 
90807b52d57SBarry Smith     Output Parameter:
90907b52d57SBarry Smith +   nproc - number of processors that are connected to this one
91007b52d57SBarry Smith .   proc - neighboring processors
91107b52d57SBarry Smith .   numproc - number of indices for each processor
91207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
91307b52d57SBarry Smith 
91407b52d57SBarry Smith     Level: advanced
91507b52d57SBarry Smith 
91607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
91707b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
91807b52d57SBarry Smith @*/
919dfbe8321SBarry Smith PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int *procs[],int *numprocs[],int **indices[])
92007b52d57SBarry Smith {
921*6849ba73SBarry Smith   PetscErrorCode ierr;
922*6849ba73SBarry Smith   int i;
92307b52d57SBarry Smith 
92407b52d57SBarry Smith   PetscFunctionBegin;
92500ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
92600ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
92700ff320aSBarry Smith   if (*indices) {
92800ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
92900ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
93024cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
93107b52d57SBarry Smith     }
93207b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
93324cf384cSBarry Smith   }
93407b52d57SBarry Smith   PetscFunctionReturn(0);
93507b52d57SBarry Smith }
93689d82c54SBarry Smith 
937bc8ff85bSBarry Smith 
938bc8ff85bSBarry Smith 
939bc8ff85bSBarry Smith 
940bc8ff85bSBarry Smith 
941bc8ff85bSBarry Smith 
942bc8ff85bSBarry Smith 
943bc8ff85bSBarry Smith 
944bc8ff85bSBarry Smith 
945bc8ff85bSBarry Smith 
946bc8ff85bSBarry Smith 
947bc8ff85bSBarry Smith 
948bc8ff85bSBarry Smith 
949bc8ff85bSBarry Smith 
950bc8ff85bSBarry Smith 
951bc8ff85bSBarry Smith 
952bc8ff85bSBarry Smith 
95324cf384cSBarry Smith 
954