xref: /petsc/src/vec/is/utils/isltog.c (revision b46b645b3d6c4791200e90736b38fd1bcaac9d8f)
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 
113*b46b645bSBarry 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 
134*b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreateNC()
1352362add9SBarry Smith @*/
136987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
1372362add9SBarry Smith {
138*b46b645bSBarry Smith   int *in,ierr;
139*b46b645bSBarry Smith 
140*b46b645bSBarry Smith   PetscFunctionBegin;
141*b46b645bSBarry Smith   PetscValidIntPointer(indices);
142*b46b645bSBarry Smith   PetscValidPointer(mapping);
143*b46b645bSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&in);CHKERRQ(ierr);
144*b46b645bSBarry Smith   ierr = PetscMemcpy(in,indices,n*sizeof(int));CHKERRQ(ierr);
145*b46b645bSBarry Smith   ierr = ISLocalToGlobalMappingCreateNC(cm,n,in,mapping);CHKERRQ(ierr);
146*b46b645bSBarry Smith   PetscFunctionReturn(0);
147*b46b645bSBarry Smith }
148*b46b645bSBarry Smith 
149*b46b645bSBarry Smith #undef __FUNCT__
150*b46b645bSBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingCreateNC"
151*b46b645bSBarry Smith /*@C
152*b46b645bSBarry Smith     ISLocalToGlobalMappingCreateNC - Creates a mapping between a local (0 to n)
153*b46b645bSBarry Smith     ordering and a global parallel ordering.
154*b46b645bSBarry Smith 
155*b46b645bSBarry Smith     Not Collective, but communicator may have more than one process
156*b46b645bSBarry Smith 
157*b46b645bSBarry Smith     Input Parameters:
158*b46b645bSBarry Smith +   comm - MPI communicator
159*b46b645bSBarry Smith .   n - the number of local elements
160*b46b645bSBarry Smith -   indices - the global index for each local element
161*b46b645bSBarry Smith 
162*b46b645bSBarry Smith     Output Parameter:
163*b46b645bSBarry Smith .   mapping - new mapping data structure
164*b46b645bSBarry Smith 
165*b46b645bSBarry Smith     Level: developer
166*b46b645bSBarry Smith 
167*b46b645bSBarry Smith     Notes: Does not copy the indices, just keeps the pointer to the indices. The ISLocalToGlobalMappingDestroy()
168*b46b645bSBarry Smith     will free the space so it must be obtained with PetscMalloc() and it must not be freed elsewhere.
169*b46b645bSBarry Smith 
170*b46b645bSBarry Smith     Concepts: mapping^local to global
171*b46b645bSBarry Smith 
172*b46b645bSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate()
173*b46b645bSBarry Smith @*/
174*b46b645bSBarry Smith int ISLocalToGlobalMappingCreateNC(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
175*b46b645bSBarry Smith {
176549d3d68SSatish Balay   int ierr;
177549d3d68SSatish Balay 
1783a40ed3dSBarry Smith   PetscFunctionBegin;
17990f02eecSBarry Smith   PetscValidIntPointer(indices);
18090f02eecSBarry Smith   PetscValidPointer(mapping);
1818e58c17dSMatthew Knepley   *mapping = PETSC_NULL;
1828e58c17dSMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
1838e58c17dSMatthew Knepley   ierr = VecInitializePackage(PETSC_NULL);                                                                CHKERRQ(ierr);
1848e58c17dSMatthew Knepley #endif
1852362add9SBarry Smith 
1863f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1873f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
188b0a32e0cSBarry Smith   PetscLogObjectCreate(*mapping);
189b0a32e0cSBarry Smith   PetscLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
190d4bb536fSBarry Smith 
191d4bb536fSBarry Smith   (*mapping)->n       = n;
192*b46b645bSBarry Smith   (*mapping)->indices = (int*)indices;
193d4bb536fSBarry Smith 
194d4bb536fSBarry Smith   /*
195d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
196d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
197d4bb536fSBarry Smith   */
198d4bb536fSBarry Smith   (*mapping)->globals = 0;
1993a40ed3dSBarry Smith   PetscFunctionReturn(0);
2002362add9SBarry Smith }
2012362add9SBarry Smith 
2024a2ae208SSatish Balay #undef __FUNCT__
2034a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
204323b833fSBarry Smith /*@C
205323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
206323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
207323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
208323b833fSBarry Smith 
209323b833fSBarry Smith     Not Collective, but communicator may have more than one process
210323b833fSBarry Smith 
211323b833fSBarry Smith     Input Parameters:
212323b833fSBarry Smith +    inmap - original point-wise mapping
213323b833fSBarry Smith -    bs - block size
214323b833fSBarry Smith 
215323b833fSBarry Smith     Output Parameter:
216323b833fSBarry Smith .   outmap - block based mapping
217323b833fSBarry Smith 
218323b833fSBarry Smith     Level: advanced
219323b833fSBarry Smith 
220323b833fSBarry Smith     Concepts: mapping^local to global
221323b833fSBarry Smith 
222323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
223323b833fSBarry Smith @*/
224323b833fSBarry Smith int ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,int bs,ISLocalToGlobalMapping *outmap)
225323b833fSBarry Smith {
226323b833fSBarry Smith   int ierr,*ii,i,n;
227323b833fSBarry Smith 
228323b833fSBarry Smith   PetscFunctionBegin;
229323b833fSBarry Smith 
230323b833fSBarry Smith   if (bs > 1) {
231323b833fSBarry Smith     n    = inmap->n/bs;
232323b833fSBarry Smith     ierr = PetscMalloc(n*sizeof(int),&ii);CHKERRQ(ierr);
233323b833fSBarry Smith     for (i=0; i<n; i++) {
234b8ee7809SBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
235323b833fSBarry Smith     }
236323b833fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(inmap->comm,n,ii,outmap);CHKERRQ(ierr);
237323b833fSBarry Smith     ierr = PetscFree(ii);CHKERRQ(ierr);
238323b833fSBarry Smith   } else {
239323b833fSBarry Smith     *outmap = inmap;
240323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
241323b833fSBarry Smith   }
242323b833fSBarry Smith   PetscFunctionReturn(0);
243323b833fSBarry Smith }
244323b833fSBarry Smith 
2454a2ae208SSatish Balay #undef __FUNCT__
2464a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
24790f02eecSBarry Smith /*@
24890f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
24990f02eecSBarry Smith    ordering and a global parallel ordering.
25090f02eecSBarry Smith 
2510f5bd95cSBarry Smith    Note Collective
252b9cd556bSLois Curfman McInnes 
25390f02eecSBarry Smith    Input Parameters:
25490f02eecSBarry Smith .  mapping - mapping data structure
25590f02eecSBarry Smith 
256a997ad1aSLois Curfman McInnes    Level: advanced
257a997ad1aSLois Curfman McInnes 
2583acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
25990f02eecSBarry Smith @*/
26090f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
26190f02eecSBarry Smith {
262606d414cSSatish Balay   int ierr;
2633a40ed3dSBarry Smith   PetscFunctionBegin;
26490f02eecSBarry Smith   PetscValidPointer(mapping);
2653a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
26685614651SBarry Smith   if (mapping->refct < 0) {
26729bbc08cSBarry Smith     SETERRQ(1,"Mapping already destroyed");
26885614651SBarry Smith   }
26990f02eecSBarry Smith 
270606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
271606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
272b0a32e0cSBarry Smith   PetscLogObjectDestroy(mapping);
273d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
2743a40ed3dSBarry Smith   PetscFunctionReturn(0);
27590f02eecSBarry Smith }
27690f02eecSBarry Smith 
2774a2ae208SSatish Balay #undef __FUNCT__
2784a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
27990f02eecSBarry Smith /*@
2803acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2813acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2823acfe500SLois Curfman McInnes     context.
28390f02eecSBarry Smith 
284b9cd556bSLois Curfman McInnes     Not collective
285b9cd556bSLois Curfman McInnes 
28690f02eecSBarry Smith     Input Parameters:
287b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
288b9cd556bSLois Curfman McInnes -   is - index set in local numbering
28990f02eecSBarry Smith 
29090f02eecSBarry Smith     Output Parameters:
29190f02eecSBarry Smith .   newis - index set in global numbering
29290f02eecSBarry Smith 
293a997ad1aSLois Curfman McInnes     Level: advanced
294a997ad1aSLois Curfman McInnes 
295273d9f13SBarry Smith     Concepts: mapping^local to global
2963acfe500SLois Curfman McInnes 
29790f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
298d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
29990f02eecSBarry Smith @*/
30090f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
30190f02eecSBarry Smith {
3023b9aefa3SBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n;
3033a40ed3dSBarry Smith 
3043a40ed3dSBarry Smith   PetscFunctionBegin;
30590f02eecSBarry Smith   PetscValidPointer(mapping);
30690f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
30790f02eecSBarry Smith   PetscValidPointer(newis);
30890f02eecSBarry Smith 
3093b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
31090f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
31190f02eecSBarry Smith   idxmap = mapping->indices;
31290f02eecSBarry Smith 
313b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&idxout);CHKERRQ(ierr);
31490f02eecSBarry Smith   for (i=0; i<n; i++) {
31529bbc08cSBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i);
31690f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
31790f02eecSBarry Smith   }
3183b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
319029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
320606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
3213a40ed3dSBarry Smith   PetscFunctionReturn(0);
32290f02eecSBarry Smith }
32390f02eecSBarry Smith 
32489d82c54SBarry Smith /*MC
3253acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3263acfe500SLois Curfman McInnes    and converts them to the global numbering.
32790f02eecSBarry Smith 
328b9cd556bSLois Curfman McInnes    Not collective
329b9cd556bSLois Curfman McInnes 
330bb25748dSBarry Smith    Input Parameters:
331b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
332bb25748dSBarry Smith .  N - number of integers
333b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
334bb25748dSBarry Smith 
335bb25748dSBarry Smith    Output Parameter:
336bb25748dSBarry Smith .  out - indices in global numbering
337bb25748dSBarry Smith 
3383b9aefa3SBarry Smith    Synopsis:
339216e7ba4SBarry Smith    int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
3403b9aefa3SBarry Smith 
341b9cd556bSLois Curfman McInnes    Notes:
342b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
343d4bb536fSBarry Smith 
344a997ad1aSLois Curfman McInnes    Level: advanced
345a997ad1aSLois Curfman McInnes 
346bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3470752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
348d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
349bb25748dSBarry Smith 
350273d9f13SBarry Smith     Concepts: mapping^local to global
351d4bb536fSBarry Smith 
35289d82c54SBarry Smith M*/
353d4bb536fSBarry Smith 
354d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
355d4bb536fSBarry Smith 
3564a2ae208SSatish Balay #undef __FUNCT__
3574a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
358d4bb536fSBarry Smith /*
359d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
360d4bb536fSBarry Smith */
361d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
362d4bb536fSBarry Smith {
363b0a32e0cSBarry Smith   int ierr,i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
364d4bb536fSBarry Smith 
3653a40ed3dSBarry Smith   PetscFunctionBegin;
366d4bb536fSBarry Smith   end   = 0;
367d4bb536fSBarry Smith   start = 100000000;
368d4bb536fSBarry Smith 
369d4bb536fSBarry Smith   for (i=0; i<n; i++) {
370d4bb536fSBarry Smith     if (idx[i] < 0) continue;
371d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
372d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
373d4bb536fSBarry Smith   }
374d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
375d4bb536fSBarry Smith   mapping->globalstart = start;
376d4bb536fSBarry Smith   mapping->globalend   = end;
377d4bb536fSBarry Smith 
378b0a32e0cSBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(int),&globals);CHKERRQ(ierr);
379b0a32e0cSBarry Smith   mapping->globals = globals;
380d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
381d4bb536fSBarry Smith     globals[i] = -1;
382d4bb536fSBarry Smith   }
383d4bb536fSBarry Smith   for (i=0; i<n; i++) {
384d4bb536fSBarry Smith     if (idx[i] < 0) continue;
385d4bb536fSBarry Smith     globals[idx[i] - start] = i;
386d4bb536fSBarry Smith   }
387d4bb536fSBarry Smith 
388b0a32e0cSBarry Smith   PetscLogObjectMemory(mapping,(end-start+1)*sizeof(int));
3893a40ed3dSBarry Smith   PetscFunctionReturn(0);
390d4bb536fSBarry Smith }
391d4bb536fSBarry Smith 
3924a2ae208SSatish Balay #undef __FUNCT__
3934a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
394d4bb536fSBarry Smith /*@
395a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
396a997ad1aSLois Curfman McInnes     specified with a global numbering.
397d4bb536fSBarry Smith 
398b9cd556bSLois Curfman McInnes     Not collective
399b9cd556bSLois Curfman McInnes 
400d4bb536fSBarry Smith     Input Parameters:
401b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
402d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
403d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
404d4bb536fSBarry Smith .   n - number of global indices to map
405b9cd556bSLois Curfman McInnes -   idx - global indices to map
406d4bb536fSBarry Smith 
407d4bb536fSBarry Smith     Output Parameters:
408b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
409b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
410e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
411e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
412e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
413e182c471SBarry Smith              a second time to set the values.
414d4bb536fSBarry Smith 
415b9cd556bSLois Curfman McInnes     Notes:
416b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
417d4bb536fSBarry Smith 
4180f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
4190f5bd95cSBarry Smith     array to compute these.
4200f5bd95cSBarry Smith 
421a997ad1aSLois Curfman McInnes     Level: advanced
422a997ad1aSLois Curfman McInnes 
423273d9f13SBarry Smith     Concepts: mapping^global to local
424d4bb536fSBarry Smith 
425d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
426d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
427d4bb536fSBarry Smith @*/
428d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
429987e4450SSatish Balay                                   int n,const int idx[],int *nout,int idxout[])
430d4bb536fSBarry Smith {
431d4bb536fSBarry Smith   int i,ierr,*globals,nf = 0,tmp,start,end;
432d4bb536fSBarry Smith 
4333a40ed3dSBarry Smith   PetscFunctionBegin;
434d4bb536fSBarry Smith   if (!mapping->globals) {
435d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
436d4bb536fSBarry Smith   }
437d4bb536fSBarry Smith   globals = mapping->globals;
438d4bb536fSBarry Smith   start   = mapping->globalstart;
439d4bb536fSBarry Smith   end     = mapping->globalend;
440d4bb536fSBarry Smith 
441d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
442d4bb536fSBarry Smith     if (idxout) {
443d4bb536fSBarry Smith       for (i=0; i<n; i++) {
444d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
445d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
446d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
447d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
448d4bb536fSBarry Smith       }
449d4bb536fSBarry Smith     }
450d4bb536fSBarry Smith     if (nout) *nout = n;
451d4bb536fSBarry Smith   } else {
452d4bb536fSBarry Smith     if (idxout) {
453d4bb536fSBarry Smith       for (i=0; i<n; i++) {
454d4bb536fSBarry Smith         if (idx[i] < 0) continue;
455d4bb536fSBarry Smith         if (idx[i] < start) continue;
456d4bb536fSBarry Smith         if (idx[i] > end) continue;
457d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
458d4bb536fSBarry Smith         if (tmp < 0) continue;
459d4bb536fSBarry Smith         idxout[nf++] = tmp;
460d4bb536fSBarry Smith       }
461d4bb536fSBarry Smith     } else {
462d4bb536fSBarry Smith       for (i=0; i<n; i++) {
463d4bb536fSBarry Smith         if (idx[i] < 0) continue;
464d4bb536fSBarry Smith         if (idx[i] < start) continue;
465d4bb536fSBarry Smith         if (idx[i] > end) continue;
466d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
467d4bb536fSBarry Smith         if (tmp < 0) continue;
468d4bb536fSBarry Smith         nf++;
469d4bb536fSBarry Smith       }
470d4bb536fSBarry Smith     }
471d4bb536fSBarry Smith     if (nout) *nout = nf;
472d4bb536fSBarry Smith   }
473d4bb536fSBarry Smith 
4743a40ed3dSBarry Smith   PetscFunctionReturn(0);
475d4bb536fSBarry Smith }
47690f02eecSBarry Smith 
4774a2ae208SSatish Balay #undef __FUNCT__
4784a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
47989d82c54SBarry Smith /*@C
48089d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
48189d82c54SBarry Smith      each index shared by more than one processor
48289d82c54SBarry Smith 
48389d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
48489d82c54SBarry Smith 
48589d82c54SBarry Smith     Input Parameters:
48689d82c54SBarry Smith .   mapping - the mapping from local to global indexing
48789d82c54SBarry Smith 
48889d82c54SBarry Smith     Output Parameter:
48989d82c54SBarry Smith +   nproc - number of processors that are connected to this one
49089d82c54SBarry Smith .   proc - neighboring processors
49107b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
49207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
49389d82c54SBarry Smith 
49489d82c54SBarry Smith     Level: advanced
49589d82c54SBarry Smith 
496273d9f13SBarry Smith     Concepts: mapping^local to global
49789d82c54SBarry Smith 
49807b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
49907b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
50089d82c54SBarry Smith @*/
50130dcb7c9SBarry Smith int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
50289d82c54SBarry Smith {
503fa7fbcffSSatish Balay   int         i,n = mapping->n,ierr,Ng,ng,max = 0,*lindices = mapping->indices;
5043a96401aSBarry Smith   int         size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc;
50524cf384cSBarry Smith   int         tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned;
50607b52d57SBarry Smith   int         node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
50724cf384cSBarry Smith   int         first_procs,first_numprocs,*first_indices;
50889d82c54SBarry Smith   MPI_Request *recv_waits,*send_waits;
50930dcb7c9SBarry Smith   MPI_Status  recv_status,*send_status,*recv_statuses;
51089d82c54SBarry Smith   MPI_Comm    comm = mapping->comm;
51107b52d57SBarry Smith   PetscTruth  debug = PETSC_FALSE;
51289d82c54SBarry Smith 
51389d82c54SBarry Smith   PetscFunctionBegin;
51424cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
51524cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
51624cf384cSBarry Smith   if (size == 1) {
51724cf384cSBarry Smith     *nproc         = 0;
51824cf384cSBarry Smith     *procs         = PETSC_NULL;
519b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int),numprocs);CHKERRQ(ierr);
5201e2105dcSBarry Smith     (*numprocs)[0] = 0;
521b0a32e0cSBarry Smith     ierr           = PetscMalloc(sizeof(int*),indices);CHKERRQ(ierr);
5221e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
52324cf384cSBarry Smith     PetscFunctionReturn(0);
52424cf384cSBarry Smith   }
52524cf384cSBarry Smith 
526b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr);
52707b52d57SBarry Smith 
5283677ff5aSBarry Smith   /*
5293677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
5303677ff5aSBarry Smith 
5313677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
5323677ff5aSBarry Smith            numbering, just for this routine.
5333677ff5aSBarry Smith 
5343677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
5353677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
5363677ff5aSBarry Smith 
5373677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
5383677ff5aSBarry Smith 
5393677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
5403677ff5aSBarry Smith            local subdomain
5413677ff5aSBarry Smith   */
54224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
54324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
54424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
54589d82c54SBarry Smith 
54689d82c54SBarry Smith   for (i=0; i<n; i++) {
54789d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
54889d82c54SBarry Smith   }
54989d82c54SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
55078058e43SBarry Smith   Ng++;
55189d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
55289d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
553bc8ff85bSBarry Smith   scale  = Ng/size + 1;
554a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
555caba0dd0SBarry Smith   rstart = scale*rank;
55689d82c54SBarry Smith 
55789d82c54SBarry Smith   /* determine ownership ranges of global indices */
558b0a32e0cSBarry Smith   ierr = PetscMalloc((2*size+1)*sizeof(int),&nprocs);CHKERRQ(ierr);
5592880cf29SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr);
56089d82c54SBarry Smith 
56189d82c54SBarry Smith   /* determine owners of each local node  */
562b0a32e0cSBarry Smith   ierr = PetscMalloc((n+1)*sizeof(int),&owner);CHKERRQ(ierr);
56389d82c54SBarry Smith   for (i=0; i<n; i++) {
5643677ff5aSBarry Smith     proc              = lindices[i]/scale; /* processor that globally owns this index */
5653677ff5aSBarry Smith     nprocs[size+proc] = 1;                 /* processor globally owns at least one of ours */
5663677ff5aSBarry Smith     owner[i]          = proc;
5673677ff5aSBarry Smith     nprocs[proc]++;                        /* count of how many that processor globally owns of ours */
56889d82c54SBarry Smith   }
56989d82c54SBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i];
570b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends);
57189d82c54SBarry Smith 
57289d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
573b0a32e0cSBarry Smith   ierr = PetscMalloc(2*size*sizeof(int),&work);CHKERRQ(ierr);
57489d82c54SBarry Smith   ierr   = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
57589d82c54SBarry Smith   nmax   = work[rank];
57689d82c54SBarry Smith   nrecvs = work[size+rank];
57789d82c54SBarry Smith   ierr   = PetscFree(work);CHKERRQ(ierr);
578b0a32e0cSBarry Smith   PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs);
57989d82c54SBarry Smith 
58089d82c54SBarry Smith   /* post receives for owned rows */
581b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr);
582b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
58389d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
58424cf384cSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
58589d82c54SBarry Smith   }
58689d82c54SBarry Smith 
58789d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
588b0a32e0cSBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr);
589b0a32e0cSBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr);
59089d82c54SBarry Smith   starts[0]  = 0;
59130dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
59289d82c54SBarry Smith   for (i=0; i<n; i++) {
59389d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
59430dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
59589d82c54SBarry Smith   }
59689d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
59789d82c54SBarry Smith   starts[0]  = 0;
59830dcb7c9SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];}
59989d82c54SBarry Smith 
60089d82c54SBarry Smith   /* send the messages */
601b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
602b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr);
60389d82c54SBarry Smith   cnt = 0;
60489d82c54SBarry Smith   for (i=0; i<size; i++) {
60589d82c54SBarry Smith     if (nprocs[i]) {
60624cf384cSBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
60730dcb7c9SBarry Smith       dest[cnt] = i;
60889d82c54SBarry Smith       cnt++;
60989d82c54SBarry Smith     }
61089d82c54SBarry Smith   }
61189d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
61289d82c54SBarry Smith 
61389d82c54SBarry Smith   /* wait on receives */
614b0a32e0cSBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr);
61589d82c54SBarry Smith   len  = source + nrecvs;
61689d82c54SBarry Smith   cnt  = nrecvs;
617b0a32e0cSBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr);
618caba0dd0SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr);
61989d82c54SBarry Smith   while (cnt) {
62089d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
62189d82c54SBarry Smith     /* unpack receives into our local space */
62289d82c54SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr);
62389d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
62430dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
625caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
62630dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
62789d82c54SBarry Smith     cnt--;
62889d82c54SBarry Smith   }
62989d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
63089d82c54SBarry Smith 
63130dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
632bc8ff85bSBarry Smith   nowned  = 0;
633bc8ff85bSBarry Smith   nownedm = 0;
634bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
635bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
636bc8ff85bSBarry Smith   }
637bc8ff85bSBarry Smith 
638bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
639b0a32e0cSBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr);
640b0a32e0cSBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr);
641bc8ff85bSBarry Smith   starts[0] = 0;
642bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
643bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
644bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
645bc8ff85bSBarry Smith   }
646bc8ff85bSBarry Smith 
64730dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
648bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
649bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
65030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
651bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
652bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
653bc8ff85bSBarry Smith       }
654bc8ff85bSBarry Smith     }
655bc8ff85bSBarry Smith   }
656bc8ff85bSBarry Smith 
65707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
65830dcb7c9SBarry Smith     starts[0]    = 0;
65930dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
66030dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
66130dcb7c9SBarry Smith       else starts[i] = starts[i-1];
66230dcb7c9SBarry Smith     }
66330dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
66430dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
66530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
66630dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
66730dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
66830dcb7c9SBarry Smith         }
66930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
67030dcb7c9SBarry Smith       }
67130dcb7c9SBarry Smith     }
67230dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
67307b52d57SBarry Smith   }/* -----------------------------------  */
67430dcb7c9SBarry Smith 
6753677ff5aSBarry Smith   /* wait on original sends */
6763a96401aSBarry Smith   if (nsends) {
677b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6783a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6793a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6803a96401aSBarry Smith   }
68189d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6823a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6833677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6843677ff5aSBarry Smith 
6853677ff5aSBarry Smith   /* pack messages to send back to local owners */
68630dcb7c9SBarry Smith   starts[0]    = 0;
68730dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
68830dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
68930dcb7c9SBarry Smith     else starts[i] = starts[i-1];
69030dcb7c9SBarry Smith   }
69130dcb7c9SBarry Smith   nsends2 = nrecvs;
692b0a32e0cSBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */
69330dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
69430dcb7c9SBarry Smith     nprocs[i] = 1;
69530dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
69630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
69730dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
69830dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
69930dcb7c9SBarry Smith       }
70030dcb7c9SBarry Smith     }
70130dcb7c9SBarry Smith   }
70230dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
703b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr);
704b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr);
70530dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
70630dcb7c9SBarry Smith   /*
70730dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
70830dcb7c9SBarry Smith        (0) the number of nodes being sent back
70930dcb7c9SBarry Smith        (1) the local node number,
71030dcb7c9SBarry Smith        (2) the number of processors sharing it,
71130dcb7c9SBarry Smith        (3) the processors sharing it
71230dcb7c9SBarry Smith   */
71330dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
71430dcb7c9SBarry Smith     cnt = 1;
71530dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
71630dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
71730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
71830dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
71930dcb7c9SBarry Smith         sends2[starts2[i]]++;
72030dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
72130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
72230dcb7c9SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr);
72330dcb7c9SBarry Smith         cnt += nownedsenders[node];
72430dcb7c9SBarry Smith       }
72530dcb7c9SBarry Smith     }
72630dcb7c9SBarry Smith   }
72730dcb7c9SBarry Smith 
72830dcb7c9SBarry Smith   /* send the message lengths */
72930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
73024cf384cSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr);
73130dcb7c9SBarry Smith   }
73230dcb7c9SBarry Smith 
73330dcb7c9SBarry Smith   /* receive the message lengths */
73430dcb7c9SBarry Smith   nrecvs2 = nsends;
735b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr);
736b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr);
73730dcb7c9SBarry Smith   nt      = 0;
73830dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
73924cf384cSBarry Smith     ierr =  MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr);
74030dcb7c9SBarry Smith     nt   += lens2[i];
74130dcb7c9SBarry Smith   }
74230dcb7c9SBarry Smith   starts3[0] = 0;
74330dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
74430dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
74530dcb7c9SBarry Smith   }
746b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr);
747b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
74852b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
74924cf384cSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
75030dcb7c9SBarry Smith   }
75130dcb7c9SBarry Smith 
75230dcb7c9SBarry Smith   /* send the messages */
753b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
75430dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
75524cf384cSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
75630dcb7c9SBarry Smith   }
75730dcb7c9SBarry Smith 
75830dcb7c9SBarry Smith   /* wait on receives */
759b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
76030dcb7c9SBarry Smith   ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
76130dcb7c9SBarry Smith   ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
76230dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
76330dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
76430dcb7c9SBarry Smith 
76507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
76630dcb7c9SBarry Smith     cnt = 0;
76730dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
76830dcb7c9SBarry Smith       nt = recvs2[cnt++];
76930dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
77030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
77130dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
77230dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
77330dcb7c9SBarry Smith         }
77430dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
77530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
77630dcb7c9SBarry Smith       }
77730dcb7c9SBarry Smith     }
77830dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
77907b52d57SBarry Smith   } /* -----------------------------------  */
78030dcb7c9SBarry Smith 
78130dcb7c9SBarry Smith   /* count number subdomains for each local node */
782b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr);
78330dcb7c9SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr);
78430dcb7c9SBarry Smith   cnt  = 0;
78530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
78630dcb7c9SBarry Smith     nt = recvs2[cnt++];
78730dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
78830dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
78930dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
79030dcb7c9SBarry Smith       }
79130dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
79230dcb7c9SBarry Smith     }
79330dcb7c9SBarry Smith   }
79430dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
79530dcb7c9SBarry Smith   *nproc    = nt;
796b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr);
797b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr);
798b0a32e0cSBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr);
799b0a32e0cSBarry Smith   ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr);
80030dcb7c9SBarry Smith   cnt       = 0;
80130dcb7c9SBarry Smith   for (i=0; i<size; i++) {
80230dcb7c9SBarry Smith     if (nprocs[i] > 0) {
80330dcb7c9SBarry Smith       bprocs[i]        = cnt;
80430dcb7c9SBarry Smith       (*procs)[cnt]    = i;
80530dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
806b0a32e0cSBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr);
80730dcb7c9SBarry Smith       cnt++;
80830dcb7c9SBarry Smith     }
80930dcb7c9SBarry Smith   }
81030dcb7c9SBarry Smith 
81130dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
81230dcb7c9SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr);
81330dcb7c9SBarry Smith   cnt  = 0;
81430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
81530dcb7c9SBarry Smith     nt = recvs2[cnt++];
81630dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
81730dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
81830dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
81930dcb7c9SBarry Smith       }
82030dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
82130dcb7c9SBarry Smith     }
82230dcb7c9SBarry Smith   }
82330dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
82407b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
82530dcb7c9SBarry Smith 
82607b52d57SBarry Smith   /* sort the node indexing by their global numbers */
82707b52d57SBarry Smith   nt = *nproc;
82807b52d57SBarry Smith   for (i=0; i<nt; i++) {
829b0a32e0cSBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr);
83007b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
83107b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
83207b52d57SBarry Smith     }
83307b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
83407b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
83507b52d57SBarry Smith   }
83607b52d57SBarry Smith 
83707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
83830dcb7c9SBarry Smith     nt = *nproc;
83930dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
84030dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
84130dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
84230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
84330dcb7c9SBarry Smith       }
84430dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
84530dcb7c9SBarry Smith     }
84630dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
84707b52d57SBarry Smith   } /* -----------------------------------  */
84830dcb7c9SBarry Smith 
84930dcb7c9SBarry Smith   /* wait on sends */
85030dcb7c9SBarry Smith   if (nsends2) {
851b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
85230dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
85330dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
85430dcb7c9SBarry Smith   }
85530dcb7c9SBarry Smith 
85630dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
85730dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
85830dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8593677ff5aSBarry Smith 
860bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
861bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
862bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
86330dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
86430dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
86589d82c54SBarry Smith 
86689d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
86789d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8683a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
86930dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
87024cf384cSBarry Smith 
87124cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
87224cf384cSBarry Smith   first_procs    = (*procs)[0];
87324cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
87424cf384cSBarry Smith   first_indices  = (*indices)[0];
87524cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
87624cf384cSBarry Smith     if ((*procs)[i] == rank) {
87724cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
87824cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
87924cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
88024cf384cSBarry Smith       (*procs)[i]    = first_procs;
88124cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
88224cf384cSBarry Smith       (*indices)[i]  = first_indices;
88324cf384cSBarry Smith       break;
88424cf384cSBarry Smith     }
88524cf384cSBarry Smith   }
88624cf384cSBarry Smith 
88789d82c54SBarry Smith   PetscFunctionReturn(0);
88889d82c54SBarry Smith }
88989d82c54SBarry Smith 
8904a2ae208SSatish Balay #undef __FUNCT__
8914a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
89207b52d57SBarry Smith /*@C
89307b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
89489d82c54SBarry Smith 
89507b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
89607b52d57SBarry Smith 
89707b52d57SBarry Smith     Input Parameters:
89807b52d57SBarry Smith .   mapping - the mapping from local to global indexing
89907b52d57SBarry Smith 
90007b52d57SBarry Smith     Output Parameter:
90107b52d57SBarry Smith +   nproc - number of processors that are connected to this one
90207b52d57SBarry Smith .   proc - neighboring processors
90307b52d57SBarry Smith .   numproc - number of indices for each processor
90407b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
90507b52d57SBarry Smith 
90607b52d57SBarry Smith     Level: advanced
90707b52d57SBarry Smith 
90807b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
90907b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
91007b52d57SBarry Smith @*/
91107b52d57SBarry Smith int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices)
91207b52d57SBarry Smith {
91307b52d57SBarry Smith   int ierr,i;
91407b52d57SBarry Smith 
91507b52d57SBarry Smith   PetscFunctionBegin;
91600ff320aSBarry Smith   if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);}
91700ff320aSBarry Smith   if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);}
91800ff320aSBarry Smith   if (*indices) {
91900ff320aSBarry Smith     if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);}
92000ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
92124cf384cSBarry Smith       if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);}
92207b52d57SBarry Smith     }
92307b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
92424cf384cSBarry Smith   }
92507b52d57SBarry Smith   PetscFunctionReturn(0);
92607b52d57SBarry Smith }
92789d82c54SBarry Smith 
928bc8ff85bSBarry Smith 
929bc8ff85bSBarry Smith 
930bc8ff85bSBarry Smith 
931bc8ff85bSBarry Smith 
932bc8ff85bSBarry Smith 
933bc8ff85bSBarry Smith 
934bc8ff85bSBarry Smith 
935bc8ff85bSBarry Smith 
936bc8ff85bSBarry Smith 
937bc8ff85bSBarry Smith 
938bc8ff85bSBarry Smith 
939bc8ff85bSBarry Smith 
940bc8ff85bSBarry Smith 
941bc8ff85bSBarry Smith 
942bc8ff85bSBarry Smith 
943bc8ff85bSBarry Smith 
94424cf384cSBarry Smith 
945