xref: /petsc/src/vec/is/utils/isltog.c (revision 216e7ba4fc2a928a093b793071ce3c893d778059)
1*216e7ba4SBarry Smith /*$Id: isltog.c,v 1.64 2001/03/23 23:21:16 balay Exp bsmith $*/
22362add9SBarry Smith 
3e090d566SSatish Balay #include "petscsys.h"   /*I "petscsys.h" I*/
4e090d566SSatish Balay #include "src/vec/is/isimpl.h"    /*I "petscis.h"  I*/
52362add9SBarry Smith 
64a2ae208SSatish Balay #undef __FUNCT__
74a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
83b9aefa3SBarry Smith /*@C
93b9aefa3SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping.
103b9aefa3SBarry Smith 
113b9aefa3SBarry Smith     Not Collective
123b9aefa3SBarry Smith 
133b9aefa3SBarry Smith     Input Parameter:
143b9aefa3SBarry Smith .   ltog - local to global mapping
153b9aefa3SBarry Smith 
163b9aefa3SBarry Smith     Output Parameter:
173b9aefa3SBarry Smith .   n - the number of entries in the local mapping
183b9aefa3SBarry Smith 
193b9aefa3SBarry Smith     Level: advanced
203b9aefa3SBarry Smith 
21273d9f13SBarry Smith     Concepts: mapping^local to global
223b9aefa3SBarry Smith 
233b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
243b9aefa3SBarry Smith @*/
253b9aefa3SBarry Smith int ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,int *n)
263b9aefa3SBarry Smith {
273b9aefa3SBarry Smith   PetscFunctionBegin;
283b9aefa3SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
293b9aefa3SBarry Smith   *n = mapping->n;
303b9aefa3SBarry Smith   PetscFunctionReturn(0);
313b9aefa3SBarry Smith }
323b9aefa3SBarry Smith 
334a2ae208SSatish Balay #undef __FUNCT__
344a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
355a5d4f66SBarry Smith /*@C
365a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
375a5d4f66SBarry Smith 
38b9cd556bSLois Curfman McInnes     Not Collective
39b9cd556bSLois Curfman McInnes 
405a5d4f66SBarry Smith     Input Parameters:
413b9aefa3SBarry Smith +   ltog - local to global mapping
423b9aefa3SBarry Smith -   viewer - viewer
435a5d4f66SBarry Smith 
44a997ad1aSLois Curfman McInnes     Level: advanced
45a997ad1aSLois Curfman McInnes 
46273d9f13SBarry Smith     Concepts: mapping^local to global
475a5d4f66SBarry Smith 
485a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
495a5d4f66SBarry Smith @*/
50b0a32e0cSBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
515a5d4f66SBarry Smith {
52f1af5d2fSBarry Smith   int        i,ierr,rank;
536831982aSBarry Smith   PetscTruth isascii;
545a5d4f66SBarry Smith 
555a5d4f66SBarry Smith   PetscFunctionBegin;
566831982aSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
57b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
58b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
595a5d4f66SBarry Smith 
60f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
61b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
626831982aSBarry Smith   if (isascii) {
635a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
64b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
656831982aSBarry Smith     }
66b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
676831982aSBarry Smith   } else {
6829bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
695a5d4f66SBarry Smith   }
705a5d4f66SBarry Smith 
715a5d4f66SBarry Smith   PetscFunctionReturn(0);
725a5d4f66SBarry Smith }
735a5d4f66SBarry Smith 
744a2ae208SSatish Balay #undef __FUNCT__
754a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
762bdab257SBarry Smith /*@C
772bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
782bdab257SBarry Smith     ordering and a global parallel ordering.
792bdab257SBarry Smith 
800f5bd95cSBarry Smith     Not collective
81b9cd556bSLois Curfman McInnes 
82a997ad1aSLois Curfman McInnes     Input Parameter:
832bdab257SBarry Smith .   is - index set containing the global numbers for each local
842bdab257SBarry Smith 
85a997ad1aSLois Curfman McInnes     Output Parameter:
862bdab257SBarry Smith .   mapping - new mapping data structure
872bdab257SBarry Smith 
88a997ad1aSLois Curfman McInnes     Level: advanced
89a997ad1aSLois Curfman McInnes 
90273d9f13SBarry Smith     Concepts: mapping^local to global
912bdab257SBarry Smith 
922bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
932bdab257SBarry Smith @*/
942bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
952bdab257SBarry Smith {
962bdab257SBarry Smith   int      n,*indices,ierr;
972bdab257SBarry Smith   MPI_Comm comm;
983a40ed3dSBarry Smith 
993a40ed3dSBarry Smith   PetscFunctionBegin;
1002bdab257SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
1012bdab257SBarry Smith 
1022bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1033b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1042bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1052bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
1062bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1072bdab257SBarry Smith 
1083a40ed3dSBarry Smith   PetscFunctionReturn(0);
1092bdab257SBarry Smith }
1105a5d4f66SBarry Smith 
1114a2ae208SSatish Balay #undef __FUNCT__
1124a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
113dd7157adSSatish Balay /*@C
11490f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
11590f02eecSBarry Smith     ordering and a global parallel ordering.
1162362add9SBarry Smith 
11789d82c54SBarry Smith     Not Collective, but communicator may have more than one process
118b9cd556bSLois Curfman McInnes 
1192362add9SBarry Smith     Input Parameters:
12089d82c54SBarry Smith +   comm - MPI communicator
12190f02eecSBarry Smith .   n - the number of local elements
122b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
1232362add9SBarry Smith 
124a997ad1aSLois Curfman McInnes     Output Parameter:
12590f02eecSBarry Smith .   mapping - new mapping data structure
1262362add9SBarry Smith 
127a997ad1aSLois Curfman McInnes     Level: advanced
128a997ad1aSLois Curfman McInnes 
129273d9f13SBarry Smith     Concepts: mapping^local to global
1302362add9SBarry Smith 
1312bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
1322362add9SBarry Smith @*/
133987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1342362add9SBarry Smith {
135549d3d68SSatish Balay   int ierr;
136549d3d68SSatish Balay 
1373a40ed3dSBarry Smith   PetscFunctionBegin;
13890f02eecSBarry Smith   PetscValidIntPointer(indices);
13990f02eecSBarry Smith   PetscValidPointer(mapping);
1402362add9SBarry Smith 
1413f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1423f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
143b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
144b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
145d4bb536fSBarry Smith 
146d4bb536fSBarry Smith   (*mapping)->n       = n;
147b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&(*mapping)->indices);CHKERRQ(ierr);
148549d3d68SSatish Balay   ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr);
149d4bb536fSBarry Smith 
150d4bb536fSBarry Smith   /*
151d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
152d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
153d4bb536fSBarry Smith   */
154d4bb536fSBarry Smith   (*mapping)->globals = 0;
1553a40ed3dSBarry Smith   PetscFunctionReturn(0);
1562362add9SBarry Smith }
1572362add9SBarry Smith 
1584a2ae208SSatish Balay #undef __FUNCT__
1594a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
160323b833fSBarry Smith /*@C
161323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
162323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
163323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
164323b833fSBarry Smith 
165323b833fSBarry Smith     Not Collective, but communicator may have more than one process
166323b833fSBarry Smith 
167323b833fSBarry Smith     Input Parameters:
168323b833fSBarry Smith +    inmap - original point-wise mapping
169323b833fSBarry Smith -    bs - block size
170323b833fSBarry Smith 
171323b833fSBarry Smith     Output Parameter:
172323b833fSBarry Smith .   outmap - block based mapping
173323b833fSBarry Smith 
174323b833fSBarry Smith     Level: advanced
175323b833fSBarry Smith 
176323b833fSBarry Smith     Concepts: mapping^local to global
177323b833fSBarry Smith 
178323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
179323b833fSBarry Smith @*/
180323b833fSBarry Smith int ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
181323b833fSBarry Smith {
182323b833fSBarry Smith   int ierr,*ii,i,n;
183323b833fSBarry Smith 
184323b833fSBarry Smith   PetscFunctionBegin;
185323b833fSBarry Smith 
186323b833fSBarry Smith   if (bs > 1) {
187323b833fSBarry Smith     n    = inmap->n/bs;
188323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
189323b833fSBarry Smith     for (i=0; i<n; i++) {
190b8ee7809SBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
191323b833fSBarry Smith     }
192323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
193323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
194323b833fSBarry Smith   } else {
195323b833fSBarry Smith     *outmap = inmap;
196323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
197323b833fSBarry Smith   }
198323b833fSBarry Smith   PetscFunctionReturn(0);
199323b833fSBarry Smith }
200323b833fSBarry Smith 
2014a2ae208SSatish Balay #undef __FUNCT__
2024a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
20390f02eecSBarry Smith /*@
20490f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
20590f02eecSBarry Smith    ordering and a global parallel ordering.
20690f02eecSBarry Smith 
2070f5bd95cSBarry Smith    Note Collective
208b9cd556bSLois Curfman McInnes 
20990f02eecSBarry Smith    Input Parameters:
21090f02eecSBarry Smith .  mapping - mapping data structure
21190f02eecSBarry Smith 
212a997ad1aSLois Curfman McInnes    Level: advanced
213a997ad1aSLois Curfman McInnes 
2143acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
21590f02eecSBarry Smith @*/
21690f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
21790f02eecSBarry Smith {
218606d414cSSatish Balay   int ierr;
2193a40ed3dSBarry Smith   PetscFunctionBegin;
22090f02eecSBarry Smith   PetscValidPointer(mapping);
2213a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
22285614651SBarry Smith   if (mapping->refct < 0) {
22329bbc08cSBarry Smith     SETERRQ(1,"Mapping already destroyed");
22485614651SBarry Smith   }
22590f02eecSBarry Smith 
226606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
227606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
228b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
229d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2303a40ed3dSBarry Smith   PetscFunctionReturn(0);
23190f02eecSBarry Smith }
23290f02eecSBarry Smith 
2334a2ae208SSatish Balay #undef __FUNCT__
2344a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
23590f02eecSBarry Smith /*@
2363acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2373acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2383acfe500SLois Curfman McInnes     context.
23990f02eecSBarry Smith 
240b9cd556bSLois Curfman McInnes     Not collective
241b9cd556bSLois Curfman McInnes 
24290f02eecSBarry Smith     Input Parameters:
243b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
244b9cd556bSLois Curfman McInnes -   is - index set in local numbering
24590f02eecSBarry Smith 
24690f02eecSBarry Smith     Output Parameters:
24790f02eecSBarry Smith .   newis - index set in global numbering
24890f02eecSBarry Smith 
249a997ad1aSLois Curfman McInnes     Level: advanced
250a997ad1aSLois Curfman McInnes 
251273d9f13SBarry Smith     Concepts: mapping^local to global
2523acfe500SLois Curfman McInnes 
25390f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
254d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
25590f02eecSBarry Smith @*/
25690f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
25790f02eecSBarry Smith {
2583b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
2593a40ed3dSBarry Smith 
2603a40ed3dSBarry Smith   PetscFunctionBegin;
26190f02eecSBarry Smith   PetscValidPointer(mapping);
26290f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
26390f02eecSBarry Smith   PetscValidPointer(newis);
26490f02eecSBarry Smith 
2653b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
26690f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
26790f02eecSBarry Smith   idxmap = mapping->indices;
26890f02eecSBarry Smith 
269b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
27090f02eecSBarry Smith   for (i=0; i<n; i++) {
27129bbc08cSBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i);
27290f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
27390f02eecSBarry Smith   }
2743b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
275029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
276606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
2773a40ed3dSBarry Smith   PetscFunctionReturn(0);
27890f02eecSBarry Smith }
27990f02eecSBarry Smith 
28089d82c54SBarry Smith /*MC
2813acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2823acfe500SLois Curfman McInnes    and converts them to the global numbering.
28390f02eecSBarry Smith 
284b9cd556bSLois Curfman McInnes    Not collective
285b9cd556bSLois Curfman McInnes 
286bb25748dSBarry Smith    Input Parameters:
287b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
288bb25748dSBarry Smith .  N - number of integers
289b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
290bb25748dSBarry Smith 
291bb25748dSBarry Smith    Output Parameter:
292bb25748dSBarry Smith .  out - indices in global numbering
293bb25748dSBarry Smith 
2943b9aefa3SBarry Smith    Synopsis:
295*216e7ba4SBarry Smith    int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
2963b9aefa3SBarry Smith 
297b9cd556bSLois Curfman McInnes    Notes:
298b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
299d4bb536fSBarry Smith 
300a997ad1aSLois Curfman McInnes    Level: advanced
301a997ad1aSLois Curfman McInnes 
302bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3030752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
304d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
305bb25748dSBarry Smith 
306273d9f13SBarry Smith     Concepts: mapping^local to global
307d4bb536fSBarry Smith 
30889d82c54SBarry Smith M*/
309d4bb536fSBarry Smith 
310d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
311d4bb536fSBarry Smith 
3124a2ae208SSatish Balay #undef __FUNCT__
3134a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
314d4bb536fSBarry Smith /*
315d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
316d4bb536fSBarry Smith */
317d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
318d4bb536fSBarry Smith {
319b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
320d4bb536fSBarry Smith 
3213a40ed3dSBarry Smith   PetscFunctionBegin;
322d4bb536fSBarry Smith   end   = 0;
323d4bb536fSBarry Smith   start = 100000000;
324d4bb536fSBarry Smith 
325d4bb536fSBarry Smith   for (i=0; i<n; i++) {
326d4bb536fSBarry Smith     if (idx[i] < 0) continue;
327d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
328d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
329d4bb536fSBarry Smith   }
330d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
331d4bb536fSBarry Smith   mapping->globalstart = start;
332d4bb536fSBarry Smith   mapping->globalend   = end;
333d4bb536fSBarry Smith 
334b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
335b0a32e0cSBarry Smith   mapping->globals = globals;
336d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
337d4bb536fSBarry Smith     globals[i] = -1;
338d4bb536fSBarry Smith   }
339d4bb536fSBarry Smith   for (i=0; i<n; i++) {
340d4bb536fSBarry Smith     if (idx[i] < 0) continue;
341d4bb536fSBarry Smith     globals[idx[i] - start] = i;
342d4bb536fSBarry Smith   }
343d4bb536fSBarry Smith 
344b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3453a40ed3dSBarry Smith   PetscFunctionReturn(0);
346d4bb536fSBarry Smith }
347d4bb536fSBarry Smith 
3484a2ae208SSatish Balay #undef __FUNCT__
3494a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
350d4bb536fSBarry Smith /*@
351a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
352a997ad1aSLois Curfman McInnes     specified with a global numbering.
353d4bb536fSBarry Smith 
354b9cd556bSLois Curfman McInnes     Not collective
355b9cd556bSLois Curfman McInnes 
356d4bb536fSBarry Smith     Input Parameters:
357b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
358d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
359d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
360d4bb536fSBarry Smith .   n - number of global indices to map
361b9cd556bSLois Curfman McInnes -   idx - global indices to map
362d4bb536fSBarry Smith 
363d4bb536fSBarry Smith     Output Parameters:
364b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
365b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
366e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
367e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
368e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
369e182c471SBarry Smith              a second time to set the values.
370d4bb536fSBarry Smith 
371b9cd556bSLois Curfman McInnes     Notes:
372b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
373d4bb536fSBarry Smith 
3740f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
3750f5bd95cSBarry Smith     array to compute these.
3760f5bd95cSBarry Smith 
377a997ad1aSLois Curfman McInnes     Level: advanced
378a997ad1aSLois Curfman McInnes 
379273d9f13SBarry Smith     Concepts: mapping^global to local
380d4bb536fSBarry Smith 
381d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
382d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
383d4bb536fSBarry Smith @*/
384d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
385987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
386d4bb536fSBarry Smith {
387d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
388d4bb536fSBarry Smith 
3893a40ed3dSBarry Smith   PetscFunctionBegin;
390d4bb536fSBarry Smith   if (!mapping->globals) {
391d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
392d4bb536fSBarry Smith   }
393d4bb536fSBarry Smith   globals = mapping->globals;
394d4bb536fSBarry Smith   start   = mapping->globalstart;
395d4bb536fSBarry Smith   end     = mapping->globalend;
396d4bb536fSBarry Smith 
397d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
398d4bb536fSBarry Smith     if (idxout) {
399d4bb536fSBarry Smith       for (i=0; i<n; i++) {
400d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
401d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
402d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
403d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
404d4bb536fSBarry Smith       }
405d4bb536fSBarry Smith     }
406d4bb536fSBarry Smith     if (nout) *nout = n;
407d4bb536fSBarry Smith   } else {
408d4bb536fSBarry Smith     if (idxout) {
409d4bb536fSBarry Smith       for (i=0; i<n; i++) {
410d4bb536fSBarry Smith         if (idx[i] < 0) continue;
411d4bb536fSBarry Smith         if (idx[i] < start) continue;
412d4bb536fSBarry Smith         if (idx[i] > end) continue;
413d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
414d4bb536fSBarry Smith         if (tmp < 0) continue;
415d4bb536fSBarry Smith         idxout[nf++] = tmp;
416d4bb536fSBarry Smith       }
417d4bb536fSBarry Smith     } else {
418d4bb536fSBarry Smith       for (i=0; i<n; i++) {
419d4bb536fSBarry Smith         if (idx[i] < 0) continue;
420d4bb536fSBarry Smith         if (idx[i] < start) continue;
421d4bb536fSBarry Smith         if (idx[i] > end) continue;
422d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
423d4bb536fSBarry Smith         if (tmp < 0) continue;
424d4bb536fSBarry Smith         nf++;
425d4bb536fSBarry Smith       }
426d4bb536fSBarry Smith     }
427d4bb536fSBarry Smith     if (nout) *nout = nf;
428d4bb536fSBarry Smith   }
429d4bb536fSBarry Smith 
4303a40ed3dSBarry Smith   PetscFunctionReturn(0);
431d4bb536fSBarry Smith }
43290f02eecSBarry Smith 
4334a2ae208SSatish Balay #undef __FUNCT__
4344a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
43589d82c54SBarry Smith /*@C
43689d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
43789d82c54SBarry Smith      each index shared by more than one processor
43889d82c54SBarry Smith 
43989d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
44089d82c54SBarry Smith 
44189d82c54SBarry Smith     Input Parameters:
44289d82c54SBarry Smith .   mapping - the mapping from local to global indexing
44389d82c54SBarry Smith 
44489d82c54SBarry Smith     Output Parameter:
44589d82c54SBarry Smith +   nproc - number of processors that are connected to this one
44689d82c54SBarry Smith .   proc - neighboring processors
44707b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
44807b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
44989d82c54SBarry Smith 
45089d82c54SBarry Smith     Level: advanced
45189d82c54SBarry Smith 
452273d9f13SBarry Smith     Concepts: mapping^local to global
45389d82c54SBarry Smith 
45407b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
45507b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
45689d82c54SBarry Smith @*/
45730dcb7c9SBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
45889d82c54SBarry Smith {
459fa7fbcffSSatish Balay   int         i,n = mapping->n,ierr,Ng,ng,max = 0,*lindices = mapping->indices;
4603a96401aSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc;
46124cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
46207b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
46324cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
46489d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
46530dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
46689d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
46707b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
46889d82c54SBarry Smith 
46989d82c54SBarry Smith   PetscFunctionBegin;
47024cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
47124cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
47224cf384cSBarry Smith   if (size == 1) {
47324cf384cSBarry Smith     *nproc         = 0;
47424cf384cSBarry Smith     *procs         = PETSC_NULL;
475b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
4761e2105dcSBarry Smith     (*numprocs)[0] = 0;
477b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
4781e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
47924cf384cSBarry Smith     PetscFunctionReturn(0);
48024cf384cSBarry Smith   }
48124cf384cSBarry Smith 
482b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
48307b52d57SBarry Smith 
4843677ff5aSBarry Smith   /*
4853677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
4863677ff5aSBarry Smith 
4873677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
4883677ff5aSBarry Smith            numbering, just for this routine.
4893677ff5aSBarry Smith 
4903677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
4913677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
4923677ff5aSBarry Smith 
4933677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
4943677ff5aSBarry Smith 
4953677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
4963677ff5aSBarry Smith            local subdomain
4973677ff5aSBarry Smith   */
49824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
49924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
50024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
50189d82c54SBarry Smith 
50289d82c54SBarry Smith   for (i=0; i<n; i++) {
50389d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
50489d82c54SBarry Smith   }
50589d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
50678058e43SBarry Smith   Ng++;
50789d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
50889d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
509bc8ff85bSBarry Smith   scale  = Ng/size + 1;
510a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
511caba0dd0SBarry Smith   rstart = scale*rank;
51289d82c54SBarry Smith 
51389d82c54SBarry Smith   /* determine ownership ranges of global indices */
514b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5152880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
51689d82c54SBarry Smith 
51789d82c54SBarry Smith   /* determine owners of each local node  */
518b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
51989d82c54SBarry Smith   for (i=0; i<n; i++) {
5203677ff5aSBarry Smith     proc              = lindices[i]/scale; /* processor that globally owns this index */
5213677ff5aSBarry Smith     nprocs[size+proc] = 1;                 /* processor globally owns at least one of ours */
5223677ff5aSBarry Smith     owner[i]          = proc;
5233677ff5aSBarry Smith     nprocs[proc]++;                        /* count of how many that processor globally owns of ours */
52489d82c54SBarry Smith   }
52589d82c54SBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i];
526b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
52789d82c54SBarry Smith 
52889d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
529b0a32e0cSBarry Smith   ierr = PetscMalloc(2*size*sizeof(int),&work);CHKERRQ(ierr);
53089d82c54SBarry Smith   ierr   = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
53189d82c54SBarry Smith   nmax   = work[rank];
53289d82c54SBarry Smith   nrecvs = work[size+rank];
53389d82c54SBarry Smith   ierr   = PetscFree(work);CHKERRQ(ierr);
534b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
53589d82c54SBarry Smith 
53689d82c54SBarry Smith   /* post receives for owned rows */
537b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
538b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
53989d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
54024cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
54189d82c54SBarry Smith   }
54289d82c54SBarry Smith 
54389d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
544b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
545b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
54689d82c54SBarry Smith   starts[0]  = 0;
54730dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
54889d82c54SBarry Smith   for (i=0; i<n; i++) {
54989d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
55030dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
55189d82c54SBarry Smith   }
55289d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
55389d82c54SBarry Smith   starts[0]  = 0;
55430dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
55589d82c54SBarry Smith 
55689d82c54SBarry Smith   /* send the messages */
557b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
558b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
55989d82c54SBarry Smith   cnt = 0;
56089d82c54SBarry Smith   for (i=0; i<size; i++) {
56189d82c54SBarry Smith     if (nprocs[i]) {
56224cf384cSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
56330dcb7c9SBarry Smith       dest[cnt] = i;
56489d82c54SBarry Smith       cnt++;
56589d82c54SBarry Smith     }
56689d82c54SBarry Smith   }
56789d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
56889d82c54SBarry Smith 
56989d82c54SBarry Smith   /* wait on receives */
570b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
57189d82c54SBarry Smith   len  = source + nrecvs;
57289d82c54SBarry Smith   cnt  = nrecvs;
573b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
574caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
57589d82c54SBarry Smith   while (cnt) {
57689d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
57789d82c54SBarry Smith     /* unpack receives into our local space */
57889d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
57989d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
58030dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
581caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
58230dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
58389d82c54SBarry Smith     cnt--;
58489d82c54SBarry Smith   }
58589d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
58689d82c54SBarry Smith 
58730dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
588bc8ff85bSBarry Smith   nowned  = 0;
589bc8ff85bSBarry Smith   nownedm = 0;
590bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
591bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
592bc8ff85bSBarry Smith   }
593bc8ff85bSBarry Smith 
594bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
595b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
596b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
597bc8ff85bSBarry Smith   starts[0] = 0;
598bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
599bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
600bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
601bc8ff85bSBarry Smith   }
602bc8ff85bSBarry Smith 
60330dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
604bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
605bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
60630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
607bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
608bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
609bc8ff85bSBarry Smith       }
610bc8ff85bSBarry Smith     }
611bc8ff85bSBarry Smith   }
612bc8ff85bSBarry Smith 
61307b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
61430dcb7c9SBarry Smith     starts[0]    = 0;
61530dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
61630dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
61730dcb7c9SBarry Smith       else starts[i] = starts[i-1];
61830dcb7c9SBarry Smith     }
61930dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
62030dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
62130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
62230dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
62330dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
62430dcb7c9SBarry Smith         }
62530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
62630dcb7c9SBarry Smith       }
62730dcb7c9SBarry Smith     }
62830dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
62907b52d57SBarry Smith   }/* -----------------------------------  */
63030dcb7c9SBarry Smith 
6313677ff5aSBarry Smith   /* wait on original sends */
6323a96401aSBarry Smith   if (nsends) {
633b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6343a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6353a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6363a96401aSBarry Smith   }
63789d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6383a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6393677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6403677ff5aSBarry Smith 
6413677ff5aSBarry Smith   /* pack messages to send back to local owners */
64230dcb7c9SBarry Smith   starts[0]    = 0;
64330dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
64430dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
64530dcb7c9SBarry Smith     else starts[i] = starts[i-1];
64630dcb7c9SBarry Smith   }
64730dcb7c9SBarry Smith   nsends2 = nrecvs;
648b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
64930dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
65030dcb7c9SBarry Smith     nprocs[i] = 1;
65130dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
65230dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
65330dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
65430dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
65530dcb7c9SBarry Smith       }
65630dcb7c9SBarry Smith     }
65730dcb7c9SBarry Smith   }
65830dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
659b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
660b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
66130dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
66230dcb7c9SBarry Smith   /*
66330dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
66430dcb7c9SBarry Smith        (0) the number of nodes being sent back
66530dcb7c9SBarry Smith        (1) the local node number,
66630dcb7c9SBarry Smith        (2) the number of processors sharing it,
66730dcb7c9SBarry Smith        (3) the processors sharing it
66830dcb7c9SBarry Smith   */
66930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
67030dcb7c9SBarry Smith     cnt = 1;
67130dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
67230dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
67330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
67430dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
67530dcb7c9SBarry Smith         sends2[starts2[i]]++;
67630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
67730dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
67830dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
67930dcb7c9SBarry Smith         cnt += nownedsenders[node];
68030dcb7c9SBarry Smith       }
68130dcb7c9SBarry Smith     }
68230dcb7c9SBarry Smith   }
68330dcb7c9SBarry Smith 
68430dcb7c9SBarry Smith   /* send the message lengths */
68530dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
68624cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
68730dcb7c9SBarry Smith   }
68830dcb7c9SBarry Smith 
68930dcb7c9SBarry Smith   /* receive the message lengths */
69030dcb7c9SBarry Smith   nrecvs2 = nsends;
691b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
692b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
69330dcb7c9SBarry Smith   nt      = 0;
69430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
69524cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
69630dcb7c9SBarry Smith     nt   += lens2[i];
69730dcb7c9SBarry Smith   }
69830dcb7c9SBarry Smith   starts3[0] = 0;
69930dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
70030dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
70130dcb7c9SBarry Smith   }
702b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
703b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
70452b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
70524cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
70630dcb7c9SBarry Smith   }
70730dcb7c9SBarry Smith 
70830dcb7c9SBarry Smith   /* send the messages */
709b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
71030dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
71124cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
71230dcb7c9SBarry Smith   }
71330dcb7c9SBarry Smith 
71430dcb7c9SBarry Smith   /* wait on receives */
715b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
71630dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
71730dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
71830dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
71930dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
72030dcb7c9SBarry Smith 
72107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
72230dcb7c9SBarry Smith     cnt = 0;
72330dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
72430dcb7c9SBarry Smith       nt = recvs2[cnt++];
72530dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
72630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
72730dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
72830dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
72930dcb7c9SBarry Smith         }
73030dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
73130dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
73230dcb7c9SBarry Smith       }
73330dcb7c9SBarry Smith     }
73430dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
73507b52d57SBarry Smith   } /* -----------------------------------  */
73630dcb7c9SBarry Smith 
73730dcb7c9SBarry Smith   /* count number subdomains for each local node */
738b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
73930dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
74030dcb7c9SBarry Smith   cnt  = 0;
74130dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
74230dcb7c9SBarry Smith     nt = recvs2[cnt++];
74330dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
74430dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
74530dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
74630dcb7c9SBarry Smith       }
74730dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
74830dcb7c9SBarry Smith     }
74930dcb7c9SBarry Smith   }
75030dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
75130dcb7c9SBarry Smith   *nproc    = nt;
752b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
753b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
754b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
755b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
75630dcb7c9SBarry Smith   cnt       = 0;
75730dcb7c9SBarry Smith   for (i=0; i<size; i++) {
75830dcb7c9SBarry Smith     if (nprocs[i] > 0) {
75930dcb7c9SBarry Smith       bprocs[i]        = cnt;
76030dcb7c9SBarry Smith       (*procs)[cnt]    = i;
76130dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
762b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
76330dcb7c9SBarry Smith       cnt++;
76430dcb7c9SBarry Smith     }
76530dcb7c9SBarry Smith   }
76630dcb7c9SBarry Smith 
76730dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
76830dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
76930dcb7c9SBarry Smith   cnt  = 0;
77030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
77130dcb7c9SBarry Smith     nt = recvs2[cnt++];
77230dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
77330dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
77430dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
77530dcb7c9SBarry Smith       }
77630dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
77730dcb7c9SBarry Smith     }
77830dcb7c9SBarry Smith   }
77930dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
78007b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
78130dcb7c9SBarry Smith 
78207b52d57SBarry Smith   /* sort the node indexing by their global numbers */
78307b52d57SBarry Smith   nt = *nproc;
78407b52d57SBarry Smith   for (i=0; i<nt; i++) {
785b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
78607b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
78707b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
78807b52d57SBarry Smith     }
78907b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
79007b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
79107b52d57SBarry Smith   }
79207b52d57SBarry Smith 
79307b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
79430dcb7c9SBarry Smith     nt = *nproc;
79530dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
79630dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
79730dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
79830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
79930dcb7c9SBarry Smith       }
80030dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
80130dcb7c9SBarry Smith     }
80230dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
80307b52d57SBarry Smith   } /* -----------------------------------  */
80430dcb7c9SBarry Smith 
80530dcb7c9SBarry Smith   /* wait on sends */
80630dcb7c9SBarry Smith   if (nsends2) {
807b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
80830dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
80930dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
81030dcb7c9SBarry Smith   }
81130dcb7c9SBarry Smith 
81230dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
81330dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
81430dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8153677ff5aSBarry Smith 
816bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
817bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
818bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
81930dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
82030dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
82189d82c54SBarry Smith 
82289d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
82389d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8243a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
82530dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
82624cf384cSBarry Smith 
82724cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
82824cf384cSBarry Smith   first_procs    = (*procs)[0];
82924cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
83024cf384cSBarry Smith   first_indices  = (*indices)[0];
83124cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
83224cf384cSBarry Smith     if ((*procs)[i] == rank) {
83324cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
83424cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
83524cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
83624cf384cSBarry Smith       (*procs)[i]    = first_procs;
83724cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
83824cf384cSBarry Smith       (*indices)[i]  = first_indices;
83924cf384cSBarry Smith       break;
84024cf384cSBarry Smith     }
84124cf384cSBarry Smith   }
84224cf384cSBarry Smith 
84389d82c54SBarry Smith   PetscFunctionReturn(0);
84489d82c54SBarry Smith }
84589d82c54SBarry Smith 
8464a2ae208SSatish Balay #undef __FUNCT__
8474a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
84807b52d57SBarry Smith /*@C
84907b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
85089d82c54SBarry Smith 
85107b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
85207b52d57SBarry Smith 
85307b52d57SBarry Smith     Input Parameters:
85407b52d57SBarry Smith .   mapping - the mapping from local to global indexing
85507b52d57SBarry Smith 
85607b52d57SBarry Smith     Output Parameter:
85707b52d57SBarry Smith +   nproc - number of processors that are connected to this one
85807b52d57SBarry Smith .   proc - neighboring processors
85907b52d57SBarry Smith .   numproc - number of indices for each processor
86007b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
86107b52d57SBarry Smith 
86207b52d57SBarry Smith     Level: advanced
86307b52d57SBarry Smith 
86407b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
86507b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
86607b52d57SBarry Smith @*/
86707b52d57SBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
86807b52d57SBarry Smith {
86907b52d57SBarry Smith   int ierr,i;
87007b52d57SBarry Smith 
87107b52d57SBarry Smith   PetscFunctionBegin;
87200ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
87300ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
87400ff320aSBarry Smith   if (*indices) {
87500ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
87600ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
87724cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
87807b52d57SBarry Smith     }
87907b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
88024cf384cSBarry Smith   }
88107b52d57SBarry Smith   PetscFunctionReturn(0);
88207b52d57SBarry Smith }
88389d82c54SBarry Smith 
884bc8ff85bSBarry Smith 
885bc8ff85bSBarry Smith 
886bc8ff85bSBarry Smith 
887bc8ff85bSBarry Smith 
888bc8ff85bSBarry Smith 
889bc8ff85bSBarry Smith 
890bc8ff85bSBarry Smith 
891bc8ff85bSBarry Smith 
892bc8ff85bSBarry Smith 
893bc8ff85bSBarry Smith 
894bc8ff85bSBarry Smith 
895bc8ff85bSBarry Smith 
896bc8ff85bSBarry Smith 
897bc8ff85bSBarry Smith 
898bc8ff85bSBarry Smith 
899bc8ff85bSBarry Smith 
90024cf384cSBarry Smith 
901