xref: /petsc/src/vec/is/utils/isltog.c (revision ca01db9ba66ebb300ac5de5b46114047c0f0cf10)
173f4d377SMatthew Knepley /*$Id: isltog.c,v 1.65 2001/05/21 14:16:29 bsmith Exp $*/
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 
68e58c17dSMatthew Knepley EXTERN int VecInitializePackage(char *);
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;
303b9aefa3SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
313b9aefa3SBarry Smith   *n = mapping->n;
323b9aefa3SBarry Smith   PetscFunctionReturn(0);
333b9aefa3SBarry Smith }
343b9aefa3SBarry Smith 
354a2ae208SSatish Balay #undef __FUNCT__
364a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
375a5d4f66SBarry Smith /*@C
385a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
395a5d4f66SBarry Smith 
40b9cd556bSLois Curfman McInnes     Not Collective
41b9cd556bSLois Curfman McInnes 
425a5d4f66SBarry Smith     Input Parameters:
433b9aefa3SBarry Smith +   ltog - local to global mapping
443b9aefa3SBarry Smith -   viewer - viewer
455a5d4f66SBarry Smith 
46a997ad1aSLois Curfman McInnes     Level: advanced
47a997ad1aSLois Curfman McInnes 
48273d9f13SBarry Smith     Concepts: mapping^local to global
495a5d4f66SBarry Smith 
505a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
515a5d4f66SBarry Smith @*/
52b0a32e0cSBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
535a5d4f66SBarry Smith {
54f1af5d2fSBarry Smith   int        i,ierr,rank;
556831982aSBarry Smith   PetscTruth isascii;
565a5d4f66SBarry Smith 
575a5d4f66SBarry Smith   PetscFunctionBegin;
586831982aSBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE);
59b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(mapping->comm);
60b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
615a5d4f66SBarry Smith 
62f1af5d2fSBarry Smith   ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr);
63b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
646831982aSBarry Smith   if (isascii) {
655a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
66b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
676831982aSBarry Smith     }
68b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
696831982aSBarry Smith   } else {
7029bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
715a5d4f66SBarry Smith   }
725a5d4f66SBarry Smith 
735a5d4f66SBarry Smith   PetscFunctionReturn(0);
745a5d4f66SBarry Smith }
755a5d4f66SBarry Smith 
764a2ae208SSatish Balay #undef __FUNCT__
774a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
782bdab257SBarry Smith /*@C
792bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
802bdab257SBarry Smith     ordering and a global parallel ordering.
812bdab257SBarry Smith 
820f5bd95cSBarry Smith     Not collective
83b9cd556bSLois Curfman McInnes 
84a997ad1aSLois Curfman McInnes     Input Parameter:
852bdab257SBarry Smith .   is - index set containing the global numbers for each local
862bdab257SBarry Smith 
87a997ad1aSLois Curfman McInnes     Output Parameter:
882bdab257SBarry Smith .   mapping - new mapping data structure
892bdab257SBarry Smith 
90a997ad1aSLois Curfman McInnes     Level: advanced
91a997ad1aSLois Curfman McInnes 
92273d9f13SBarry Smith     Concepts: mapping^local to global
932bdab257SBarry Smith 
942bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
952bdab257SBarry Smith @*/
962bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
972bdab257SBarry Smith {
982bdab257SBarry Smith   int      n,*indices,ierr;
992bdab257SBarry Smith   MPI_Comm comm;
1003a40ed3dSBarry Smith 
1013a40ed3dSBarry Smith   PetscFunctionBegin;
1022bdab257SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
1032bdab257SBarry Smith 
1042bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1053b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1062bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
1072bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
1082bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1092bdab257SBarry Smith 
1103a40ed3dSBarry Smith   PetscFunctionReturn(0);
1112bdab257SBarry Smith }
1125a5d4f66SBarry Smith 
113b46b645bSBarry Smith 
1144a2ae208SSatish Balay #undef __FUNCT__
1154a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
116dd7157adSSatish Balay /*@C
11790f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
11890f02eecSBarry Smith     ordering and a global parallel ordering.
1192362add9SBarry Smith 
12089d82c54SBarry Smith     Not Collective, but communicator may have more than one process
121b9cd556bSLois Curfman McInnes 
1222362add9SBarry Smith     Input Parameters:
12389d82c54SBarry Smith +   comm - MPI communicator
12490f02eecSBarry Smith .   n - the number of local elements
125b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
1262362add9SBarry Smith 
127a997ad1aSLois Curfman McInnes     Output Parameter:
12890f02eecSBarry Smith .   mapping - new mapping data structure
1292362add9SBarry Smith 
130a997ad1aSLois Curfman McInnes     Level: advanced
131a997ad1aSLois Curfman McInnes 
132273d9f13SBarry Smith     Concepts: mapping^local to global
1332362add9SBarry Smith 
134b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreateNC()
1352362add9SBarry Smith @*/
136987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1372362add9SBarry Smith {
138b46b645bSBarry Smith   int *in,ierr;
139b46b645bSBarry Smith 
140b46b645bSBarry Smith   PetscFunctionBegin;
141b46b645bSBarry Smith   PetscValidIntPointer(indices);
142b46b645bSBarry Smith   PetscValidPointer(mapping);
143b46b645bSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&in);CHKERRQ(ierr);
144b46b645bSBarry Smith   ierr = PetscMemcpy(in,indices,n*sizeof(int));CHKERRQ(ierr);
145b46b645bSBarry Smith   ierr = ISLocalToGlobalMappingCreateNC(cm,n,in,mapping);CHKERRQ(ierr);
146b46b645bSBarry Smith   PetscFunctionReturn(0);
147b46b645bSBarry Smith }
148b46b645bSBarry Smith 
149b46b645bSBarry Smith #undef __FUNCT__
150b46b645bSBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingCreateNC"
151b46b645bSBarry Smith /*@C
152b46b645bSBarry Smith     ISLocalToGlobalMappingCreateNC - Creates a mapping between a local (0 to n)
153b46b645bSBarry Smith     ordering and a global parallel ordering.
154b46b645bSBarry Smith 
155b46b645bSBarry Smith     Not Collective, but communicator may have more than one process
156b46b645bSBarry Smith 
157b46b645bSBarry Smith     Input Parameters:
158b46b645bSBarry Smith +   comm - MPI communicator
159b46b645bSBarry Smith .   n - the number of local elements
160b46b645bSBarry Smith -   indices - the global index for each local element
161b46b645bSBarry Smith 
162b46b645bSBarry Smith     Output Parameter:
163b46b645bSBarry Smith .   mapping - new mapping data structure
164b46b645bSBarry Smith 
165b46b645bSBarry Smith     Level: developer
166b46b645bSBarry Smith 
167b46b645bSBarry Smith     Notes: Does not copy the indices, just keeps the pointer to the indices. The ISLocalToGlobalMappingDestroy()
168b46b645bSBarry Smith     will free the space so it must be obtained with PetscMalloc() and it must not be freed elsewhere.
169b46b645bSBarry Smith 
170b46b645bSBarry Smith     Concepts: mapping^local to global
171b46b645bSBarry Smith 
172b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate()
173b46b645bSBarry Smith @*/
174b46b645bSBarry Smith int ISLocalToGlobalMappingCreateNC(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
175b46b645bSBarry Smith {
1763a40ed3dSBarry Smith   PetscFunctionBegin;
17790f02eecSBarry Smith   PetscValidIntPointer(indices);
17890f02eecSBarry Smith   PetscValidPointer(mapping);
1798e58c17dSMatthew Knepley   *mapping = PETSC_NULL;
1808e58c17dSMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
18158d3e684SBarry Smith   {int ierr = VecInitializePackage(PETSC_NULL);                                                                CHKERRQ(ierr);}
1828e58c17dSMatthew Knepley #endif
1832362add9SBarry Smith 
1843f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1853f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
186b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
187b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
188d4bb536fSBarry Smith 
189d4bb536fSBarry Smith   (*mapping)->n       = n;
190b46b645bSBarry Smith   (*mapping)->indices = (int*)indices;
191d4bb536fSBarry Smith 
192d4bb536fSBarry Smith   /*
193d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
194d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
195d4bb536fSBarry Smith   */
196d4bb536fSBarry Smith   (*mapping)->globals = 0;
1973a40ed3dSBarry Smith   PetscFunctionReturn(0);
1982362add9SBarry Smith }
1992362add9SBarry Smith 
2004a2ae208SSatish Balay #undef __FUNCT__
2014a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
202323b833fSBarry Smith /*@C
203323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
204323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
205323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
206323b833fSBarry Smith 
207323b833fSBarry Smith     Not Collective, but communicator may have more than one process
208323b833fSBarry Smith 
209323b833fSBarry Smith     Input Parameters:
210323b833fSBarry Smith +    inmap - original point-wise mapping
211323b833fSBarry Smith -    bs - block size
212323b833fSBarry Smith 
213323b833fSBarry Smith     Output Parameter:
214323b833fSBarry Smith .   outmap - block based mapping
215323b833fSBarry Smith 
216323b833fSBarry Smith     Level: advanced
217323b833fSBarry Smith 
218323b833fSBarry Smith     Concepts: mapping^local to global
219323b833fSBarry Smith 
220323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
221323b833fSBarry Smith @*/
222323b833fSBarry Smith int ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
223323b833fSBarry Smith {
224323b833fSBarry Smith   int ierr,*ii,i,n;
225323b833fSBarry Smith 
226323b833fSBarry Smith   PetscFunctionBegin;
227323b833fSBarry Smith 
228323b833fSBarry Smith   if (bs > 1) {
229323b833fSBarry Smith     n    = inmap->n/bs;
230323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
231323b833fSBarry Smith     for (i=0; i<n; i++) {
232b8ee7809SBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
233323b833fSBarry Smith     }
234323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
235323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
236323b833fSBarry Smith   } else {
237323b833fSBarry Smith     *outmap = inmap;
238323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
239323b833fSBarry Smith   }
240323b833fSBarry Smith   PetscFunctionReturn(0);
241323b833fSBarry Smith }
242323b833fSBarry Smith 
2434a2ae208SSatish Balay #undef __FUNCT__
2444a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
24590f02eecSBarry Smith /*@
24690f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
24790f02eecSBarry Smith    ordering and a global parallel ordering.
24890f02eecSBarry Smith 
2490f5bd95cSBarry Smith    Note Collective
250b9cd556bSLois Curfman McInnes 
25190f02eecSBarry Smith    Input Parameters:
25290f02eecSBarry Smith .  mapping - mapping data structure
25390f02eecSBarry Smith 
254a997ad1aSLois Curfman McInnes    Level: advanced
255a997ad1aSLois Curfman McInnes 
2563acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
25790f02eecSBarry Smith @*/
25890f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
25990f02eecSBarry Smith {
260606d414cSSatish Balay   int ierr;
2613a40ed3dSBarry Smith   PetscFunctionBegin;
26290f02eecSBarry Smith   PetscValidPointer(mapping);
2633a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
26485614651SBarry Smith   if (mapping->refct < 0) {
26529bbc08cSBarry Smith     SETERRQ(1,"Mapping already destroyed");
26685614651SBarry Smith   }
26790f02eecSBarry Smith 
268606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
269606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
270b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
271d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2723a40ed3dSBarry Smith   PetscFunctionReturn(0);
27390f02eecSBarry Smith }
27490f02eecSBarry Smith 
2754a2ae208SSatish Balay #undef __FUNCT__
2764a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
27790f02eecSBarry Smith /*@
2783acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2793acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2803acfe500SLois Curfman McInnes     context.
28190f02eecSBarry Smith 
282b9cd556bSLois Curfman McInnes     Not collective
283b9cd556bSLois Curfman McInnes 
28490f02eecSBarry Smith     Input Parameters:
285b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
286b9cd556bSLois Curfman McInnes -   is - index set in local numbering
28790f02eecSBarry Smith 
28890f02eecSBarry Smith     Output Parameters:
28990f02eecSBarry Smith .   newis - index set in global numbering
29090f02eecSBarry Smith 
291a997ad1aSLois Curfman McInnes     Level: advanced
292a997ad1aSLois Curfman McInnes 
293273d9f13SBarry Smith     Concepts: mapping^local to global
2943acfe500SLois Curfman McInnes 
29590f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
296d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
29790f02eecSBarry Smith @*/
29890f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
29990f02eecSBarry Smith {
3003b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
3013a40ed3dSBarry Smith 
3023a40ed3dSBarry Smith   PetscFunctionBegin;
30390f02eecSBarry Smith   PetscValidPointer(mapping);
30490f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
30590f02eecSBarry Smith   PetscValidPointer(newis);
30690f02eecSBarry Smith 
3073b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
30890f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
30990f02eecSBarry Smith   idxmap = mapping->indices;
31090f02eecSBarry Smith 
311b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
31290f02eecSBarry Smith   for (i=0; i<n; i++) {
313590ac198SBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax-1,i);
31490f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
31590f02eecSBarry Smith   }
3163b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
317029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
318606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
3193a40ed3dSBarry Smith   PetscFunctionReturn(0);
32090f02eecSBarry Smith }
32190f02eecSBarry Smith 
32289d82c54SBarry Smith /*MC
3233acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3243acfe500SLois Curfman McInnes    and converts them to the global numbering.
32590f02eecSBarry Smith 
326b9cd556bSLois Curfman McInnes    Not collective
327b9cd556bSLois Curfman McInnes 
328bb25748dSBarry Smith    Input Parameters:
329b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
330bb25748dSBarry Smith .  N - number of integers
331b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
332bb25748dSBarry Smith 
333bb25748dSBarry Smith    Output Parameter:
334bb25748dSBarry Smith .  out - indices in global numbering
335bb25748dSBarry Smith 
3363b9aefa3SBarry Smith    Synopsis:
337216e7ba4SBarry Smith    int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
3383b9aefa3SBarry Smith 
339b9cd556bSLois Curfman McInnes    Notes:
340b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
341d4bb536fSBarry Smith 
342a997ad1aSLois Curfman McInnes    Level: advanced
343a997ad1aSLois Curfman McInnes 
344bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3450752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
346d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
347bb25748dSBarry Smith 
348273d9f13SBarry Smith     Concepts: mapping^local to global
349d4bb536fSBarry Smith 
35089d82c54SBarry Smith M*/
351d4bb536fSBarry Smith 
352d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
353d4bb536fSBarry Smith 
3544a2ae208SSatish Balay #undef __FUNCT__
3554a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
356d4bb536fSBarry Smith /*
357d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
358d4bb536fSBarry Smith */
359d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
360d4bb536fSBarry Smith {
361b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
362d4bb536fSBarry Smith 
3633a40ed3dSBarry Smith   PetscFunctionBegin;
364d4bb536fSBarry Smith   end   = 0;
365d4bb536fSBarry Smith   start = 100000000;
366d4bb536fSBarry Smith 
367d4bb536fSBarry Smith   for (i=0; i<n; i++) {
368d4bb536fSBarry Smith     if (idx[i] < 0) continue;
369d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
370d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
371d4bb536fSBarry Smith   }
372d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
373d4bb536fSBarry Smith   mapping->globalstart = start;
374d4bb536fSBarry Smith   mapping->globalend   = end;
375d4bb536fSBarry Smith 
376b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
377b0a32e0cSBarry Smith   mapping->globals = globals;
378d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
379d4bb536fSBarry Smith     globals[i] = -1;
380d4bb536fSBarry Smith   }
381d4bb536fSBarry Smith   for (i=0; i<n; i++) {
382d4bb536fSBarry Smith     if (idx[i] < 0) continue;
383d4bb536fSBarry Smith     globals[idx[i] - start] = i;
384d4bb536fSBarry Smith   }
385d4bb536fSBarry Smith 
386b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3873a40ed3dSBarry Smith   PetscFunctionReturn(0);
388d4bb536fSBarry Smith }
389d4bb536fSBarry Smith 
3904a2ae208SSatish Balay #undef __FUNCT__
3914a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
392d4bb536fSBarry Smith /*@
393a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
394a997ad1aSLois Curfman McInnes     specified with a global numbering.
395d4bb536fSBarry Smith 
396b9cd556bSLois Curfman McInnes     Not collective
397b9cd556bSLois Curfman McInnes 
398d4bb536fSBarry Smith     Input Parameters:
399b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
400d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
401d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
402d4bb536fSBarry Smith .   n - number of global indices to map
403b9cd556bSLois Curfman McInnes -   idx - global indices to map
404d4bb536fSBarry Smith 
405d4bb536fSBarry Smith     Output Parameters:
406b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
407b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
408e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
409e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
410e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
411e182c471SBarry Smith              a second time to set the values.
412d4bb536fSBarry Smith 
413b9cd556bSLois Curfman McInnes     Notes:
414b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
415d4bb536fSBarry Smith 
4160f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
4170f5bd95cSBarry Smith     array to compute these.
4180f5bd95cSBarry Smith 
419a997ad1aSLois Curfman McInnes     Level: advanced
420a997ad1aSLois Curfman McInnes 
421273d9f13SBarry Smith     Concepts: mapping^global to local
422d4bb536fSBarry Smith 
423d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
424d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
425d4bb536fSBarry Smith @*/
426d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
427987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
428d4bb536fSBarry Smith {
429d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
430d4bb536fSBarry Smith 
4313a40ed3dSBarry Smith   PetscFunctionBegin;
432d4bb536fSBarry Smith   if (!mapping->globals) {
433d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
434d4bb536fSBarry Smith   }
435d4bb536fSBarry Smith   globals = mapping->globals;
436d4bb536fSBarry Smith   start   = mapping->globalstart;
437d4bb536fSBarry Smith   end     = mapping->globalend;
438d4bb536fSBarry Smith 
439d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
440d4bb536fSBarry Smith     if (idxout) {
441d4bb536fSBarry Smith       for (i=0; i<n; i++) {
442d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
443d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
444d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
445d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
446d4bb536fSBarry Smith       }
447d4bb536fSBarry Smith     }
448d4bb536fSBarry Smith     if (nout) *nout = n;
449d4bb536fSBarry Smith   } else {
450d4bb536fSBarry Smith     if (idxout) {
451d4bb536fSBarry Smith       for (i=0; i<n; i++) {
452d4bb536fSBarry Smith         if (idx[i] < 0) continue;
453d4bb536fSBarry Smith         if (idx[i] < start) continue;
454d4bb536fSBarry Smith         if (idx[i] > end) continue;
455d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
456d4bb536fSBarry Smith         if (tmp < 0) continue;
457d4bb536fSBarry Smith         idxout[nf++] = tmp;
458d4bb536fSBarry Smith       }
459d4bb536fSBarry Smith     } else {
460d4bb536fSBarry Smith       for (i=0; i<n; i++) {
461d4bb536fSBarry Smith         if (idx[i] < 0) continue;
462d4bb536fSBarry Smith         if (idx[i] < start) continue;
463d4bb536fSBarry Smith         if (idx[i] > end) continue;
464d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
465d4bb536fSBarry Smith         if (tmp < 0) continue;
466d4bb536fSBarry Smith         nf++;
467d4bb536fSBarry Smith       }
468d4bb536fSBarry Smith     }
469d4bb536fSBarry Smith     if (nout) *nout = nf;
470d4bb536fSBarry Smith   }
471d4bb536fSBarry Smith 
4723a40ed3dSBarry Smith   PetscFunctionReturn(0);
473d4bb536fSBarry Smith }
47490f02eecSBarry Smith 
4754a2ae208SSatish Balay #undef __FUNCT__
4764a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
47789d82c54SBarry Smith /*@C
47889d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
47989d82c54SBarry Smith      each index shared by more than one processor
48089d82c54SBarry Smith 
48189d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
48289d82c54SBarry Smith 
48389d82c54SBarry Smith     Input Parameters:
48489d82c54SBarry Smith .   mapping - the mapping from local to global indexing
48589d82c54SBarry Smith 
48689d82c54SBarry Smith     Output Parameter:
48789d82c54SBarry Smith +   nproc - number of processors that are connected to this one
48889d82c54SBarry Smith .   proc - neighboring processors
48907b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
49007b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
49189d82c54SBarry Smith 
49289d82c54SBarry Smith     Level: advanced
49389d82c54SBarry Smith 
494273d9f13SBarry Smith     Concepts: mapping^local to global
49589d82c54SBarry Smith 
49607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
49707b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
49889d82c54SBarry Smith @*/
499*ca01db9bSBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int *procs[],int *numprocs[],int **indices[])
50089d82c54SBarry Smith {
501fa7fbcffSSatish Balay   int         i,n = mapping->n,ierr,Ng,ng,max = 0,*lindices = mapping->indices;
50227c402fcSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
50324cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
50407b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
50524cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
50689d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
50730dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
50889d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
50907b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
51089d82c54SBarry Smith 
51189d82c54SBarry Smith   PetscFunctionBegin;
51224cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
51324cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
51424cf384cSBarry Smith   if (size == 1) {
51524cf384cSBarry Smith     *nproc         = 0;
51624cf384cSBarry Smith     *procs         = PETSC_NULL;
517b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
5181e2105dcSBarry Smith     (*numprocs)[0] = 0;
519b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
5201e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
52124cf384cSBarry Smith     PetscFunctionReturn(0);
52224cf384cSBarry Smith   }
52324cf384cSBarry Smith 
524b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
52507b52d57SBarry Smith 
5263677ff5aSBarry Smith   /*
5273677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
5283677ff5aSBarry Smith 
5293677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
5303677ff5aSBarry Smith            numbering, just for this routine.
5313677ff5aSBarry Smith 
5323677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
5333677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
5343677ff5aSBarry Smith 
5353677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
5363677ff5aSBarry Smith 
5373677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
5383677ff5aSBarry Smith            local subdomain
5393677ff5aSBarry Smith   */
54024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
54124cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
54224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
54389d82c54SBarry Smith 
54489d82c54SBarry Smith   for (i=0; i<n; i++) {
54589d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
54689d82c54SBarry Smith   }
54789d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
54878058e43SBarry Smith   Ng++;
54989d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
55089d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
551bc8ff85bSBarry Smith   scale  = Ng/size + 1;
552a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
553caba0dd0SBarry Smith   rstart = scale*rank;
55489d82c54SBarry Smith 
55589d82c54SBarry Smith   /* determine ownership ranges of global indices */
556b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5572880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
55889d82c54SBarry Smith 
55989d82c54SBarry Smith   /* determine owners of each local node  */
560b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
56189d82c54SBarry Smith   for (i=0; i<n; i++) {
5623677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
56327c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
5643677ff5aSBarry Smith     owner[i]         = proc;
56527c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
56689d82c54SBarry Smith   }
56727c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
568b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
56989d82c54SBarry Smith 
57089d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
57127c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
572b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
57389d82c54SBarry Smith 
57489d82c54SBarry Smith   /* post receives for owned rows */
575b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
576b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
57789d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
57824cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
57989d82c54SBarry Smith   }
58089d82c54SBarry Smith 
58189d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
582b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
583b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
58489d82c54SBarry Smith   starts[0]  = 0;
58527c402fcSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];}
58689d82c54SBarry Smith   for (i=0; i<n; i++) {
58789d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
58830dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
58989d82c54SBarry Smith   }
59089d82c54SBarry Smith   ierr = PetscFree(owner);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 
59489d82c54SBarry Smith   /* send the messages */
595b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
596b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
59789d82c54SBarry Smith   cnt = 0;
59889d82c54SBarry Smith   for (i=0; i<size; i++) {
59927c402fcSBarry Smith     if (nprocs[2*i]) {
60027c402fcSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
60130dcb7c9SBarry Smith       dest[cnt] = i;
60289d82c54SBarry Smith       cnt++;
60389d82c54SBarry Smith     }
60489d82c54SBarry Smith   }
60589d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
60689d82c54SBarry Smith 
60789d82c54SBarry Smith   /* wait on receives */
608b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
60989d82c54SBarry Smith   len  = source + nrecvs;
61089d82c54SBarry Smith   cnt  = nrecvs;
611b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
612caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
61389d82c54SBarry Smith   while (cnt) {
61489d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
61589d82c54SBarry Smith     /* unpack receives into our local space */
61689d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
61789d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
61830dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
619caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
62030dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
62189d82c54SBarry Smith     cnt--;
62289d82c54SBarry Smith   }
62389d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
62489d82c54SBarry Smith 
62530dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
626bc8ff85bSBarry Smith   nowned  = 0;
627bc8ff85bSBarry Smith   nownedm = 0;
628bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
629bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
630bc8ff85bSBarry Smith   }
631bc8ff85bSBarry Smith 
632bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
633b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
634b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
635bc8ff85bSBarry Smith   starts[0] = 0;
636bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
637bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
638bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
639bc8ff85bSBarry Smith   }
640bc8ff85bSBarry Smith 
64130dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
642bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
643bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
64430dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
645bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
646bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
647bc8ff85bSBarry Smith       }
648bc8ff85bSBarry Smith     }
649bc8ff85bSBarry Smith   }
650bc8ff85bSBarry Smith 
65107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
65230dcb7c9SBarry Smith     starts[0]    = 0;
65330dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
65430dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
65530dcb7c9SBarry Smith       else starts[i] = starts[i-1];
65630dcb7c9SBarry Smith     }
65730dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
65830dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
65930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
66030dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
66130dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
66230dcb7c9SBarry Smith         }
66330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
66430dcb7c9SBarry Smith       }
66530dcb7c9SBarry Smith     }
66630dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
66707b52d57SBarry Smith   }/* -----------------------------------  */
66830dcb7c9SBarry Smith 
6693677ff5aSBarry Smith   /* wait on original sends */
6703a96401aSBarry Smith   if (nsends) {
671b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6723a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6733a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6743a96401aSBarry Smith   }
67589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6763a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6773677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6783677ff5aSBarry Smith 
6793677ff5aSBarry Smith   /* pack messages to send back to local owners */
68030dcb7c9SBarry Smith   starts[0]    = 0;
68130dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
68230dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
68330dcb7c9SBarry Smith     else starts[i] = starts[i-1];
68430dcb7c9SBarry Smith   }
68530dcb7c9SBarry Smith   nsends2 = nrecvs;
686b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
68730dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
68830dcb7c9SBarry Smith     nprocs[i] = 1;
68930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
69030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
69130dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
69230dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
69330dcb7c9SBarry Smith       }
69430dcb7c9SBarry Smith     }
69530dcb7c9SBarry Smith   }
69630dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
697b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
698b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
69930dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
70030dcb7c9SBarry Smith   /*
70130dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
70230dcb7c9SBarry Smith        (0) the number of nodes being sent back
70330dcb7c9SBarry Smith        (1) the local node number,
70430dcb7c9SBarry Smith        (2) the number of processors sharing it,
70530dcb7c9SBarry Smith        (3) the processors sharing it
70630dcb7c9SBarry Smith   */
70730dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
70830dcb7c9SBarry Smith     cnt = 1;
70930dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
71030dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
71130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
71230dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
71330dcb7c9SBarry Smith         sends2[starts2[i]]++;
71430dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
71530dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
71630dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
71730dcb7c9SBarry Smith         cnt += nownedsenders[node];
71830dcb7c9SBarry Smith       }
71930dcb7c9SBarry Smith     }
72030dcb7c9SBarry Smith   }
72130dcb7c9SBarry Smith 
72230dcb7c9SBarry Smith   /* send the message lengths */
72330dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
72424cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
72530dcb7c9SBarry Smith   }
72630dcb7c9SBarry Smith 
72730dcb7c9SBarry Smith   /* receive the message lengths */
72830dcb7c9SBarry Smith   nrecvs2 = nsends;
729b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
730b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
73130dcb7c9SBarry Smith   nt      = 0;
73230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
73324cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
73430dcb7c9SBarry Smith     nt   += lens2[i];
73530dcb7c9SBarry Smith   }
73630dcb7c9SBarry Smith   starts3[0] = 0;
73730dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
73830dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
73930dcb7c9SBarry Smith   }
740b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
741b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
74252b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
74324cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
74430dcb7c9SBarry Smith   }
74530dcb7c9SBarry Smith 
74630dcb7c9SBarry Smith   /* send the messages */
747b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
74830dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
74924cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
75030dcb7c9SBarry Smith   }
75130dcb7c9SBarry Smith 
75230dcb7c9SBarry Smith   /* wait on receives */
753b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
75430dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
75530dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
75630dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
75730dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
75830dcb7c9SBarry Smith 
75907b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
76030dcb7c9SBarry Smith     cnt = 0;
76130dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
76230dcb7c9SBarry Smith       nt = recvs2[cnt++];
76330dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
76430dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
76530dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
76630dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
76730dcb7c9SBarry Smith         }
76830dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
76930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
77030dcb7c9SBarry Smith       }
77130dcb7c9SBarry Smith     }
77230dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
77307b52d57SBarry Smith   } /* -----------------------------------  */
77430dcb7c9SBarry Smith 
77530dcb7c9SBarry Smith   /* count number subdomains for each local node */
776b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
77730dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
77830dcb7c9SBarry Smith   cnt  = 0;
77930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
78030dcb7c9SBarry Smith     nt = recvs2[cnt++];
78130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
78230dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
78330dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
78430dcb7c9SBarry Smith       }
78530dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
78630dcb7c9SBarry Smith     }
78730dcb7c9SBarry Smith   }
78830dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
78930dcb7c9SBarry Smith   *nproc    = nt;
790b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
791b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
792b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
793b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
79430dcb7c9SBarry Smith   cnt       = 0;
79530dcb7c9SBarry Smith   for (i=0; i<size; i++) {
79630dcb7c9SBarry Smith     if (nprocs[i] > 0) {
79730dcb7c9SBarry Smith       bprocs[i]        = cnt;
79830dcb7c9SBarry Smith       (*procs)[cnt]    = i;
79930dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
800b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
80130dcb7c9SBarry Smith       cnt++;
80230dcb7c9SBarry Smith     }
80330dcb7c9SBarry Smith   }
80430dcb7c9SBarry Smith 
80530dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
80630dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
80730dcb7c9SBarry Smith   cnt  = 0;
80830dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
80930dcb7c9SBarry Smith     nt = recvs2[cnt++];
81030dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
81130dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
81230dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
81330dcb7c9SBarry Smith       }
81430dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
81530dcb7c9SBarry Smith     }
81630dcb7c9SBarry Smith   }
81730dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
81807b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
81930dcb7c9SBarry Smith 
82007b52d57SBarry Smith   /* sort the node indexing by their global numbers */
82107b52d57SBarry Smith   nt = *nproc;
82207b52d57SBarry Smith   for (i=0; i<nt; i++) {
823b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
82407b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
82507b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
82607b52d57SBarry Smith     }
82707b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
82807b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
82907b52d57SBarry Smith   }
83007b52d57SBarry Smith 
83107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
83230dcb7c9SBarry Smith     nt = *nproc;
83330dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
83430dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
83530dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
83630dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
83730dcb7c9SBarry Smith       }
83830dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
83930dcb7c9SBarry Smith     }
84030dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
84107b52d57SBarry Smith   } /* -----------------------------------  */
84230dcb7c9SBarry Smith 
84330dcb7c9SBarry Smith   /* wait on sends */
84430dcb7c9SBarry Smith   if (nsends2) {
845b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
84630dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
84730dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
84830dcb7c9SBarry Smith   }
84930dcb7c9SBarry Smith 
85030dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
85130dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
85230dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8533677ff5aSBarry Smith 
854bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
855bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
856bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
85730dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
85830dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
85989d82c54SBarry Smith 
86089d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
86189d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8623a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
86330dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
86424cf384cSBarry Smith 
86524cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
86624cf384cSBarry Smith   first_procs    = (*procs)[0];
86724cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
86824cf384cSBarry Smith   first_indices  = (*indices)[0];
86924cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
87024cf384cSBarry Smith     if ((*procs)[i] == rank) {
87124cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
87224cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
87324cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
87424cf384cSBarry Smith       (*procs)[i]    = first_procs;
87524cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
87624cf384cSBarry Smith       (*indices)[i]  = first_indices;
87724cf384cSBarry Smith       break;
87824cf384cSBarry Smith     }
87924cf384cSBarry Smith   }
88024cf384cSBarry Smith 
88189d82c54SBarry Smith   PetscFunctionReturn(0);
88289d82c54SBarry Smith }
88389d82c54SBarry Smith 
8844a2ae208SSatish Balay #undef __FUNCT__
8854a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
88607b52d57SBarry Smith /*@C
88707b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
88889d82c54SBarry Smith 
88907b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
89007b52d57SBarry Smith 
89107b52d57SBarry Smith     Input Parameters:
89207b52d57SBarry Smith .   mapping - the mapping from local to global indexing
89307b52d57SBarry Smith 
89407b52d57SBarry Smith     Output Parameter:
89507b52d57SBarry Smith +   nproc - number of processors that are connected to this one
89607b52d57SBarry Smith .   proc - neighboring processors
89707b52d57SBarry Smith .   numproc - number of indices for each processor
89807b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
89907b52d57SBarry Smith 
90007b52d57SBarry Smith     Level: advanced
90107b52d57SBarry Smith 
90207b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
90307b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
90407b52d57SBarry Smith @*/
905*ca01db9bSBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int *procs[],int *numprocs[],int **indices[])
90607b52d57SBarry Smith {
90707b52d57SBarry Smith   int ierr,i;
90807b52d57SBarry Smith 
90907b52d57SBarry Smith   PetscFunctionBegin;
91000ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
91100ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
91200ff320aSBarry Smith   if (*indices) {
91300ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
91400ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
91524cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
91607b52d57SBarry Smith     }
91707b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
91824cf384cSBarry Smith   }
91907b52d57SBarry Smith   PetscFunctionReturn(0);
92007b52d57SBarry Smith }
92189d82c54SBarry Smith 
922bc8ff85bSBarry Smith 
923bc8ff85bSBarry Smith 
924bc8ff85bSBarry Smith 
925bc8ff85bSBarry Smith 
926bc8ff85bSBarry Smith 
927bc8ff85bSBarry Smith 
928bc8ff85bSBarry Smith 
929bc8ff85bSBarry Smith 
930bc8ff85bSBarry Smith 
931bc8ff85bSBarry Smith 
932bc8ff85bSBarry Smith 
933bc8ff85bSBarry Smith 
934bc8ff85bSBarry Smith 
935bc8ff85bSBarry Smith 
936bc8ff85bSBarry Smith 
937bc8ff85bSBarry Smith 
93824cf384cSBarry Smith 
939