xref: /petsc/src/vec/is/utils/isltog.c (revision 634064b45b5c838063ae82f97ffb7e99245dcdb5)
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 
58e58c17dSMatthew Knepley EXTERN int VecInitializePackage(char *);
623f7533aSBarry Smith int 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 @*/
273b9aefa3SBarry Smith int 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 @*/
53b0a32e0cSBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
545a5d4f66SBarry Smith {
55f1af5d2fSBarry Smith   int        i,ierr,rank;
5632077d6dSBarry Smith   PetscTruth iascii;
575a5d4f66SBarry Smith 
585a5d4f66SBarry Smith   PetscFunctionBegin;
594482741eSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE,1);
60b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
614482741eSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
625a5d4f66SBarry Smith 
63f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
6432077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
6532077d6dSBarry Smith   if (iascii) {
665a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
67b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
686831982aSBarry Smith     }
69b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
706831982aSBarry Smith   } else {
71958c9bccSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
725a5d4f66SBarry Smith   }
735a5d4f66SBarry Smith 
745a5d4f66SBarry Smith   PetscFunctionReturn(0);
755a5d4f66SBarry Smith }
765a5d4f66SBarry Smith 
774a2ae208SSatish Balay #undef __FUNCT__
784a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
792bdab257SBarry Smith /*@C
802bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
812bdab257SBarry Smith     ordering and a global parallel ordering.
822bdab257SBarry Smith 
830f5bd95cSBarry Smith     Not collective
84b9cd556bSLois Curfman McInnes 
85a997ad1aSLois Curfman McInnes     Input Parameter:
862bdab257SBarry Smith .   is - index set containing the global numbers for each local
872bdab257SBarry Smith 
88a997ad1aSLois Curfman McInnes     Output Parameter:
892bdab257SBarry Smith .   mapping - new mapping data structure
902bdab257SBarry Smith 
91a997ad1aSLois Curfman McInnes     Level: advanced
92a997ad1aSLois Curfman McInnes 
93273d9f13SBarry Smith     Concepts: mapping^local to global
942bdab257SBarry Smith 
952bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
962bdab257SBarry Smith @*/
972bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
982bdab257SBarry Smith {
992bdab257SBarry Smith   int      n,*indices,ierr;
1002bdab257SBarry Smith   MPI_Comm comm;
1013a40ed3dSBarry Smith 
1023a40ed3dSBarry Smith   PetscFunctionBegin;
1034482741eSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE,1);
1044482741eSBarry Smith   PetscValidPointer(mapping,2);
1052bdab257SBarry Smith 
1062bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1073b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1082bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1092bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
1102bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1112bdab257SBarry Smith 
1123a40ed3dSBarry Smith   PetscFunctionReturn(0);
1132bdab257SBarry Smith }
1145a5d4f66SBarry Smith 
115b46b645bSBarry Smith 
1164a2ae208SSatish Balay #undef __FUNCT__
1174a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
118dd7157adSSatish Balay /*@C
11990f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
12090f02eecSBarry Smith     ordering and a global parallel ordering.
1212362add9SBarry Smith 
12289d82c54SBarry Smith     Not Collective, but communicator may have more than one process
123b9cd556bSLois Curfman McInnes 
1242362add9SBarry Smith     Input Parameters:
12589d82c54SBarry Smith +   comm - MPI communicator
12690f02eecSBarry Smith .   n - the number of local elements
127b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
1282362add9SBarry Smith 
129a997ad1aSLois Curfman McInnes     Output Parameter:
13090f02eecSBarry Smith .   mapping - new mapping data structure
1312362add9SBarry Smith 
132a997ad1aSLois Curfman McInnes     Level: advanced
133a997ad1aSLois Curfman McInnes 
134273d9f13SBarry Smith     Concepts: mapping^local to global
1352362add9SBarry Smith 
136b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreateNC()
1372362add9SBarry Smith @*/
138987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1392362add9SBarry Smith {
140b46b645bSBarry Smith   int *in,ierr;
141b46b645bSBarry Smith 
142b46b645bSBarry Smith   PetscFunctionBegin;
1434482741eSBarry Smith   PetscValidIntPointer(indices,3);
1444482741eSBarry Smith   PetscValidPointer(mapping,4);
145b46b645bSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&in);CHKERRQ(ierr);
146b46b645bSBarry Smith   ierr = PetscMemcpy(in,indices,n*sizeof(int));CHKERRQ(ierr);
147b46b645bSBarry Smith   ierr = ISLocalToGlobalMappingCreateNC(cm,n,in,mapping);CHKERRQ(ierr);
148b46b645bSBarry Smith   PetscFunctionReturn(0);
149b46b645bSBarry Smith }
150b46b645bSBarry Smith 
151b46b645bSBarry Smith #undef __FUNCT__
152b46b645bSBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingCreateNC"
153b46b645bSBarry Smith /*@C
154b46b645bSBarry Smith     ISLocalToGlobalMappingCreateNC - Creates a mapping between a local (0 to n)
155b46b645bSBarry Smith     ordering and a global parallel ordering.
156b46b645bSBarry Smith 
157b46b645bSBarry Smith     Not Collective, but communicator may have more than one process
158b46b645bSBarry Smith 
159b46b645bSBarry Smith     Input Parameters:
160b46b645bSBarry Smith +   comm - MPI communicator
161b46b645bSBarry Smith .   n - the number of local elements
162b46b645bSBarry Smith -   indices - the global index for each local element
163b46b645bSBarry Smith 
164b46b645bSBarry Smith     Output Parameter:
165b46b645bSBarry Smith .   mapping - new mapping data structure
166b46b645bSBarry Smith 
167b46b645bSBarry Smith     Level: developer
168b46b645bSBarry Smith 
169b46b645bSBarry Smith     Notes: Does not copy the indices, just keeps the pointer to the indices. The ISLocalToGlobalMappingDestroy()
170b46b645bSBarry Smith     will free the space so it must be obtained with PetscMalloc() and it must not be freed elsewhere.
171b46b645bSBarry Smith 
172b46b645bSBarry Smith     Concepts: mapping^local to global
173b46b645bSBarry Smith 
174b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate()
175b46b645bSBarry Smith @*/
176b46b645bSBarry Smith int ISLocalToGlobalMappingCreateNC(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
177b46b645bSBarry Smith {
17823f7533aSBarry Smith   int ierr;
17923f7533aSBarry Smith 
1803a40ed3dSBarry Smith   PetscFunctionBegin;
1814482741eSBarry Smith   PetscValidIntPointer(indices,3);
1824482741eSBarry Smith   PetscValidPointer(mapping,4);
1838e58c17dSMatthew Knepley   *mapping = PETSC_NULL;
1848e58c17dSMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
18523f7533aSBarry Smith   ierr = VecInitializePackage(PETSC_NULL);CHKERRQ(ierr);
1868e58c17dSMatthew Knepley #endif
18723f7533aSBarry Smith   if (IS_LTOGM_COOKIE == -1) {
18823f7533aSBarry Smith     ierr = PetscLogClassRegister(&IS_LTOGM_COOKIE,"IS Local to global mapping");CHKERRQ(ierr);
18923f7533aSBarry Smith   }
1902362add9SBarry Smith 
1913f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1923f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
193b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
194b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
195d4bb536fSBarry Smith 
196d4bb536fSBarry Smith   (*mapping)->n       = n;
197b46b645bSBarry Smith   (*mapping)->indices = (int*)indices;
198d4bb536fSBarry Smith 
199d4bb536fSBarry Smith   /*
200d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
201d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
202d4bb536fSBarry Smith   */
203d4bb536fSBarry Smith   (*mapping)->globals = 0;
2043a40ed3dSBarry Smith   PetscFunctionReturn(0);
2052362add9SBarry Smith }
2062362add9SBarry Smith 
2074a2ae208SSatish Balay #undef __FUNCT__
2084a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
209323b833fSBarry Smith /*@C
210323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
211323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
212323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
213323b833fSBarry Smith 
214323b833fSBarry Smith     Not Collective, but communicator may have more than one process
215323b833fSBarry Smith 
216323b833fSBarry Smith     Input Parameters:
217323b833fSBarry Smith +    inmap - original point-wise mapping
218323b833fSBarry Smith -    bs - block size
219323b833fSBarry Smith 
220323b833fSBarry Smith     Output Parameter:
221323b833fSBarry Smith .   outmap - block based mapping
222323b833fSBarry Smith 
223323b833fSBarry Smith     Level: advanced
224323b833fSBarry Smith 
225323b833fSBarry Smith     Concepts: mapping^local to global
226323b833fSBarry Smith 
227323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
228323b833fSBarry Smith @*/
229323b833fSBarry Smith int ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
230323b833fSBarry Smith {
231323b833fSBarry Smith   int ierr,*ii,i,n;
232323b833fSBarry Smith 
233323b833fSBarry Smith   PetscFunctionBegin;
234323b833fSBarry Smith 
235323b833fSBarry Smith   if (bs > 1) {
236323b833fSBarry Smith     n    = inmap->n/bs;
237323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
238323b833fSBarry Smith     for (i=0; i<n; i++) {
239b8ee7809SBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
240323b833fSBarry Smith     }
241323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
242323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
243323b833fSBarry Smith   } else {
244323b833fSBarry Smith     *outmap = inmap;
245323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
246323b833fSBarry Smith   }
247323b833fSBarry Smith   PetscFunctionReturn(0);
248323b833fSBarry Smith }
249323b833fSBarry Smith 
2504a2ae208SSatish Balay #undef __FUNCT__
2514a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
25290f02eecSBarry Smith /*@
25390f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
25490f02eecSBarry Smith    ordering and a global parallel ordering.
25590f02eecSBarry Smith 
2560f5bd95cSBarry Smith    Note Collective
257b9cd556bSLois Curfman McInnes 
25890f02eecSBarry Smith    Input Parameters:
25990f02eecSBarry Smith .  mapping - mapping data structure
26090f02eecSBarry Smith 
261a997ad1aSLois Curfman McInnes    Level: advanced
262a997ad1aSLois Curfman McInnes 
2633acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
26490f02eecSBarry Smith @*/
26590f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
26690f02eecSBarry Smith {
267606d414cSSatish Balay   int ierr;
2683a40ed3dSBarry Smith   PetscFunctionBegin;
2694482741eSBarry Smith   PetscValidPointer(mapping,1);
2703a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
27185614651SBarry Smith   if (mapping->refct < 0) {
272*634064b4SBarry Smith     SETERRQ(PETSC_ERR_PLIB,"Mapping already destroyed");
27385614651SBarry Smith   }
27490f02eecSBarry Smith 
275606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
276606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
277b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
278d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2793a40ed3dSBarry Smith   PetscFunctionReturn(0);
28090f02eecSBarry Smith }
28190f02eecSBarry Smith 
2824a2ae208SSatish Balay #undef __FUNCT__
2834a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
28490f02eecSBarry Smith /*@
2853acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2863acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2873acfe500SLois Curfman McInnes     context.
28890f02eecSBarry Smith 
289b9cd556bSLois Curfman McInnes     Not collective
290b9cd556bSLois Curfman McInnes 
29190f02eecSBarry Smith     Input Parameters:
292b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
293b9cd556bSLois Curfman McInnes -   is - index set in local numbering
29490f02eecSBarry Smith 
29590f02eecSBarry Smith     Output Parameters:
29690f02eecSBarry Smith .   newis - index set in global numbering
29790f02eecSBarry Smith 
298a997ad1aSLois Curfman McInnes     Level: advanced
299a997ad1aSLois Curfman McInnes 
300273d9f13SBarry Smith     Concepts: mapping^local to global
3013acfe500SLois Curfman McInnes 
30290f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
303d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
30490f02eecSBarry Smith @*/
30590f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
30690f02eecSBarry Smith {
3073b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
3083a40ed3dSBarry Smith 
3093a40ed3dSBarry Smith   PetscFunctionBegin;
3104482741eSBarry Smith   PetscValidPointer(mapping,1);
3114482741eSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE,2);
3124482741eSBarry Smith   PetscValidPointer(newis,3);
31390f02eecSBarry Smith 
3143b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
31590f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
31690f02eecSBarry Smith   idxmap = mapping->indices;
31790f02eecSBarry Smith 
318b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
31990f02eecSBarry Smith   for (i=0; i<n; i++) {
320590ac198SBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax-1,i);
32190f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
32290f02eecSBarry Smith   }
3233b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
324029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
325606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
3263a40ed3dSBarry Smith   PetscFunctionReturn(0);
32790f02eecSBarry Smith }
32890f02eecSBarry Smith 
32989d82c54SBarry Smith /*MC
3303acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3313acfe500SLois Curfman McInnes    and converts them to the global numbering.
33290f02eecSBarry Smith 
333b9cd556bSLois Curfman McInnes    Not collective
334b9cd556bSLois Curfman McInnes 
335bb25748dSBarry Smith    Input Parameters:
336b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
337bb25748dSBarry Smith .  N - number of integers
338b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
339bb25748dSBarry Smith 
340bb25748dSBarry Smith    Output Parameter:
341bb25748dSBarry Smith .  out - indices in global numbering
342bb25748dSBarry Smith 
3433b9aefa3SBarry Smith    Synopsis:
344216e7ba4SBarry Smith    int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
3453b9aefa3SBarry Smith 
346b9cd556bSLois Curfman McInnes    Notes:
347b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
348d4bb536fSBarry Smith 
349a997ad1aSLois Curfman McInnes    Level: advanced
350a997ad1aSLois Curfman McInnes 
351bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3520752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
353d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
354bb25748dSBarry Smith 
355273d9f13SBarry Smith     Concepts: mapping^local to global
356d4bb536fSBarry Smith 
35789d82c54SBarry Smith M*/
358d4bb536fSBarry Smith 
359d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
360d4bb536fSBarry Smith 
3614a2ae208SSatish Balay #undef __FUNCT__
3624a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
363d4bb536fSBarry Smith /*
364d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
365d4bb536fSBarry Smith */
366d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
367d4bb536fSBarry Smith {
368b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
369d4bb536fSBarry Smith 
3703a40ed3dSBarry Smith   PetscFunctionBegin;
371d4bb536fSBarry Smith   end   = 0;
372d4bb536fSBarry Smith   start = 100000000;
373d4bb536fSBarry Smith 
374d4bb536fSBarry Smith   for (i=0; i<n; i++) {
375d4bb536fSBarry Smith     if (idx[i] < 0) continue;
376d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
377d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
378d4bb536fSBarry Smith   }
379d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
380d4bb536fSBarry Smith   mapping->globalstart = start;
381d4bb536fSBarry Smith   mapping->globalend   = end;
382d4bb536fSBarry Smith 
383b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
384b0a32e0cSBarry Smith   mapping->globals = globals;
385d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
386d4bb536fSBarry Smith     globals[i] = -1;
387d4bb536fSBarry Smith   }
388d4bb536fSBarry Smith   for (i=0; i<n; i++) {
389d4bb536fSBarry Smith     if (idx[i] < 0) continue;
390d4bb536fSBarry Smith     globals[idx[i] - start] = i;
391d4bb536fSBarry Smith   }
392d4bb536fSBarry Smith 
393b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3943a40ed3dSBarry Smith   PetscFunctionReturn(0);
395d4bb536fSBarry Smith }
396d4bb536fSBarry Smith 
3974a2ae208SSatish Balay #undef __FUNCT__
3984a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
399d4bb536fSBarry Smith /*@
400a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
401a997ad1aSLois Curfman McInnes     specified with a global numbering.
402d4bb536fSBarry Smith 
403b9cd556bSLois Curfman McInnes     Not collective
404b9cd556bSLois Curfman McInnes 
405d4bb536fSBarry Smith     Input Parameters:
406b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
407d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
408d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
409d4bb536fSBarry Smith .   n - number of global indices to map
410b9cd556bSLois Curfman McInnes -   idx - global indices to map
411d4bb536fSBarry Smith 
412d4bb536fSBarry Smith     Output Parameters:
413b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
414b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
415e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
416e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
417e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
418e182c471SBarry Smith              a second time to set the values.
419d4bb536fSBarry Smith 
420b9cd556bSLois Curfman McInnes     Notes:
421b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
422d4bb536fSBarry Smith 
4230f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
4240f5bd95cSBarry Smith     array to compute these.
4250f5bd95cSBarry Smith 
426a997ad1aSLois Curfman McInnes     Level: advanced
427a997ad1aSLois Curfman McInnes 
428273d9f13SBarry Smith     Concepts: mapping^global to local
429d4bb536fSBarry Smith 
430d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
431d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
432d4bb536fSBarry Smith @*/
433d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
434987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
435d4bb536fSBarry Smith {
436d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
437d4bb536fSBarry Smith 
4383a40ed3dSBarry Smith   PetscFunctionBegin;
439d4bb536fSBarry Smith   if (!mapping->globals) {
440d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
441d4bb536fSBarry Smith   }
442d4bb536fSBarry Smith   globals = mapping->globals;
443d4bb536fSBarry Smith   start   = mapping->globalstart;
444d4bb536fSBarry Smith   end     = mapping->globalend;
445d4bb536fSBarry Smith 
446d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
447d4bb536fSBarry Smith     if (idxout) {
448d4bb536fSBarry Smith       for (i=0; i<n; i++) {
449d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
450d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
451d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
452d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
453d4bb536fSBarry Smith       }
454d4bb536fSBarry Smith     }
455d4bb536fSBarry Smith     if (nout) *nout = n;
456d4bb536fSBarry Smith   } else {
457d4bb536fSBarry Smith     if (idxout) {
458d4bb536fSBarry Smith       for (i=0; i<n; i++) {
459d4bb536fSBarry Smith         if (idx[i] < 0) continue;
460d4bb536fSBarry Smith         if (idx[i] < start) continue;
461d4bb536fSBarry Smith         if (idx[i] > end) continue;
462d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
463d4bb536fSBarry Smith         if (tmp < 0) continue;
464d4bb536fSBarry Smith         idxout[nf++] = tmp;
465d4bb536fSBarry Smith       }
466d4bb536fSBarry Smith     } else {
467d4bb536fSBarry Smith       for (i=0; i<n; i++) {
468d4bb536fSBarry Smith         if (idx[i] < 0) continue;
469d4bb536fSBarry Smith         if (idx[i] < start) continue;
470d4bb536fSBarry Smith         if (idx[i] > end) continue;
471d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
472d4bb536fSBarry Smith         if (tmp < 0) continue;
473d4bb536fSBarry Smith         nf++;
474d4bb536fSBarry Smith       }
475d4bb536fSBarry Smith     }
476d4bb536fSBarry Smith     if (nout) *nout = nf;
477d4bb536fSBarry Smith   }
478d4bb536fSBarry Smith 
4793a40ed3dSBarry Smith   PetscFunctionReturn(0);
480d4bb536fSBarry Smith }
48190f02eecSBarry Smith 
4824a2ae208SSatish Balay #undef __FUNCT__
4834a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
48489d82c54SBarry Smith /*@C
48589d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
48689d82c54SBarry Smith      each index shared by more than one processor
48789d82c54SBarry Smith 
48889d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
48989d82c54SBarry Smith 
49089d82c54SBarry Smith     Input Parameters:
49189d82c54SBarry Smith .   mapping - the mapping from local to global indexing
49289d82c54SBarry Smith 
49389d82c54SBarry Smith     Output Parameter:
49489d82c54SBarry Smith +   nproc - number of processors that are connected to this one
49589d82c54SBarry Smith .   proc - neighboring processors
49607b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
49707b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
49889d82c54SBarry Smith 
49989d82c54SBarry Smith     Level: advanced
50089d82c54SBarry Smith 
501273d9f13SBarry Smith     Concepts: mapping^local to global
50289d82c54SBarry Smith 
50307b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
50407b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
50589d82c54SBarry Smith @*/
506ca01db9bSBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int *procs[],int *numprocs[],int **indices[])
50789d82c54SBarry Smith {
508fa7fbcffSSatish Balay   int         i,n = mapping->n,ierr,Ng,ng,max = 0,*lindices = mapping->indices;
50927c402fcSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
51024cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
51107b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
51224cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
51389d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
51430dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
51589d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
51607b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
51789d82c54SBarry Smith 
51889d82c54SBarry Smith   PetscFunctionBegin;
51924cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
52024cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
52124cf384cSBarry Smith   if (size == 1) {
52224cf384cSBarry Smith     *nproc         = 0;
52324cf384cSBarry Smith     *procs         = PETSC_NULL;
524b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
5251e2105dcSBarry Smith     (*numprocs)[0] = 0;
526b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
5271e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
52824cf384cSBarry Smith     PetscFunctionReturn(0);
52924cf384cSBarry Smith   }
53024cf384cSBarry Smith 
531b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
53207b52d57SBarry Smith 
5333677ff5aSBarry Smith   /*
5343677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
5353677ff5aSBarry Smith 
5363677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
5373677ff5aSBarry Smith            numbering, just for this routine.
5383677ff5aSBarry Smith 
5393677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
5403677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
5413677ff5aSBarry Smith 
5423677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
5433677ff5aSBarry Smith 
5443677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
5453677ff5aSBarry Smith            local subdomain
5463677ff5aSBarry Smith   */
54724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
54824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
54924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
55089d82c54SBarry Smith 
55189d82c54SBarry Smith   for (i=0; i<n; i++) {
55289d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
55389d82c54SBarry Smith   }
55489d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
55578058e43SBarry Smith   Ng++;
55689d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
55789d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
558bc8ff85bSBarry Smith   scale  = Ng/size + 1;
559a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
560caba0dd0SBarry Smith   rstart = scale*rank;
56189d82c54SBarry Smith 
56289d82c54SBarry Smith   /* determine ownership ranges of global indices */
563b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5642880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
56589d82c54SBarry Smith 
56689d82c54SBarry Smith   /* determine owners of each local node  */
567b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
56889d82c54SBarry Smith   for (i=0; i<n; i++) {
5693677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
57027c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
5713677ff5aSBarry Smith     owner[i]         = proc;
57227c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
57389d82c54SBarry Smith   }
57427c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
575b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
57689d82c54SBarry Smith 
57789d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
57827c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
579b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
58089d82c54SBarry Smith 
58189d82c54SBarry Smith   /* post receives for owned rows */
582b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
583b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
58489d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
58524cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
58689d82c54SBarry Smith   }
58789d82c54SBarry Smith 
58889d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
589b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
590b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
59189d82c54SBarry Smith   starts[0]  = 0;
59227c402fcSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];}
59389d82c54SBarry Smith   for (i=0; i<n; i++) {
59489d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
59530dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
59689d82c54SBarry Smith   }
59789d82c54SBarry Smith   ierr = PetscFree(owner);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 
60189d82c54SBarry Smith   /* send the messages */
602b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
603b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
60489d82c54SBarry Smith   cnt = 0;
60589d82c54SBarry Smith   for (i=0; i<size; i++) {
60627c402fcSBarry Smith     if (nprocs[2*i]) {
60727c402fcSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
60830dcb7c9SBarry Smith       dest[cnt] = i;
60989d82c54SBarry Smith       cnt++;
61089d82c54SBarry Smith     }
61189d82c54SBarry Smith   }
61289d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
61389d82c54SBarry Smith 
61489d82c54SBarry Smith   /* wait on receives */
615b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
61689d82c54SBarry Smith   len  = source + nrecvs;
61789d82c54SBarry Smith   cnt  = nrecvs;
618b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
619caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
62089d82c54SBarry Smith   while (cnt) {
62189d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
62289d82c54SBarry Smith     /* unpack receives into our local space */
62389d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
62489d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
62530dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
626caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
62730dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
62889d82c54SBarry Smith     cnt--;
62989d82c54SBarry Smith   }
63089d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
63189d82c54SBarry Smith 
63230dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
633bc8ff85bSBarry Smith   nowned  = 0;
634bc8ff85bSBarry Smith   nownedm = 0;
635bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
636bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
637bc8ff85bSBarry Smith   }
638bc8ff85bSBarry Smith 
639bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
640b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
641b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
642bc8ff85bSBarry Smith   starts[0] = 0;
643bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
644bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
645bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
646bc8ff85bSBarry Smith   }
647bc8ff85bSBarry Smith 
64830dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
649bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
650bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
65130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
652bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
653bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
654bc8ff85bSBarry Smith       }
655bc8ff85bSBarry Smith     }
656bc8ff85bSBarry Smith   }
657bc8ff85bSBarry Smith 
65807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
65930dcb7c9SBarry Smith     starts[0]    = 0;
66030dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
66130dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
66230dcb7c9SBarry Smith       else starts[i] = starts[i-1];
66330dcb7c9SBarry Smith     }
66430dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
66530dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
66630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
66730dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
66830dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
66930dcb7c9SBarry Smith         }
67030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
67130dcb7c9SBarry Smith       }
67230dcb7c9SBarry Smith     }
67330dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
67407b52d57SBarry Smith   }/* -----------------------------------  */
67530dcb7c9SBarry Smith 
6763677ff5aSBarry Smith   /* wait on original sends */
6773a96401aSBarry Smith   if (nsends) {
678b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6793a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6803a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6813a96401aSBarry Smith   }
68289d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6833a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6843677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6853677ff5aSBarry Smith 
6863677ff5aSBarry Smith   /* pack messages to send back to local owners */
68730dcb7c9SBarry Smith   starts[0]    = 0;
68830dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
68930dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
69030dcb7c9SBarry Smith     else starts[i] = starts[i-1];
69130dcb7c9SBarry Smith   }
69230dcb7c9SBarry Smith   nsends2 = nrecvs;
693b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
69430dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
69530dcb7c9SBarry Smith     nprocs[i] = 1;
69630dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
69730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
69830dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
69930dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
70030dcb7c9SBarry Smith       }
70130dcb7c9SBarry Smith     }
70230dcb7c9SBarry Smith   }
70330dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
704b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
705b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
70630dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
70730dcb7c9SBarry Smith   /*
70830dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
70930dcb7c9SBarry Smith        (0) the number of nodes being sent back
71030dcb7c9SBarry Smith        (1) the local node number,
71130dcb7c9SBarry Smith        (2) the number of processors sharing it,
71230dcb7c9SBarry Smith        (3) the processors sharing it
71330dcb7c9SBarry Smith   */
71430dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
71530dcb7c9SBarry Smith     cnt = 1;
71630dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
71730dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
71830dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
71930dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
72030dcb7c9SBarry Smith         sends2[starts2[i]]++;
72130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
72230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
72330dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
72430dcb7c9SBarry Smith         cnt += nownedsenders[node];
72530dcb7c9SBarry Smith       }
72630dcb7c9SBarry Smith     }
72730dcb7c9SBarry Smith   }
72830dcb7c9SBarry Smith 
72930dcb7c9SBarry Smith   /* send the message lengths */
73030dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
73124cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
73230dcb7c9SBarry Smith   }
73330dcb7c9SBarry Smith 
73430dcb7c9SBarry Smith   /* receive the message lengths */
73530dcb7c9SBarry Smith   nrecvs2 = nsends;
736b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
737b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
73830dcb7c9SBarry Smith   nt      = 0;
73930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
74024cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
74130dcb7c9SBarry Smith     nt   += lens2[i];
74230dcb7c9SBarry Smith   }
74330dcb7c9SBarry Smith   starts3[0] = 0;
74430dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
74530dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
74630dcb7c9SBarry Smith   }
747b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
748b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
74952b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
75024cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
75130dcb7c9SBarry Smith   }
75230dcb7c9SBarry Smith 
75330dcb7c9SBarry Smith   /* send the messages */
754b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
75530dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
75624cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
75730dcb7c9SBarry Smith   }
75830dcb7c9SBarry Smith 
75930dcb7c9SBarry Smith   /* wait on receives */
760b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
76130dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
76230dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
76330dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
76430dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
76530dcb7c9SBarry Smith 
76607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
76730dcb7c9SBarry Smith     cnt = 0;
76830dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
76930dcb7c9SBarry Smith       nt = recvs2[cnt++];
77030dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
77130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
77230dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
77330dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
77430dcb7c9SBarry Smith         }
77530dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
77630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
77730dcb7c9SBarry Smith       }
77830dcb7c9SBarry Smith     }
77930dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
78007b52d57SBarry Smith   } /* -----------------------------------  */
78130dcb7c9SBarry Smith 
78230dcb7c9SBarry Smith   /* count number subdomains for each local node */
783b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
78430dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
78530dcb7c9SBarry Smith   cnt  = 0;
78630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
78730dcb7c9SBarry Smith     nt = recvs2[cnt++];
78830dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
78930dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
79030dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
79130dcb7c9SBarry Smith       }
79230dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
79330dcb7c9SBarry Smith     }
79430dcb7c9SBarry Smith   }
79530dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
79630dcb7c9SBarry Smith   *nproc    = nt;
797b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
798b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
799b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
800b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
80130dcb7c9SBarry Smith   cnt       = 0;
80230dcb7c9SBarry Smith   for (i=0; i<size; i++) {
80330dcb7c9SBarry Smith     if (nprocs[i] > 0) {
80430dcb7c9SBarry Smith       bprocs[i]        = cnt;
80530dcb7c9SBarry Smith       (*procs)[cnt]    = i;
80630dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
807b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
80830dcb7c9SBarry Smith       cnt++;
80930dcb7c9SBarry Smith     }
81030dcb7c9SBarry Smith   }
81130dcb7c9SBarry Smith 
81230dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
81330dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
81430dcb7c9SBarry Smith   cnt  = 0;
81530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
81630dcb7c9SBarry Smith     nt = recvs2[cnt++];
81730dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
81830dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
81930dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
82030dcb7c9SBarry Smith       }
82130dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
82230dcb7c9SBarry Smith     }
82330dcb7c9SBarry Smith   }
82430dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
82507b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
82630dcb7c9SBarry Smith 
82707b52d57SBarry Smith   /* sort the node indexing by their global numbers */
82807b52d57SBarry Smith   nt = *nproc;
82907b52d57SBarry Smith   for (i=0; i<nt; i++) {
830b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
83107b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
83207b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
83307b52d57SBarry Smith     }
83407b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
83507b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
83607b52d57SBarry Smith   }
83707b52d57SBarry Smith 
83807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
83930dcb7c9SBarry Smith     nt = *nproc;
84030dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
84130dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
84230dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
84330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
84430dcb7c9SBarry Smith       }
84530dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
84630dcb7c9SBarry Smith     }
84730dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
84807b52d57SBarry Smith   } /* -----------------------------------  */
84930dcb7c9SBarry Smith 
85030dcb7c9SBarry Smith   /* wait on sends */
85130dcb7c9SBarry Smith   if (nsends2) {
852b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
85330dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
85430dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
85530dcb7c9SBarry Smith   }
85630dcb7c9SBarry Smith 
85730dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
85830dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
85930dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8603677ff5aSBarry Smith 
861bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
862bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
863bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
86430dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
86530dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
86689d82c54SBarry Smith 
86789d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
86889d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8693a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
87030dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
87124cf384cSBarry Smith 
87224cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
87324cf384cSBarry Smith   first_procs    = (*procs)[0];
87424cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
87524cf384cSBarry Smith   first_indices  = (*indices)[0];
87624cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
87724cf384cSBarry Smith     if ((*procs)[i] == rank) {
87824cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
87924cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
88024cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
88124cf384cSBarry Smith       (*procs)[i]    = first_procs;
88224cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
88324cf384cSBarry Smith       (*indices)[i]  = first_indices;
88424cf384cSBarry Smith       break;
88524cf384cSBarry Smith     }
88624cf384cSBarry Smith   }
88724cf384cSBarry Smith 
88889d82c54SBarry Smith   PetscFunctionReturn(0);
88989d82c54SBarry Smith }
89089d82c54SBarry Smith 
8914a2ae208SSatish Balay #undef __FUNCT__
8924a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
89307b52d57SBarry Smith /*@C
89407b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
89589d82c54SBarry Smith 
89607b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
89707b52d57SBarry Smith 
89807b52d57SBarry Smith     Input Parameters:
89907b52d57SBarry Smith .   mapping - the mapping from local to global indexing
90007b52d57SBarry Smith 
90107b52d57SBarry Smith     Output Parameter:
90207b52d57SBarry Smith +   nproc - number of processors that are connected to this one
90307b52d57SBarry Smith .   proc - neighboring processors
90407b52d57SBarry Smith .   numproc - number of indices for each processor
90507b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
90607b52d57SBarry Smith 
90707b52d57SBarry Smith     Level: advanced
90807b52d57SBarry Smith 
90907b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
91007b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
91107b52d57SBarry Smith @*/
912ca01db9bSBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int *procs[],int *numprocs[],int **indices[])
91307b52d57SBarry Smith {
91407b52d57SBarry Smith   int ierr,i;
91507b52d57SBarry Smith 
91607b52d57SBarry Smith   PetscFunctionBegin;
91700ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
91800ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
91900ff320aSBarry Smith   if (*indices) {
92000ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
92100ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
92224cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
92307b52d57SBarry Smith     }
92407b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
92524cf384cSBarry Smith   }
92607b52d57SBarry Smith   PetscFunctionReturn(0);
92707b52d57SBarry Smith }
92889d82c54SBarry Smith 
929bc8ff85bSBarry Smith 
930bc8ff85bSBarry Smith 
931bc8ff85bSBarry Smith 
932bc8ff85bSBarry Smith 
933bc8ff85bSBarry Smith 
934bc8ff85bSBarry Smith 
935bc8ff85bSBarry Smith 
936bc8ff85bSBarry Smith 
937bc8ff85bSBarry Smith 
938bc8ff85bSBarry Smith 
939bc8ff85bSBarry Smith 
940bc8ff85bSBarry Smith 
941bc8ff85bSBarry Smith 
942bc8ff85bSBarry Smith 
943bc8ff85bSBarry Smith 
944bc8ff85bSBarry Smith 
94524cf384cSBarry Smith 
946