xref: /petsc/src/vec/is/utils/isltog.c (revision acfcf0e5ba359b58e6a8a7af3f239cd7334278e8)
10c735eedSKris Buschelman #define PETSCVEC_DLL
22362add9SBarry Smith 
35f5f199fSBarry Smith #include "petscvec.h"   /*I "petscvec.h" I*/
47c4f633dSBarry Smith #include "private/isimpl.h"    /*I "petscis.h"  I*/
52362add9SBarry Smith 
60700a824SBarry Smith PetscClassId PETSCVEC_DLLEXPORT IS_LTOGM_CLASSID;
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 @*/
270c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
283b9aefa3SBarry Smith {
293b9aefa3SBarry Smith   PetscFunctionBegin;
300700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
314482741eSBarry Smith   PetscValidIntPointer(n,2);
323b9aefa3SBarry Smith   *n = mapping->n;
333b9aefa3SBarry Smith   PetscFunctionReturn(0);
343b9aefa3SBarry Smith }
353b9aefa3SBarry Smith 
364a2ae208SSatish Balay #undef __FUNCT__
374a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
385a5d4f66SBarry Smith /*@C
395a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
405a5d4f66SBarry Smith 
41b9cd556bSLois Curfman McInnes     Not Collective
42b9cd556bSLois Curfman McInnes 
435a5d4f66SBarry Smith     Input Parameters:
443b9aefa3SBarry Smith +   ltog - local to global mapping
453b9aefa3SBarry Smith -   viewer - viewer
465a5d4f66SBarry Smith 
47a997ad1aSLois Curfman McInnes     Level: advanced
48a997ad1aSLois Curfman McInnes 
49273d9f13SBarry Smith     Concepts: mapping^local to global
505a5d4f66SBarry Smith 
515a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
525a5d4f66SBarry Smith @*/
530c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
545a5d4f66SBarry Smith {
5532dcc486SBarry Smith   PetscInt        i;
5632dcc486SBarry Smith   PetscMPIInt     rank;
57ace3abfcSBarry Smith   PetscBool       iascii;
586849ba73SBarry Smith   PetscErrorCode  ierr;
595a5d4f66SBarry Smith 
605a5d4f66SBarry Smith   PetscFunctionBegin;
610700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
623050cee2SBarry Smith   if (!viewer) {
637adad957SLisandro Dalcin     ierr = PetscViewerASCIIGetStdout(((PetscObject)mapping)->comm,&viewer);CHKERRQ(ierr);
643050cee2SBarry Smith   }
650700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
665a5d4f66SBarry Smith 
677adad957SLisandro Dalcin   ierr = MPI_Comm_rank(((PetscObject)mapping)->comm,&rank);CHKERRQ(ierr);
682692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
6932077d6dSBarry Smith   if (iascii) {
705a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
71b0a32e0cSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
726831982aSBarry Smith     }
73b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
746831982aSBarry Smith   } else {
75e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name);
765a5d4f66SBarry Smith   }
775a5d4f66SBarry Smith 
785a5d4f66SBarry Smith   PetscFunctionReturn(0);
795a5d4f66SBarry Smith }
805a5d4f66SBarry Smith 
814a2ae208SSatish Balay #undef __FUNCT__
824a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
831f428162SBarry Smith /*@
842bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
852bdab257SBarry Smith     ordering and a global parallel ordering.
862bdab257SBarry Smith 
870f5bd95cSBarry Smith     Not collective
88b9cd556bSLois Curfman McInnes 
89a997ad1aSLois Curfman McInnes     Input Parameter:
902bdab257SBarry Smith .   is - index set containing the global numbers for each local
912bdab257SBarry Smith 
92a997ad1aSLois Curfman McInnes     Output Parameter:
932bdab257SBarry Smith .   mapping - new mapping data structure
942bdab257SBarry Smith 
95a997ad1aSLois Curfman McInnes     Level: advanced
96a997ad1aSLois Curfman McInnes 
97273d9f13SBarry Smith     Concepts: mapping^local to global
982bdab257SBarry Smith 
992bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1002bdab257SBarry Smith @*/
1010c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1022bdab257SBarry Smith {
1036849ba73SBarry Smith   PetscErrorCode ierr;
1045d0c19d7SBarry Smith   PetscInt       n;
1055d0c19d7SBarry Smith   const PetscInt *indices;
1062bdab257SBarry Smith   MPI_Comm       comm;
1073a40ed3dSBarry Smith 
1083a40ed3dSBarry Smith   PetscFunctionBegin;
1090700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1104482741eSBarry Smith   PetscValidPointer(mapping,2);
1112bdab257SBarry Smith 
1122bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1133b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1142bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
115d5ad8652SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1162bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1173a40ed3dSBarry Smith   PetscFunctionReturn(0);
1182bdab257SBarry Smith }
1195a5d4f66SBarry Smith 
120b46b645bSBarry Smith 
1214a2ae208SSatish Balay #undef __FUNCT__
1224a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
123ba5bb76aSSatish Balay /*@
12490f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
12590f02eecSBarry Smith     ordering and a global parallel ordering.
1262362add9SBarry Smith 
12789d82c54SBarry Smith     Not Collective, but communicator may have more than one process
128b9cd556bSLois Curfman McInnes 
1292362add9SBarry Smith     Input Parameters:
13089d82c54SBarry Smith +   comm - MPI communicator
13190f02eecSBarry Smith .   n - the number of local elements
132d5ad8652SBarry Smith .   indices - the global index for each local element
133d5ad8652SBarry Smith -   mode - see PetscCopyMode
1342362add9SBarry Smith 
135a997ad1aSLois Curfman McInnes     Output Parameter:
13690f02eecSBarry Smith .   mapping - new mapping data structure
1372362add9SBarry Smith 
138a997ad1aSLois Curfman McInnes     Level: advanced
139a997ad1aSLois Curfman McInnes 
140273d9f13SBarry Smith     Concepts: mapping^local to global
1412362add9SBarry Smith 
142d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
1432362add9SBarry Smith @*/
144d5ad8652SBarry Smith PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingCreate(MPI_Comm cm,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
1452362add9SBarry Smith {
1466849ba73SBarry Smith   PetscErrorCode ierr;
14732dcc486SBarry Smith   PetscInt       *in;
148b46b645bSBarry Smith 
149b46b645bSBarry Smith   PetscFunctionBegin;
15073911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
1514482741eSBarry Smith   PetscValidPointer(mapping,4);
152b46b645bSBarry Smith 
1538e58c17dSMatthew Knepley   *mapping = PETSC_NULL;
1548e58c17dSMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES
1552b6de112SBarry Smith   ierr = ISInitializePackage(PETSC_NULL);CHKERRQ(ierr);
1568e58c17dSMatthew Knepley #endif
1572362add9SBarry Smith 
1580700a824SBarry Smith   ierr = PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_CLASSID,0,"ISLocalToGlobalMapping",
15952e6d16bSBarry Smith 			   cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
160d4bb536fSBarry Smith   (*mapping)->n       = n;
161d4bb536fSBarry Smith   /*
162d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
163d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
164d4bb536fSBarry Smith   */
165d4bb536fSBarry Smith   (*mapping)->globals = 0;
166d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
167d5ad8652SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&in);CHKERRQ(ierr);
168d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
169d5ad8652SBarry Smith     ierr = PetscLogObjectMemory(*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
170d5ad8652SBarry Smith     (*mapping)->indices = in;
171d5ad8652SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
172d5ad8652SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
173d5ad8652SBarry Smith   } else SETERRQ(cm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
1743a40ed3dSBarry Smith   PetscFunctionReturn(0);
1752362add9SBarry Smith }
1762362add9SBarry Smith 
1774a2ae208SSatish Balay #undef __FUNCT__
1784a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingBlock"
179bce096a4SSatish Balay /*@
180323b833fSBarry Smith     ISLocalToGlobalMappingBlock - Creates a blocked index version of an
181323b833fSBarry Smith        ISLocalToGlobalMapping that is appropriate for MatSetLocalToGlobalMappingBlock()
182323b833fSBarry Smith        and VecSetLocalToGlobalMappingBlock().
183323b833fSBarry Smith 
184323b833fSBarry Smith     Not Collective, but communicator may have more than one process
185323b833fSBarry Smith 
186323b833fSBarry Smith     Input Parameters:
187323b833fSBarry Smith +    inmap - original point-wise mapping
188323b833fSBarry Smith -    bs - block size
189323b833fSBarry Smith 
190323b833fSBarry Smith     Output Parameter:
19169eb54c3SBarry Smith .   outmap - block based mapping; the indices are relative to BLOCKS, not individual vector or matrix entries.
192323b833fSBarry Smith 
193323b833fSBarry Smith     Level: advanced
194323b833fSBarry Smith 
195323b833fSBarry Smith     Concepts: mapping^local to global
196323b833fSBarry Smith 
197323b833fSBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
198323b833fSBarry Smith @*/
1990c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping inmap,PetscInt bs,ISLocalToGlobalMapping *outmap)
200323b833fSBarry Smith {
2016849ba73SBarry Smith   PetscErrorCode ierr;
20232dcc486SBarry Smith   PetscInt       *ii,i,n;
203323b833fSBarry Smith 
204323b833fSBarry Smith   PetscFunctionBegin;
2050700a824SBarry Smith   PetscValidHeaderSpecific(inmap,IS_LTOGM_CLASSID,1);
206ad48de64SLisandro Dalcin   PetscValidPointer(outmap,1);
207323b833fSBarry Smith   if (bs > 1) {
208323b833fSBarry Smith     n    = inmap->n/bs;
209e32f2f54SBarry Smith     if (n*bs != inmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Pointwise mapping length is not divisible by block size");
21032dcc486SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt),&ii);CHKERRQ(ierr);
211323b833fSBarry Smith     for (i=0; i<n; i++) {
212db032c9dSBarry Smith       ii[i] = inmap->indices[bs*i]/bs;
213323b833fSBarry Smith     }
214d5ad8652SBarry Smith     ierr = ISLocalToGlobalMappingCreate(((PetscObject)inmap)->comm,n,ii,PETSC_OWN_POINTER,outmap);CHKERRQ(ierr);
215323b833fSBarry Smith   } else {
216323b833fSBarry Smith     ierr    = PetscObjectReference((PetscObject)inmap);CHKERRQ(ierr);
217c3122656SLisandro Dalcin     *outmap = inmap;
218323b833fSBarry Smith   }
219323b833fSBarry Smith   PetscFunctionReturn(0);
220323b833fSBarry Smith }
221323b833fSBarry Smith 
2224a2ae208SSatish Balay #undef __FUNCT__
2234a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
22490f02eecSBarry Smith /*@
22590f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
22690f02eecSBarry Smith    ordering and a global parallel ordering.
22790f02eecSBarry Smith 
2280f5bd95cSBarry Smith    Note Collective
229b9cd556bSLois Curfman McInnes 
23090f02eecSBarry Smith    Input Parameters:
23190f02eecSBarry Smith .  mapping - mapping data structure
23290f02eecSBarry Smith 
233a997ad1aSLois Curfman McInnes    Level: advanced
234a997ad1aSLois Curfman McInnes 
2353acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
23690f02eecSBarry Smith @*/
2370c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
23890f02eecSBarry Smith {
239dfbe8321SBarry Smith   PetscErrorCode ierr;
2403a40ed3dSBarry Smith   PetscFunctionBegin;
2410700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
2427adad957SLisandro Dalcin   if (--((PetscObject)mapping)->refct > 0) PetscFunctionReturn(0);
243606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
24405b42c5fSBarry Smith   ierr = PetscFree(mapping->globals);CHKERRQ(ierr);
245d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
2463a40ed3dSBarry Smith   PetscFunctionReturn(0);
24790f02eecSBarry Smith }
24890f02eecSBarry Smith 
2494a2ae208SSatish Balay #undef __FUNCT__
2504a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
25190f02eecSBarry Smith /*@
2523acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
2533acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
2543acfe500SLois Curfman McInnes     context.
25590f02eecSBarry Smith 
256b9cd556bSLois Curfman McInnes     Not collective
257b9cd556bSLois Curfman McInnes 
25890f02eecSBarry Smith     Input Parameters:
259b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
260b9cd556bSLois Curfman McInnes -   is - index set in local numbering
26190f02eecSBarry Smith 
26290f02eecSBarry Smith     Output Parameters:
26390f02eecSBarry Smith .   newis - index set in global numbering
26490f02eecSBarry Smith 
265a997ad1aSLois Curfman McInnes     Level: advanced
266a997ad1aSLois Curfman McInnes 
267273d9f13SBarry Smith     Concepts: mapping^local to global
2683acfe500SLois Curfman McInnes 
26990f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
270d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
27190f02eecSBarry Smith @*/
2720c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
27390f02eecSBarry Smith {
2746849ba73SBarry Smith   PetscErrorCode ierr;
2755d0c19d7SBarry Smith   PetscInt       n,i,*idxmap,*idxout,Nmax = mapping->n;
2765d0c19d7SBarry Smith   const PetscInt *idxin;
2773a40ed3dSBarry Smith 
2783a40ed3dSBarry Smith   PetscFunctionBegin;
2790700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
2800700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
2814482741eSBarry Smith   PetscValidPointer(newis,3);
28290f02eecSBarry Smith 
2833b9aefa3SBarry Smith   ierr   = ISGetLocalSize(is,&n);CHKERRQ(ierr);
28490f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
28590f02eecSBarry Smith   idxmap = mapping->indices;
28690f02eecSBarry Smith 
2877c334f02SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&idxout);CHKERRQ(ierr);
28890f02eecSBarry Smith   for (i=0; i<n; i++) {
289e32f2f54SBarry Smith     if (idxin[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax-1,i);
29090f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
29190f02eecSBarry Smith   }
2923b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
29370b3c8c7SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
2943a40ed3dSBarry Smith   PetscFunctionReturn(0);
29590f02eecSBarry Smith }
29690f02eecSBarry Smith 
29789d82c54SBarry Smith /*MC
2983acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2993acfe500SLois Curfman McInnes    and converts them to the global numbering.
30090f02eecSBarry Smith 
301eca87e8dSBarry Smith    Synopsis:
302eca87e8dSBarry Smith    PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[])
303eca87e8dSBarry Smith 
304b9cd556bSLois Curfman McInnes    Not collective
305b9cd556bSLois Curfman McInnes 
306bb25748dSBarry Smith    Input Parameters:
307b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
308bb25748dSBarry Smith .  N - number of integers
309b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
310bb25748dSBarry Smith 
311bb25748dSBarry Smith    Output Parameter:
312bb25748dSBarry Smith .  out - indices in global numbering
313bb25748dSBarry Smith 
314b9cd556bSLois Curfman McInnes    Notes:
315b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
316d4bb536fSBarry Smith 
317a997ad1aSLois Curfman McInnes    Level: advanced
318a997ad1aSLois Curfman McInnes 
319bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3200752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
321d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
322bb25748dSBarry Smith 
323273d9f13SBarry Smith     Concepts: mapping^local to global
324d4bb536fSBarry Smith 
32589d82c54SBarry Smith M*/
326d4bb536fSBarry Smith 
327d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
328d4bb536fSBarry Smith 
3294a2ae208SSatish Balay #undef __FUNCT__
3304a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
331d4bb536fSBarry Smith /*
332d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
333d4bb536fSBarry Smith */
3346849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
335d4bb536fSBarry Smith {
3366849ba73SBarry Smith   PetscErrorCode ierr;
33732dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
338d4bb536fSBarry Smith 
3393a40ed3dSBarry Smith   PetscFunctionBegin;
340d4bb536fSBarry Smith   end   = 0;
341d4bb536fSBarry Smith   start = 100000000;
342d4bb536fSBarry Smith 
343d4bb536fSBarry Smith   for (i=0; i<n; i++) {
344d4bb536fSBarry Smith     if (idx[i] < 0) continue;
345d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
346d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
347d4bb536fSBarry Smith   }
348d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
349d4bb536fSBarry Smith   mapping->globalstart = start;
350d4bb536fSBarry Smith   mapping->globalend   = end;
351d4bb536fSBarry Smith 
35232dcc486SBarry Smith   ierr             = PetscMalloc((end-start+2)*sizeof(PetscInt),&globals);CHKERRQ(ierr);
353b0a32e0cSBarry Smith   mapping->globals = globals;
354d4bb536fSBarry Smith   for (i=0; i<end-start+1; i++) {
355d4bb536fSBarry Smith     globals[i] = -1;
356d4bb536fSBarry Smith   }
357d4bb536fSBarry Smith   for (i=0; i<n; i++) {
358d4bb536fSBarry Smith     if (idx[i] < 0) continue;
359d4bb536fSBarry Smith     globals[idx[i] - start] = i;
360d4bb536fSBarry Smith   }
361d4bb536fSBarry Smith 
36252e6d16bSBarry Smith   ierr = PetscLogObjectMemory(mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
3633a40ed3dSBarry Smith   PetscFunctionReturn(0);
364d4bb536fSBarry Smith }
365d4bb536fSBarry Smith 
3664a2ae208SSatish Balay #undef __FUNCT__
3674a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
368d4bb536fSBarry Smith /*@
369a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
370a997ad1aSLois Curfman McInnes     specified with a global numbering.
371d4bb536fSBarry Smith 
372b9cd556bSLois Curfman McInnes     Not collective
373b9cd556bSLois Curfman McInnes 
374d4bb536fSBarry Smith     Input Parameters:
375b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
376d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
377d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
378d4bb536fSBarry Smith .   n - number of global indices to map
379b9cd556bSLois Curfman McInnes -   idx - global indices to map
380d4bb536fSBarry Smith 
381d4bb536fSBarry Smith     Output Parameters:
382b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
383b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
384e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
385e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
386e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
387e182c471SBarry Smith              a second time to set the values.
388d4bb536fSBarry Smith 
389b9cd556bSLois Curfman McInnes     Notes:
390b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
391d4bb536fSBarry Smith 
3920f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
3930f5bd95cSBarry Smith     array to compute these.
3940f5bd95cSBarry Smith 
395a997ad1aSLois Curfman McInnes     Level: advanced
396a997ad1aSLois Curfman McInnes 
397273d9f13SBarry Smith     Concepts: mapping^global to local
398d4bb536fSBarry Smith 
399d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
400d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
401d4bb536fSBarry Smith @*/
4020c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
40332dcc486SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
404d4bb536fSBarry Smith {
40532dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
4066849ba73SBarry Smith   PetscErrorCode ierr;
407d4bb536fSBarry Smith 
4083a40ed3dSBarry Smith   PetscFunctionBegin;
4090700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
410d4bb536fSBarry Smith   if (!mapping->globals) {
411d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
412d4bb536fSBarry Smith   }
413d4bb536fSBarry Smith   globals = mapping->globals;
414d4bb536fSBarry Smith   start   = mapping->globalstart;
415d4bb536fSBarry Smith   end     = mapping->globalend;
416d4bb536fSBarry Smith 
417d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
418d4bb536fSBarry Smith     if (idxout) {
419d4bb536fSBarry Smith       for (i=0; i<n; i++) {
420d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
421d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
422d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
423d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
424d4bb536fSBarry Smith       }
425d4bb536fSBarry Smith     }
426d4bb536fSBarry Smith     if (nout) *nout = n;
427d4bb536fSBarry Smith   } else {
428d4bb536fSBarry Smith     if (idxout) {
429d4bb536fSBarry Smith       for (i=0; i<n; i++) {
430d4bb536fSBarry Smith         if (idx[i] < 0) continue;
431d4bb536fSBarry Smith         if (idx[i] < start) continue;
432d4bb536fSBarry Smith         if (idx[i] > end) continue;
433d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
434d4bb536fSBarry Smith         if (tmp < 0) continue;
435d4bb536fSBarry Smith         idxout[nf++] = tmp;
436d4bb536fSBarry Smith       }
437d4bb536fSBarry Smith     } else {
438d4bb536fSBarry Smith       for (i=0; i<n; i++) {
439d4bb536fSBarry Smith         if (idx[i] < 0) continue;
440d4bb536fSBarry Smith         if (idx[i] < start) continue;
441d4bb536fSBarry Smith         if (idx[i] > end) continue;
442d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
443d4bb536fSBarry Smith         if (tmp < 0) continue;
444d4bb536fSBarry Smith         nf++;
445d4bb536fSBarry Smith       }
446d4bb536fSBarry Smith     }
447d4bb536fSBarry Smith     if (nout) *nout = nf;
448d4bb536fSBarry Smith   }
449d4bb536fSBarry Smith 
4503a40ed3dSBarry Smith   PetscFunctionReturn(0);
451d4bb536fSBarry Smith }
45290f02eecSBarry Smith 
4534a2ae208SSatish Balay #undef __FUNCT__
4544a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
45589d82c54SBarry Smith /*@C
45689d82c54SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
45789d82c54SBarry Smith      each index shared by more than one processor
45889d82c54SBarry Smith 
45989d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
46089d82c54SBarry Smith 
46189d82c54SBarry Smith     Input Parameters:
46289d82c54SBarry Smith .   mapping - the mapping from local to global indexing
46389d82c54SBarry Smith 
46489d82c54SBarry Smith     Output Parameter:
46589d82c54SBarry Smith +   nproc - number of processors that are connected to this one
46689d82c54SBarry Smith .   proc - neighboring processors
46707b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
4683463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
46989d82c54SBarry Smith 
47089d82c54SBarry Smith     Level: advanced
47189d82c54SBarry Smith 
472273d9f13SBarry Smith     Concepts: mapping^local to global
47389d82c54SBarry Smith 
4742cfcea29SBarry Smith     Fortran Usage:
4752cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
4762cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
4772cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
4782cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
4792cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
4802cfcea29SBarry Smith 
4812cfcea29SBarry Smith 
48207b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
48307b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
48489d82c54SBarry Smith @*/
4850c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
48689d82c54SBarry Smith {
4876849ba73SBarry Smith   PetscErrorCode ierr;
48897f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
48932dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
49032dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
49197f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
49232dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
49332dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
49489d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
49530dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
4967adad957SLisandro Dalcin   MPI_Comm       comm = ((PetscObject)mapping)->comm;
497ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
49889d82c54SBarry Smith 
49989d82c54SBarry Smith   PetscFunctionBegin;
5000700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
50124cf384cSBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
50224cf384cSBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
50324cf384cSBarry Smith   if (size == 1) {
50424cf384cSBarry Smith     *nproc         = 0;
50524cf384cSBarry Smith     *procs         = PETSC_NULL;
50632dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr);
5071e2105dcSBarry Smith     (*numprocs)[0] = 0;
50832dcc486SBarry Smith     ierr           = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr);
5091e2105dcSBarry Smith     (*indices)[0]  = PETSC_NULL;
51024cf384cSBarry Smith     PetscFunctionReturn(0);
51124cf384cSBarry Smith   }
51224cf384cSBarry Smith 
513*acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,PETSC_NULL);CHKERRQ(ierr);
51407b52d57SBarry Smith 
5153677ff5aSBarry Smith   /*
5163677ff5aSBarry Smith     Notes on ISLocalToGlobalMappingGetInfo
5173677ff5aSBarry Smith 
5183677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
5193677ff5aSBarry Smith            numbering, just for this routine.
5203677ff5aSBarry Smith 
5213677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
5223677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
5233677ff5aSBarry Smith 
5243677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
5253677ff5aSBarry Smith 
5263677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
5273677ff5aSBarry Smith            local subdomain
5283677ff5aSBarry Smith   */
52924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
53024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
53124cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
53289d82c54SBarry Smith 
53389d82c54SBarry Smith   for (i=0; i<n; i++) {
53489d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
53589d82c54SBarry Smith   }
53632dcc486SBarry Smith   ierr   = MPI_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
53778058e43SBarry Smith   Ng++;
53889d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
53989d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
540bc8ff85bSBarry Smith   scale  = Ng/size + 1;
541a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
542caba0dd0SBarry Smith   rstart = scale*rank;
54389d82c54SBarry Smith 
54489d82c54SBarry Smith   /* determine ownership ranges of global indices */
5457c334f02SBarry Smith   ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
54632dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
54789d82c54SBarry Smith 
54889d82c54SBarry Smith   /* determine owners of each local node  */
5497c334f02SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&owner);CHKERRQ(ierr);
55089d82c54SBarry Smith   for (i=0; i<n; i++) {
5513677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
55227c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
5533677ff5aSBarry Smith     owner[i]         = proc;
55427c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
55589d82c54SBarry Smith   }
55627c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
5571e2582c4SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %d\n",nsends);CHKERRQ(ierr);
55889d82c54SBarry Smith 
55989d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
56027c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
5611e2582c4SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %d\n",nrecvs);CHKERRQ(ierr);
56289d82c54SBarry Smith 
56389d82c54SBarry Smith   /* post receives for owned rows */
56432dcc486SBarry Smith   ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(PetscInt),&recvs);CHKERRQ(ierr);
565b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
56689d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
56732dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
56889d82c54SBarry Smith   }
56989d82c54SBarry Smith 
57089d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
57132dcc486SBarry Smith   ierr       = PetscMalloc((2*n+1)*sizeof(PetscInt),&sends);CHKERRQ(ierr);
57232dcc486SBarry Smith   ierr       = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
57389d82c54SBarry Smith   starts[0]  = 0;
57427c402fcSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];}
57589d82c54SBarry Smith   for (i=0; i<n; i++) {
57689d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
57730dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
57889d82c54SBarry Smith   }
57989d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
58089d82c54SBarry Smith   starts[0]  = 0;
58127c402fcSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];}
58289d82c54SBarry Smith 
58389d82c54SBarry Smith   /* send the messages */
584b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
58532dcc486SBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(PetscInt),&dest);CHKERRQ(ierr);
58689d82c54SBarry Smith   cnt = 0;
58789d82c54SBarry Smith   for (i=0; i<size; i++) {
58827c402fcSBarry Smith     if (nprocs[2*i]) {
58932dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
59030dcb7c9SBarry Smith       dest[cnt] = i;
59189d82c54SBarry Smith       cnt++;
59289d82c54SBarry Smith     }
59389d82c54SBarry Smith   }
59489d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
59589d82c54SBarry Smith 
59689d82c54SBarry Smith   /* wait on receives */
59797f1f81fSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(PetscMPIInt),&source);CHKERRQ(ierr);
59897f1f81fSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(PetscMPIInt),&len);CHKERRQ(ierr);
59989d82c54SBarry Smith   cnt  = nrecvs;
60032dcc486SBarry Smith   ierr = PetscMalloc((ng+1)*sizeof(PetscInt),&nownedsenders);CHKERRQ(ierr);
60132dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
60289d82c54SBarry Smith   while (cnt) {
60389d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
60489d82c54SBarry Smith     /* unpack receives into our local space */
60532dcc486SBarry Smith     ierr           = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
60689d82c54SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
60730dcb7c9SBarry Smith     len[imdex]     = len[imdex]/2;
608caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
60930dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
61089d82c54SBarry Smith     cnt--;
61189d82c54SBarry Smith   }
61289d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
61389d82c54SBarry Smith 
61430dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
615bc8ff85bSBarry Smith   nowned  = 0;
616bc8ff85bSBarry Smith   nownedm = 0;
617bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
618bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
619bc8ff85bSBarry Smith   }
620bc8ff85bSBarry Smith 
621bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
62232dcc486SBarry Smith   ierr      = PetscMalloc((nownedm+1)*sizeof(PetscInt),&ownedsenders);CHKERRQ(ierr);
62332dcc486SBarry Smith   ierr      = PetscMalloc((ng+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
624bc8ff85bSBarry Smith   starts[0] = 0;
625bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
626bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
627bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
628bc8ff85bSBarry Smith   }
629bc8ff85bSBarry Smith 
63030dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
631bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
632bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
63330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
634bc8ff85bSBarry Smith       if (nownedsenders[node] > 1) {
635bc8ff85bSBarry Smith         ownedsenders[starts[node]++] = source[i];
636bc8ff85bSBarry Smith       }
637bc8ff85bSBarry Smith     }
638bc8ff85bSBarry Smith   }
639bc8ff85bSBarry Smith 
64007b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
64130dcb7c9SBarry Smith     starts[0]    = 0;
64230dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
64330dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
64430dcb7c9SBarry Smith       else starts[i] = starts[i-1];
64530dcb7c9SBarry Smith     }
64630dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
64730dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
64830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
64930dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
65030dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
65130dcb7c9SBarry Smith         }
65230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
65330dcb7c9SBarry Smith       }
65430dcb7c9SBarry Smith     }
65530dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
65607b52d57SBarry Smith   }/* -----------------------------------  */
65730dcb7c9SBarry Smith 
6583677ff5aSBarry Smith   /* wait on original sends */
6593a96401aSBarry Smith   if (nsends) {
660b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
6613a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
6623a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
6633a96401aSBarry Smith   }
66489d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
6653a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
6663677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
6673677ff5aSBarry Smith 
6683677ff5aSBarry Smith   /* pack messages to send back to local owners */
66930dcb7c9SBarry Smith   starts[0]    = 0;
67030dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
67130dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
67230dcb7c9SBarry Smith     else starts[i] = starts[i-1];
67330dcb7c9SBarry Smith   }
67430dcb7c9SBarry Smith   nsends2 = nrecvs;
67532dcc486SBarry Smith   ierr    = PetscMalloc((nsends2+1)*sizeof(PetscInt),&nprocs);CHKERRQ(ierr); /* length of each message */
67630dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
67730dcb7c9SBarry Smith     nprocs[i] = 1;
67830dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
67930dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
68030dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
68130dcb7c9SBarry Smith         nprocs[i] += 2 + nownedsenders[node];
68230dcb7c9SBarry Smith       }
68330dcb7c9SBarry Smith     }
68430dcb7c9SBarry Smith   }
68530dcb7c9SBarry Smith   nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i];
68632dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&sends2);CHKERRQ(ierr);
68732dcc486SBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(PetscInt),&starts2);CHKERRQ(ierr);
68830dcb7c9SBarry Smith   starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
68930dcb7c9SBarry Smith   /*
69030dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
69130dcb7c9SBarry Smith        (0) the number of nodes being sent back
69230dcb7c9SBarry Smith        (1) the local node number,
69330dcb7c9SBarry Smith        (2) the number of processors sharing it,
69430dcb7c9SBarry Smith        (3) the processors sharing it
69530dcb7c9SBarry Smith   */
69630dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
69730dcb7c9SBarry Smith     cnt = 1;
69830dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
69930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
70030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
70130dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
70230dcb7c9SBarry Smith         sends2[starts2[i]]++;
70330dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
70430dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
70532dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
70630dcb7c9SBarry Smith         cnt += nownedsenders[node];
70730dcb7c9SBarry Smith       }
70830dcb7c9SBarry Smith     }
70930dcb7c9SBarry Smith   }
71030dcb7c9SBarry Smith 
71130dcb7c9SBarry Smith   /* receive the message lengths */
71230dcb7c9SBarry Smith   nrecvs2 = nsends;
71332dcc486SBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(PetscInt),&lens2);CHKERRQ(ierr);
71432dcc486SBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(PetscInt),&starts3);CHKERRQ(ierr);
715d44834fbSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
71630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
717d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
71830dcb7c9SBarry Smith   }
719d44834fbSBarry Smith 
7208a8e0b3aSBarry Smith   /* send the message lengths */
7218a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
7228a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
7238a8e0b3aSBarry Smith   }
7248a8e0b3aSBarry Smith 
725d44834fbSBarry Smith   /* wait on receives of lens */
7260c468ba9SBarry Smith   if (nrecvs2) {
7270c468ba9SBarry Smith     ierr = PetscMalloc(nrecvs2*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
728d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
729d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
7300c468ba9SBarry Smith   }
731d44834fbSBarry Smith   ierr = PetscFree(recv_waits);
732d44834fbSBarry Smith 
73330dcb7c9SBarry Smith   starts3[0] = 0;
734d44834fbSBarry Smith   nt         = 0;
73530dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
73630dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
737d44834fbSBarry Smith     nt          += lens2[i];
73830dcb7c9SBarry Smith   }
739d44834fbSBarry Smith   nt += lens2[nrecvs2-1];
740d44834fbSBarry Smith 
74132dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&recvs2);CHKERRQ(ierr);
742b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
74352b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
74432dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
74530dcb7c9SBarry Smith   }
74630dcb7c9SBarry Smith 
74730dcb7c9SBarry Smith   /* send the messages */
748b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
74930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
75032dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
75130dcb7c9SBarry Smith   }
75230dcb7c9SBarry Smith 
75330dcb7c9SBarry Smith   /* wait on receives */
7540c468ba9SBarry Smith   if (nrecvs2) {
7550c468ba9SBarry Smith     ierr = PetscMalloc(nrecvs2*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr);
75630dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
75730dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
7580c468ba9SBarry Smith   }
75930dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
76030dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
76130dcb7c9SBarry Smith 
76207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
76330dcb7c9SBarry Smith     cnt = 0;
76430dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
76530dcb7c9SBarry Smith       nt = recvs2[cnt++];
76630dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
76730dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
76830dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
76930dcb7c9SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr);
77030dcb7c9SBarry Smith         }
77130dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
77230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
77330dcb7c9SBarry Smith       }
77430dcb7c9SBarry Smith     }
77530dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
77607b52d57SBarry Smith   } /* -----------------------------------  */
77730dcb7c9SBarry Smith 
77830dcb7c9SBarry Smith   /* count number subdomains for each local node */
77932dcc486SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
78032dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
78130dcb7c9SBarry Smith   cnt  = 0;
78230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
78330dcb7c9SBarry Smith     nt = recvs2[cnt++];
78430dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
78530dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
78630dcb7c9SBarry Smith         nprocs[recvs2[cnt+2+k]]++;
78730dcb7c9SBarry Smith       }
78830dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
78930dcb7c9SBarry Smith     }
79030dcb7c9SBarry Smith   }
79130dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
79230dcb7c9SBarry Smith   *nproc    = nt;
79332dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),procs);CHKERRQ(ierr);
79432dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt),numprocs);CHKERRQ(ierr);
79532dcc486SBarry Smith   ierr = PetscMalloc((nt+1)*sizeof(PetscInt*),indices);CHKERRQ(ierr);
79632dcc486SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscInt),&bprocs);CHKERRQ(ierr);
79730dcb7c9SBarry Smith   cnt       = 0;
79830dcb7c9SBarry Smith   for (i=0; i<size; i++) {
79930dcb7c9SBarry Smith     if (nprocs[i] > 0) {
80030dcb7c9SBarry Smith       bprocs[i]        = cnt;
80130dcb7c9SBarry Smith       (*procs)[cnt]    = i;
80230dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
80332dcc486SBarry Smith       ierr             = PetscMalloc(nprocs[i]*sizeof(PetscInt),&(*indices)[cnt]);CHKERRQ(ierr);
80430dcb7c9SBarry Smith       cnt++;
80530dcb7c9SBarry Smith     }
80630dcb7c9SBarry Smith   }
80730dcb7c9SBarry Smith 
80830dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
80932dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
81030dcb7c9SBarry Smith   cnt  = 0;
81130dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
81230dcb7c9SBarry Smith     nt = recvs2[cnt++];
81330dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
81430dcb7c9SBarry Smith       for (k=0; k<recvs2[cnt+1]; k++) {
81530dcb7c9SBarry Smith         (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
81630dcb7c9SBarry Smith       }
81730dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
81830dcb7c9SBarry Smith     }
81930dcb7c9SBarry Smith   }
82030dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
82107b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
82230dcb7c9SBarry Smith 
82307b52d57SBarry Smith   /* sort the node indexing by their global numbers */
82407b52d57SBarry Smith   nt = *nproc;
82507b52d57SBarry Smith   for (i=0; i<nt; i++) {
82632dcc486SBarry Smith     ierr = PetscMalloc(((*numprocs)[i])*sizeof(PetscInt),&tmp);CHKERRQ(ierr);
82707b52d57SBarry Smith     for (j=0; j<(*numprocs)[i]; j++) {
82807b52d57SBarry Smith       tmp[j] = lindices[(*indices)[i][j]];
82907b52d57SBarry Smith     }
83007b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
83107b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
83207b52d57SBarry Smith   }
83307b52d57SBarry Smith 
83407b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
83530dcb7c9SBarry Smith     nt = *nproc;
83630dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
83730dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
83830dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
83930dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr);
84030dcb7c9SBarry Smith       }
84130dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
84230dcb7c9SBarry Smith     }
84330dcb7c9SBarry Smith     ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr);
84407b52d57SBarry Smith   } /* -----------------------------------  */
84530dcb7c9SBarry Smith 
84630dcb7c9SBarry Smith   /* wait on sends */
84730dcb7c9SBarry Smith   if (nsends2) {
848b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
84930dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
85030dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
85130dcb7c9SBarry Smith   }
85230dcb7c9SBarry Smith 
85330dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
85430dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
85530dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
8563677ff5aSBarry Smith 
857bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
858bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
859bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
86030dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
86130dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
86289d82c54SBarry Smith 
86389d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
86497f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
86589d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
8663a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
86730dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
86824cf384cSBarry Smith 
86924cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
87024cf384cSBarry Smith   first_procs    = (*procs)[0];
87124cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
87224cf384cSBarry Smith   first_indices  = (*indices)[0];
87324cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
87424cf384cSBarry Smith     if ((*procs)[i] == rank) {
87524cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
87624cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
87724cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
87824cf384cSBarry Smith       (*procs)[i]    = first_procs;
87924cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
88024cf384cSBarry Smith       (*indices)[i]  = first_indices;
88124cf384cSBarry Smith       break;
88224cf384cSBarry Smith     }
88324cf384cSBarry Smith   }
88489d82c54SBarry Smith   PetscFunctionReturn(0);
88589d82c54SBarry Smith }
88689d82c54SBarry Smith 
8874a2ae208SSatish Balay #undef __FUNCT__
8884a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
88907b52d57SBarry Smith /*@C
89007b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
89189d82c54SBarry Smith 
89207b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
89307b52d57SBarry Smith 
89407b52d57SBarry Smith     Input Parameters:
89507b52d57SBarry Smith .   mapping - the mapping from local to global indexing
89607b52d57SBarry Smith 
89707b52d57SBarry Smith     Output Parameter:
89807b52d57SBarry Smith +   nproc - number of processors that are connected to this one
89907b52d57SBarry Smith .   proc - neighboring processors
90007b52d57SBarry Smith .   numproc - number of indices for each processor
90107b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
90207b52d57SBarry Smith 
90307b52d57SBarry Smith     Level: advanced
90407b52d57SBarry Smith 
90507b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
90607b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
90707b52d57SBarry Smith @*/
9080c735eedSKris Buschelman PetscErrorCode PETSCVEC_DLLEXPORT ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
90907b52d57SBarry Smith {
9106849ba73SBarry Smith   PetscErrorCode ierr;
91132dcc486SBarry Smith   PetscInt       i;
91207b52d57SBarry Smith 
91307b52d57SBarry Smith   PetscFunctionBegin;
91405b42c5fSBarry Smith   ierr = PetscFree(*procs);CHKERRQ(ierr);
91505b42c5fSBarry Smith   ierr = PetscFree(*numprocs);CHKERRQ(ierr);
91600ff320aSBarry Smith   if (*indices) {
91705b42c5fSBarry Smith     ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
91800ff320aSBarry Smith     for (i=1; i<*nproc; i++) {
91905b42c5fSBarry Smith       ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
92007b52d57SBarry Smith     }
92107b52d57SBarry Smith     ierr = PetscFree(*indices);CHKERRQ(ierr);
92224cf384cSBarry Smith   }
92307b52d57SBarry Smith   PetscFunctionReturn(0);
92407b52d57SBarry Smith }
925