xref: /petsc/src/vec/is/utils/isltog.c (revision 6658fb44ff488c2bcae81ef2c01cc0a1455ea879)
12362add9SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>    /*I "petscis.h"  I*/
30c312b8eSJed Brown #include <petscsf.h>
4665c2dedSJed Brown #include <petscviewer.h>
52362add9SBarry Smith 
67087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID;
7268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***);
88e58c17dSMatthew Knepley 
9186d4ecdSBarry Smith #undef __FUNCT__
10*6658fb44Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingDuplicate"
11*6658fb44Sstefano_zampini /*@
12*6658fb44Sstefano_zampini     ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
13*6658fb44Sstefano_zampini 
14*6658fb44Sstefano_zampini     Not Collective
15*6658fb44Sstefano_zampini 
16*6658fb44Sstefano_zampini     Input Parameter:
17*6658fb44Sstefano_zampini .   ltog - local to global mapping
18*6658fb44Sstefano_zampini 
19*6658fb44Sstefano_zampini     Output Parameter:
20*6658fb44Sstefano_zampini .   nltog - the duplicated local to global mapping
21*6658fb44Sstefano_zampini 
22*6658fb44Sstefano_zampini     Level: advanced
23*6658fb44Sstefano_zampini 
24*6658fb44Sstefano_zampini     Concepts: mapping^local to global
25*6658fb44Sstefano_zampini 
26*6658fb44Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
27*6658fb44Sstefano_zampini @*/
28*6658fb44Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping* nltog)
29*6658fb44Sstefano_zampini {
30*6658fb44Sstefano_zampini   PetscErrorCode ierr;
31*6658fb44Sstefano_zampini 
32*6658fb44Sstefano_zampini   PetscFunctionBegin;
33*6658fb44Sstefano_zampini   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
34*6658fb44Sstefano_zampini   ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog),ltog->bs,ltog->n,ltog->indices,PETSC_COPY_VALUES,nltog);CHKERRQ(ierr);
35*6658fb44Sstefano_zampini   PetscFunctionReturn(0);
36*6658fb44Sstefano_zampini }
37*6658fb44Sstefano_zampini 
38*6658fb44Sstefano_zampini #undef __FUNCT__
394a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
40565245c5SBarry Smith /*@
41107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
423b9aefa3SBarry Smith 
433b9aefa3SBarry Smith     Not Collective
443b9aefa3SBarry Smith 
453b9aefa3SBarry Smith     Input Parameter:
463b9aefa3SBarry Smith .   ltog - local to global mapping
473b9aefa3SBarry Smith 
483b9aefa3SBarry Smith     Output Parameter:
49107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
503b9aefa3SBarry Smith 
513b9aefa3SBarry Smith     Level: advanced
523b9aefa3SBarry Smith 
53273d9f13SBarry Smith     Concepts: mapping^local to global
543b9aefa3SBarry Smith 
553b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
563b9aefa3SBarry Smith @*/
577087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
583b9aefa3SBarry Smith {
593b9aefa3SBarry Smith   PetscFunctionBegin;
600700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
614482741eSBarry Smith   PetscValidIntPointer(n,2);
62107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
633b9aefa3SBarry Smith   PetscFunctionReturn(0);
643b9aefa3SBarry Smith }
653b9aefa3SBarry Smith 
664a2ae208SSatish Balay #undef __FUNCT__
674a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
685a5d4f66SBarry Smith /*@C
695a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
705a5d4f66SBarry Smith 
71b9cd556bSLois Curfman McInnes     Not Collective
72b9cd556bSLois Curfman McInnes 
735a5d4f66SBarry Smith     Input Parameters:
743b9aefa3SBarry Smith +   ltog - local to global mapping
753b9aefa3SBarry Smith -   viewer - viewer
765a5d4f66SBarry Smith 
77a997ad1aSLois Curfman McInnes     Level: advanced
78a997ad1aSLois Curfman McInnes 
79273d9f13SBarry Smith     Concepts: mapping^local to global
805a5d4f66SBarry Smith 
815a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
825a5d4f66SBarry Smith @*/
837087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
845a5d4f66SBarry Smith {
8532dcc486SBarry Smith   PetscInt       i;
8632dcc486SBarry Smith   PetscMPIInt    rank;
87ace3abfcSBarry Smith   PetscBool      iascii;
886849ba73SBarry Smith   PetscErrorCode ierr;
895a5d4f66SBarry Smith 
905a5d4f66SBarry Smith   PetscFunctionBegin;
910700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
923050cee2SBarry Smith   if (!viewer) {
93ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
943050cee2SBarry Smith   }
950700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
965a5d4f66SBarry Smith 
97ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
98251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
9932077d6dSBarry Smith   if (iascii) {
10098c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
1011575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
1025a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
1037904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
1046831982aSBarry Smith     }
105b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1061575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
1071575c14dSBarry Smith   }
1085a5d4f66SBarry Smith   PetscFunctionReturn(0);
1095a5d4f66SBarry Smith }
1105a5d4f66SBarry Smith 
1114a2ae208SSatish Balay #undef __FUNCT__
1124a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
1131f428162SBarry Smith /*@
1142bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
1152bdab257SBarry Smith     ordering and a global parallel ordering.
1162bdab257SBarry Smith 
1170f5bd95cSBarry Smith     Not collective
118b9cd556bSLois Curfman McInnes 
119a997ad1aSLois Curfman McInnes     Input Parameter:
1208c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
1212bdab257SBarry Smith 
122a997ad1aSLois Curfman McInnes     Output Parameter:
1232bdab257SBarry Smith .   mapping - new mapping data structure
1242bdab257SBarry Smith 
125f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
126a997ad1aSLois Curfman McInnes     Level: advanced
127a997ad1aSLois Curfman McInnes 
128273d9f13SBarry Smith     Concepts: mapping^local to global
1292bdab257SBarry Smith 
1302bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1312bdab257SBarry Smith @*/
1327087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1332bdab257SBarry Smith {
1346849ba73SBarry Smith   PetscErrorCode ierr;
1353bbf0e92SBarry Smith   PetscInt       n,bs;
1365d0c19d7SBarry Smith   const PetscInt *indices;
1372bdab257SBarry Smith   MPI_Comm       comm;
1383bbf0e92SBarry Smith   PetscBool      isblock;
1393a40ed3dSBarry Smith 
1403a40ed3dSBarry Smith   PetscFunctionBegin;
1410700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1424482741eSBarry Smith   PetscValidPointer(mapping,2);
1432bdab257SBarry Smith 
1442bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1453b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1463bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1476006e8d2SBarry Smith   if (!isblock) {
148f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
149f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1502bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1516006e8d2SBarry Smith   } else {
1526006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
153f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
15428bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
155f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1566006e8d2SBarry Smith   }
1573a40ed3dSBarry Smith   PetscFunctionReturn(0);
1582bdab257SBarry Smith }
1595a5d4f66SBarry Smith 
160a4d96a55SJed Brown #undef __FUNCT__
161a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
162a4d96a55SJed Brown /*@C
163a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
164a4d96a55SJed Brown     ordering and a global parallel ordering.
165a4d96a55SJed Brown 
166a4d96a55SJed Brown     Collective
167a4d96a55SJed Brown 
168a4d96a55SJed Brown     Input Parameter:
169a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
170a4d96a55SJed Brown -   start - first global index on this process
171a4d96a55SJed Brown 
172a4d96a55SJed Brown     Output Parameter:
173a4d96a55SJed Brown .   mapping - new mapping data structure
174a4d96a55SJed Brown 
175a4d96a55SJed Brown     Level: advanced
176a4d96a55SJed Brown 
177a4d96a55SJed Brown     Concepts: mapping^local to global
178a4d96a55SJed Brown 
179a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
180a4d96a55SJed Brown @*/
181a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
182a4d96a55SJed Brown {
183a4d96a55SJed Brown   PetscErrorCode ierr;
184a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
185a4d96a55SJed Brown   const PetscInt *ilocal;
186a4d96a55SJed Brown   MPI_Comm       comm;
187a4d96a55SJed Brown 
188a4d96a55SJed Brown   PetscFunctionBegin;
189a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
190a4d96a55SJed Brown   PetscValidPointer(mapping,3);
191a4d96a55SJed Brown 
192a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1930298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
194f6e5521dSKarl Rupp   if (ilocal) {
195f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
196f6e5521dSKarl Rupp   }
197a4d96a55SJed Brown   else maxlocal = nleaves;
198785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
199785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
200a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
201a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
202a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
203a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
204f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
205a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
206a4d96a55SJed Brown   PetscFunctionReturn(0);
207a4d96a55SJed Brown }
208b46b645bSBarry Smith 
2094a2ae208SSatish Balay #undef __FUNCT__
21063fa5c83Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingSetBlockSize"
21163fa5c83Sstefano_zampini /*@
21263fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
21363fa5c83Sstefano_zampini 
21463fa5c83Sstefano_zampini     Not collective
21563fa5c83Sstefano_zampini 
21663fa5c83Sstefano_zampini     Input Parameters:
21763fa5c83Sstefano_zampini .   mapping - mapping data structure
21863fa5c83Sstefano_zampini .   bs - the blocksize
21963fa5c83Sstefano_zampini 
22063fa5c83Sstefano_zampini     Level: advanced
22163fa5c83Sstefano_zampini 
22263fa5c83Sstefano_zampini     Concepts: mapping^local to global
22363fa5c83Sstefano_zampini 
22463fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
22563fa5c83Sstefano_zampini @*/
22663fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
22763fa5c83Sstefano_zampini {
22863fa5c83Sstefano_zampini   PetscInt       *nid,*oid;
2298b7cb0e6Sstefano_zampini   PetscInt       i,cn,on,obs,nn,cum,r,rbs,ri;
23063fa5c83Sstefano_zampini   PetscErrorCode ierr;
23163fa5c83Sstefano_zampini 
23263fa5c83Sstefano_zampini   PetscFunctionBegin;
23363fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
23463fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
23563fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
23663fa5c83Sstefano_zampini   on  = mapping->n;
23763fa5c83Sstefano_zampini   obs = mapping->bs;
23863fa5c83Sstefano_zampini   oid = mapping->indices;
23963fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
24063fa5c83Sstefano_zampini   if ((on*obs)%bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D and number of block indices %D",bs,obs,on);
2418b7cb0e6Sstefano_zampini   if (bs < obs && obs%bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D",bs,obs);
2428b7cb0e6Sstefano_zampini   if (bs < obs) {
2438b7cb0e6Sstefano_zampini     r   = bs;
2448b7cb0e6Sstefano_zampini     rbs = obs/bs;
2458b7cb0e6Sstefano_zampini     ri  = 1;
2468b7cb0e6Sstefano_zampini   } else {
2478b7cb0e6Sstefano_zampini     r   = obs;
2488b7cb0e6Sstefano_zampini     rbs = 1;
2498b7cb0e6Sstefano_zampini     ri  = bs/obs;
2508b7cb0e6Sstefano_zampini   }
25163fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
252c9345713Sstefano_zampini   for (i=0,cum=0,cn=0;i<on;i++) {
2538b7cb0e6Sstefano_zampini     if (oid[i] < 0) cn += r;
2548b7cb0e6Sstefano_zampini     if ((cn && !(cn%bs)) || (oid[i] > -1 && !((oid[i]*obs)%bs))) {
25563fa5c83Sstefano_zampini       if (cum == nn) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices",bs,obs);
2568b7cb0e6Sstefano_zampini       if (cn && cn%bs) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices (neg = %D, rbs %D, r %D)",bs,obs,cn,rbs,r);
2578b7cb0e6Sstefano_zampini       if (cn) {
2588b7cb0e6Sstefano_zampini         PetscInt j;
2598b7cb0e6Sstefano_zampini         for (j=0;j<rbs;j++) nid[cum++] = -1;
2608b7cb0e6Sstefano_zampini       } else {
2618b7cb0e6Sstefano_zampini         PetscInt j;
2628b7cb0e6Sstefano_zampini         for (j=1;j<ri;j++) {
2638b7cb0e6Sstefano_zampini           if (i+j >= on) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices found",bs,obs);
2648b7cb0e6Sstefano_zampini           if (oid[i] != oid[i+j]-j) SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices %D %D (%D,%D)",bs,obs,oid[i],oid[i+j],j,ri);
2658b7cb0e6Sstefano_zampini         }
2668b7cb0e6Sstefano_zampini         for (j=0;j<rbs;j++) nid[cum++] = (oid[i]*obs)/bs+j;
2678b7cb0e6Sstefano_zampini       }
268c9345713Sstefano_zampini       cn   = 0;
26963fa5c83Sstefano_zampini     }
27063fa5c83Sstefano_zampini   }
271c9345713Sstefano_zampini   if (cum != nn || cn) {
27263fa5c83Sstefano_zampini     ierr = PetscFree(nid);CHKERRQ(ierr);
2738b7cb0e6Sstefano_zampini     SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Incompatible block sizes %D and %D (new block indices found %D != %D, neg %D, rbs %D)",bs,obs,cum,nn,cn,rbs);
27463fa5c83Sstefano_zampini   }
27563fa5c83Sstefano_zampini   mapping->n           = nn;
27663fa5c83Sstefano_zampini   mapping->bs          = bs;
27763fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
27863fa5c83Sstefano_zampini   mapping->indices     = nid;
279c9345713Sstefano_zampini   ierr                 = PetscFree(mapping->globals);CHKERRQ(ierr);
280c9345713Sstefano_zampini   mapping->globalstart = 0;
281c9345713Sstefano_zampini   mapping->globalend   = 0;
28263fa5c83Sstefano_zampini   PetscFunctionReturn(0);
28363fa5c83Sstefano_zampini }
28463fa5c83Sstefano_zampini 
28563fa5c83Sstefano_zampini #undef __FUNCT__
28645b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
28745b6f7e9SBarry Smith /*@
28845b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
28945b6f7e9SBarry Smith     ordering and a global parallel ordering.
29045b6f7e9SBarry Smith 
29145b6f7e9SBarry Smith     Not Collective
29245b6f7e9SBarry Smith 
29345b6f7e9SBarry Smith     Input Parameters:
29445b6f7e9SBarry Smith .   mapping - mapping data structure
29545b6f7e9SBarry Smith 
29645b6f7e9SBarry Smith     Output Parameter:
29745b6f7e9SBarry Smith .   bs - the blocksize
29845b6f7e9SBarry Smith 
29945b6f7e9SBarry Smith     Level: advanced
30045b6f7e9SBarry Smith 
30145b6f7e9SBarry Smith     Concepts: mapping^local to global
30245b6f7e9SBarry Smith 
30345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
30445b6f7e9SBarry Smith @*/
30545b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
30645b6f7e9SBarry Smith {
30745b6f7e9SBarry Smith   PetscFunctionBegin;
308cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
30945b6f7e9SBarry Smith   *bs = mapping->bs;
31045b6f7e9SBarry Smith   PetscFunctionReturn(0);
31145b6f7e9SBarry Smith }
31245b6f7e9SBarry Smith 
31345b6f7e9SBarry Smith #undef __FUNCT__
3144a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
315ba5bb76aSSatish Balay /*@
31690f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
31790f02eecSBarry Smith     ordering and a global parallel ordering.
3182362add9SBarry Smith 
31989d82c54SBarry Smith     Not Collective, but communicator may have more than one process
320b9cd556bSLois Curfman McInnes 
3212362add9SBarry Smith     Input Parameters:
32289d82c54SBarry Smith +   comm - MPI communicator
323f0413b6fSBarry Smith .   bs - the block size
32428bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
32528bc9809SBarry Smith .   indices - the global index for each local element, these do not need to be in increasing order (sorted), these values should not be scaled (i.e. multiplied) by the blocksize bs
326d5ad8652SBarry Smith -   mode - see PetscCopyMode
3272362add9SBarry Smith 
328a997ad1aSLois Curfman McInnes     Output Parameter:
32990f02eecSBarry Smith .   mapping - new mapping data structure
3302362add9SBarry Smith 
331f0413b6fSBarry Smith     Notes: There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
332a997ad1aSLois Curfman McInnes     Level: advanced
333a997ad1aSLois Curfman McInnes 
334273d9f13SBarry Smith     Concepts: mapping^local to global
3352362add9SBarry Smith 
336d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
3372362add9SBarry Smith @*/
33860c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
3392362add9SBarry Smith {
3406849ba73SBarry Smith   PetscErrorCode ierr;
34132dcc486SBarry Smith   PetscInt       *in;
342b46b645bSBarry Smith 
343b46b645bSBarry Smith   PetscFunctionBegin;
34473911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
3454482741eSBarry Smith   PetscValidPointer(mapping,4);
346b46b645bSBarry Smith 
3470298fd71SBarry Smith   *mapping = NULL;
348607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
3492362add9SBarry Smith 
35073107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
35160c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
352d4bb536fSBarry Smith   (*mapping)->n             = n;
353f0413b6fSBarry Smith   (*mapping)->bs            = bs;
354268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
355268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
356268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
357268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
358268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
359d4bb536fSBarry Smith   /*
360d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
361d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
362d4bb536fSBarry Smith   */
363d4bb536fSBarry Smith   (*mapping)->globals = 0;
364d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
365785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
366d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
367d5ad8652SBarry Smith     (*mapping)->indices = in;
3686389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3696389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
3706389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
3716389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
3726389a1a1SBarry Smith   }
37360c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
374d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
3753a40ed3dSBarry Smith   PetscFunctionReturn(0);
3762362add9SBarry Smith }
3772362add9SBarry Smith 
3784a2ae208SSatish Balay #undef __FUNCT__
3794a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
38090f02eecSBarry Smith /*@
38190f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
38290f02eecSBarry Smith    ordering and a global parallel ordering.
38390f02eecSBarry Smith 
3840f5bd95cSBarry Smith    Note Collective
385b9cd556bSLois Curfman McInnes 
38690f02eecSBarry Smith    Input Parameters:
38790f02eecSBarry Smith .  mapping - mapping data structure
38890f02eecSBarry Smith 
389a997ad1aSLois Curfman McInnes    Level: advanced
390a997ad1aSLois Curfman McInnes 
3913acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
39290f02eecSBarry Smith @*/
3936bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
39490f02eecSBarry Smith {
395dfbe8321SBarry Smith   PetscErrorCode ierr;
3965fd66863SKarl Rupp 
3973a40ed3dSBarry Smith   PetscFunctionBegin;
3986bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
3996bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
400997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
4016bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
4026bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
403268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
404268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
405268a049cSStefano Zampini   if ((*mapping)->info_indices) {
406268a049cSStefano Zampini     PetscInt i;
407268a049cSStefano Zampini 
408268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
409268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
410268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
411268a049cSStefano Zampini     }
412268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
413268a049cSStefano Zampini   }
414d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
415992144d0SBarry Smith   *mapping = 0;
4163a40ed3dSBarry Smith   PetscFunctionReturn(0);
41790f02eecSBarry Smith }
41890f02eecSBarry Smith 
4194a2ae208SSatish Balay #undef __FUNCT__
4204a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
42190f02eecSBarry Smith /*@
4223acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
4233acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
4243acfe500SLois Curfman McInnes     context.
42590f02eecSBarry Smith 
426b9cd556bSLois Curfman McInnes     Not collective
427b9cd556bSLois Curfman McInnes 
42890f02eecSBarry Smith     Input Parameters:
429b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
430b9cd556bSLois Curfman McInnes -   is - index set in local numbering
43190f02eecSBarry Smith 
43290f02eecSBarry Smith     Output Parameters:
43390f02eecSBarry Smith .   newis - index set in global numbering
43490f02eecSBarry Smith 
435a997ad1aSLois Curfman McInnes     Level: advanced
436a997ad1aSLois Curfman McInnes 
437273d9f13SBarry Smith     Concepts: mapping^local to global
4383acfe500SLois Curfman McInnes 
43990f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
440d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
44190f02eecSBarry Smith @*/
4427087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
44390f02eecSBarry Smith {
4446849ba73SBarry Smith   PetscErrorCode ierr;
445e24637baSBarry Smith   PetscInt       n,*idxout;
4465d0c19d7SBarry Smith   const PetscInt *idxin;
4473a40ed3dSBarry Smith 
4483a40ed3dSBarry Smith   PetscFunctionBegin;
4490700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
4500700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
4514482741eSBarry Smith   PetscValidPointer(newis,3);
45290f02eecSBarry Smith 
4533b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
45490f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
455785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
456e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
4573b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
458543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
4593a40ed3dSBarry Smith   PetscFunctionReturn(0);
46090f02eecSBarry Smith }
46190f02eecSBarry Smith 
462afcb2eb5SJed Brown #undef __FUNCT__
463afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
464b89cb25eSSatish Balay /*@
4653acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
4663acfe500SLois Curfman McInnes    and converts them to the global numbering.
46790f02eecSBarry Smith 
468b9cd556bSLois Curfman McInnes    Not collective
469b9cd556bSLois Curfman McInnes 
470bb25748dSBarry Smith    Input Parameters:
471b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
472bb25748dSBarry Smith .  N - number of integers
473b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
474bb25748dSBarry Smith 
475bb25748dSBarry Smith    Output Parameter:
476bb25748dSBarry Smith .  out - indices in global numbering
477bb25748dSBarry Smith 
478b9cd556bSLois Curfman McInnes    Notes:
479b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
480d4bb536fSBarry Smith 
481a997ad1aSLois Curfman McInnes    Level: advanced
482a997ad1aSLois Curfman McInnes 
48345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
4840752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
485d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
486bb25748dSBarry Smith 
487273d9f13SBarry Smith     Concepts: mapping^local to global
488afcb2eb5SJed Brown @*/
489afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
490afcb2eb5SJed Brown {
491cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
49245b6f7e9SBarry Smith 
49345b6f7e9SBarry Smith   PetscFunctionBegin;
494cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
495cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
496cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
49745b6f7e9SBarry Smith   if (bs == 1) {
498cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
49945b6f7e9SBarry Smith     for (i=0; i<N; i++) {
50045b6f7e9SBarry Smith       if (in[i] < 0) {
50145b6f7e9SBarry Smith         out[i] = in[i];
50245b6f7e9SBarry Smith         continue;
50345b6f7e9SBarry Smith       }
504e24637baSBarry Smith       if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i);
50545b6f7e9SBarry Smith       out[i] = idx[in[i]];
50645b6f7e9SBarry Smith     }
50745b6f7e9SBarry Smith   } else {
508cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
50945b6f7e9SBarry Smith     for (i=0; i<N; i++) {
51045b6f7e9SBarry Smith       if (in[i] < 0) {
51145b6f7e9SBarry Smith         out[i] = in[i];
51245b6f7e9SBarry Smith         continue;
51345b6f7e9SBarry Smith       }
514e24637baSBarry Smith       if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i);
51545b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
51645b6f7e9SBarry Smith     }
51745b6f7e9SBarry Smith   }
51845b6f7e9SBarry Smith   PetscFunctionReturn(0);
51945b6f7e9SBarry Smith }
52045b6f7e9SBarry Smith 
52145b6f7e9SBarry Smith #undef __FUNCT__
52245b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
52345b6f7e9SBarry Smith /*@
5246006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
52545b6f7e9SBarry Smith 
52645b6f7e9SBarry Smith    Not collective
52745b6f7e9SBarry Smith 
52845b6f7e9SBarry Smith    Input Parameters:
52945b6f7e9SBarry Smith +  mapping - the local to global mapping context
53045b6f7e9SBarry Smith .  N - number of integers
5316006e8d2SBarry Smith -  in - input indices in local block numbering
53245b6f7e9SBarry Smith 
53345b6f7e9SBarry Smith    Output Parameter:
5346006e8d2SBarry Smith .  out - indices in global block numbering
53545b6f7e9SBarry Smith 
53645b6f7e9SBarry Smith    Notes:
53745b6f7e9SBarry Smith    The in and out array parameters may be identical.
53845b6f7e9SBarry Smith 
5396006e8d2SBarry Smith    Example:
5406006e8d2SBarry Smith      If the index values are {0,1,6,7} set with a call to ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,2,2,{0,3}) then the mapping applied to 0
5416006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
5426006e8d2SBarry Smith 
54345b6f7e9SBarry Smith    Level: advanced
54445b6f7e9SBarry Smith 
54545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
54645b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
54745b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
54845b6f7e9SBarry Smith 
54945b6f7e9SBarry Smith     Concepts: mapping^local to global
55045b6f7e9SBarry Smith @*/
55145b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
55245b6f7e9SBarry Smith {
553cbc1caf0SMatthew G. Knepley 
554cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
555cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
556cbc1caf0SMatthew G. Knepley   {
557afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
558afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
559d4bb536fSBarry Smith 
560afcb2eb5SJed Brown     for (i=0; i<N; i++) {
561afcb2eb5SJed Brown       if (in[i] < 0) {
562afcb2eb5SJed Brown         out[i] = in[i];
563afcb2eb5SJed Brown         continue;
564afcb2eb5SJed Brown       }
565e24637baSBarry Smith       if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local block index %D too large %D (max) at %D",in[i],Nmax-1,i);
566afcb2eb5SJed Brown       out[i] = idx[in[i]];
567afcb2eb5SJed Brown     }
568cbc1caf0SMatthew G. Knepley   }
569afcb2eb5SJed Brown   PetscFunctionReturn(0);
570afcb2eb5SJed Brown }
571d4bb536fSBarry Smith 
572d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
573d4bb536fSBarry Smith 
5744a2ae208SSatish Balay #undef __FUNCT__
5754a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
576d4bb536fSBarry Smith /*
577d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
578d4bb536fSBarry Smith */
5796849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
580d4bb536fSBarry Smith {
5816849ba73SBarry Smith   PetscErrorCode ierr;
58232dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
583d4bb536fSBarry Smith 
5843a40ed3dSBarry Smith   PetscFunctionBegin;
585d4bb536fSBarry Smith   end   = 0;
586ec268f7cSJed Brown   start = PETSC_MAX_INT;
587d4bb536fSBarry Smith 
588d4bb536fSBarry Smith   for (i=0; i<n; i++) {
589d4bb536fSBarry Smith     if (idx[i] < 0) continue;
590d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
591d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
592d4bb536fSBarry Smith   }
593d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
594d4bb536fSBarry Smith   mapping->globalstart = start;
595d4bb536fSBarry Smith   mapping->globalend   = end;
596d4bb536fSBarry Smith 
597854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
598b0a32e0cSBarry Smith   mapping->globals = globals;
599f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
600d4bb536fSBarry Smith   for (i=0; i<n; i++) {
601d4bb536fSBarry Smith     if (idx[i] < 0) continue;
602d4bb536fSBarry Smith     globals[idx[i] - start] = i;
603d4bb536fSBarry Smith   }
604d4bb536fSBarry Smith 
6053bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
6063a40ed3dSBarry Smith   PetscFunctionReturn(0);
607d4bb536fSBarry Smith }
608d4bb536fSBarry Smith 
6094a2ae208SSatish Balay #undef __FUNCT__
6104a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
611d4bb536fSBarry Smith /*@
612a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
613a997ad1aSLois Curfman McInnes     specified with a global numbering.
614d4bb536fSBarry Smith 
615b9cd556bSLois Curfman McInnes     Not collective
616b9cd556bSLois Curfman McInnes 
617d4bb536fSBarry Smith     Input Parameters:
618b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
619d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
620d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
621d4bb536fSBarry Smith .   n - number of global indices to map
622b9cd556bSLois Curfman McInnes -   idx - global indices to map
623d4bb536fSBarry Smith 
624d4bb536fSBarry Smith     Output Parameters:
625b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
626b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
627e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
6280298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
629e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
630e182c471SBarry Smith              a second time to set the values.
631d4bb536fSBarry Smith 
632b9cd556bSLois Curfman McInnes     Notes:
6330298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
634d4bb536fSBarry Smith 
6350f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6360f5bd95cSBarry Smith     array to compute these.
6370f5bd95cSBarry Smith 
638a997ad1aSLois Curfman McInnes     Level: advanced
639a997ad1aSLois Curfman McInnes 
64032fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
64132fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
64232fd6b96SBarry Smith 
643273d9f13SBarry Smith     Concepts: mapping^global to local
644d4bb536fSBarry Smith 
6459d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
646d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
647d4bb536fSBarry Smith @*/
6487087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
64932dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
650d4bb536fSBarry Smith {
6519d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
6529d90f715SBarry Smith   PetscErrorCode ierr;
6539d90f715SBarry Smith 
6549d90f715SBarry Smith   PetscFunctionBegin;
6559d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6569d90f715SBarry Smith   if (!mapping->globals) {
6579d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
6589d90f715SBarry Smith   }
6599d90f715SBarry Smith   globals = mapping->globals;
6609d90f715SBarry Smith   start   = mapping->globalstart;
6619d90f715SBarry Smith   end     = mapping->globalend;
6629d90f715SBarry Smith   bs      = mapping->bs;
6639d90f715SBarry Smith 
6649d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
6659d90f715SBarry Smith     if (idxout) {
6669d90f715SBarry Smith       for (i=0; i<n; i++) {
6679d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
6689d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
669663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
6709d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6719d90f715SBarry Smith       }
6729d90f715SBarry Smith     }
6739d90f715SBarry Smith     if (nout) *nout = n;
6749d90f715SBarry Smith   } else {
6759d90f715SBarry Smith     if (idxout) {
6769d90f715SBarry Smith       for (i=0; i<n; i++) {
6779d90f715SBarry Smith         if (idx[i] < 0) continue;
6789d90f715SBarry Smith         if (idx[i] < bs*start) continue;
679663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6809d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6819d90f715SBarry Smith         if (tmp < 0) continue;
6829d90f715SBarry Smith         idxout[nf++] = tmp;
6839d90f715SBarry Smith       }
6849d90f715SBarry Smith     } else {
6859d90f715SBarry Smith       for (i=0; i<n; i++) {
6869d90f715SBarry Smith         if (idx[i] < 0) continue;
6879d90f715SBarry Smith         if (idx[i] < bs*start) continue;
688663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
6899d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
6909d90f715SBarry Smith         if (tmp < 0) continue;
6919d90f715SBarry Smith         nf++;
6929d90f715SBarry Smith       }
6939d90f715SBarry Smith     }
6949d90f715SBarry Smith     if (nout) *nout = nf;
6959d90f715SBarry Smith   }
6969d90f715SBarry Smith   PetscFunctionReturn(0);
6979d90f715SBarry Smith }
6989d90f715SBarry Smith 
6999d90f715SBarry Smith #undef __FUNCT__
700d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
701d4fe737eSStefano Zampini /*@
702d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
703d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
704d4fe737eSStefano Zampini     context.
705d4fe737eSStefano Zampini 
706d4fe737eSStefano Zampini     Not collective
707d4fe737eSStefano Zampini 
708d4fe737eSStefano Zampini     Input Parameters:
709d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
710d4fe737eSStefano Zampini -   is - index set in global numbering
711d4fe737eSStefano Zampini 
712d4fe737eSStefano Zampini     Output Parameters:
713d4fe737eSStefano Zampini .   newis - index set in local numbering
714d4fe737eSStefano Zampini 
715d4fe737eSStefano Zampini     Level: advanced
716d4fe737eSStefano Zampini 
717d4fe737eSStefano Zampini     Concepts: mapping^local to global
718d4fe737eSStefano Zampini 
719d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
720d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
721d4fe737eSStefano Zampini @*/
722d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
723d4fe737eSStefano Zampini {
724d4fe737eSStefano Zampini   PetscErrorCode ierr;
725d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
726d4fe737eSStefano Zampini   const PetscInt *idxin;
727d4fe737eSStefano Zampini 
728d4fe737eSStefano Zampini   PetscFunctionBegin;
729d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
730d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
731d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
732d4fe737eSStefano Zampini 
733d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
734d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
735d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
736d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
737d4fe737eSStefano Zampini   } else {
738d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
739d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
740d4fe737eSStefano Zampini   }
741d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
742d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
743d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
744d4fe737eSStefano Zampini   PetscFunctionReturn(0);
745d4fe737eSStefano Zampini }
746d4fe737eSStefano Zampini 
747d4fe737eSStefano Zampini #undef __FUNCT__
7489d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
7499d90f715SBarry Smith /*@
7509d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
7519d90f715SBarry Smith     specified with a block global numbering.
7529d90f715SBarry Smith 
7539d90f715SBarry Smith     Not collective
7549d90f715SBarry Smith 
7559d90f715SBarry Smith     Input Parameters:
7569d90f715SBarry Smith +   mapping - mapping between local and global numbering
7579d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
7589d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
7599d90f715SBarry Smith .   n - number of global indices to map
7609d90f715SBarry Smith -   idx - global indices to map
7619d90f715SBarry Smith 
7629d90f715SBarry Smith     Output Parameters:
7639d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
7649d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
7659d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
7669d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
7679d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
7689d90f715SBarry Smith              a second time to set the values.
7699d90f715SBarry Smith 
7709d90f715SBarry Smith     Notes:
7719d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
7729d90f715SBarry Smith 
7739d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
7749d90f715SBarry Smith     array to compute these.
7759d90f715SBarry Smith 
7769d90f715SBarry Smith     Level: advanced
7779d90f715SBarry Smith 
7789d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
7799d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
7809d90f715SBarry Smith 
7819d90f715SBarry Smith     Concepts: mapping^global to local
7829d90f715SBarry Smith 
7839d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
7849d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
7859d90f715SBarry Smith @*/
7869d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
7879d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
7889d90f715SBarry Smith {
78932dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
7906849ba73SBarry Smith   PetscErrorCode ierr;
791d4bb536fSBarry Smith 
7923a40ed3dSBarry Smith   PetscFunctionBegin;
7930700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
794d4bb536fSBarry Smith   if (!mapping->globals) {
795d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
796d4bb536fSBarry Smith   }
797d4bb536fSBarry Smith   globals = mapping->globals;
798d4bb536fSBarry Smith   start   = mapping->globalstart;
799d4bb536fSBarry Smith   end     = mapping->globalend;
800d4bb536fSBarry Smith 
801d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
802d4bb536fSBarry Smith     if (idxout) {
803d4bb536fSBarry Smith       for (i=0; i<n; i++) {
804d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
805d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
806d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
807d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
808d4bb536fSBarry Smith       }
809d4bb536fSBarry Smith     }
810d4bb536fSBarry Smith     if (nout) *nout = n;
811d4bb536fSBarry Smith   } else {
812d4bb536fSBarry Smith     if (idxout) {
813d4bb536fSBarry Smith       for (i=0; i<n; i++) {
814d4bb536fSBarry Smith         if (idx[i] < 0) continue;
815d4bb536fSBarry Smith         if (idx[i] < start) continue;
816d4bb536fSBarry Smith         if (idx[i] > end) continue;
817d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
818d4bb536fSBarry Smith         if (tmp < 0) continue;
819d4bb536fSBarry Smith         idxout[nf++] = tmp;
820d4bb536fSBarry Smith       }
821d4bb536fSBarry Smith     } else {
822d4bb536fSBarry Smith       for (i=0; i<n; i++) {
823d4bb536fSBarry Smith         if (idx[i] < 0) continue;
824d4bb536fSBarry Smith         if (idx[i] < start) continue;
825d4bb536fSBarry Smith         if (idx[i] > end) continue;
826d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
827d4bb536fSBarry Smith         if (tmp < 0) continue;
828d4bb536fSBarry Smith         nf++;
829d4bb536fSBarry Smith       }
830d4bb536fSBarry Smith     }
831d4bb536fSBarry Smith     if (nout) *nout = nf;
832d4bb536fSBarry Smith   }
8333a40ed3dSBarry Smith   PetscFunctionReturn(0);
834d4bb536fSBarry Smith }
83590f02eecSBarry Smith 
8364a2ae208SSatish Balay #undef __FUNCT__
8376a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
83889d82c54SBarry Smith /*@C
8396a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
84089d82c54SBarry Smith      each index shared by more than one processor
84189d82c54SBarry Smith 
84289d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
84389d82c54SBarry Smith 
84489d82c54SBarry Smith     Input Parameters:
84589d82c54SBarry Smith .   mapping - the mapping from local to global indexing
84689d82c54SBarry Smith 
84789d82c54SBarry Smith     Output Parameter:
84889d82c54SBarry Smith +   nproc - number of processors that are connected to this one
84989d82c54SBarry Smith .   proc - neighboring processors
85007b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
8513463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
85289d82c54SBarry Smith 
85389d82c54SBarry Smith     Level: advanced
85489d82c54SBarry Smith 
855273d9f13SBarry Smith     Concepts: mapping^local to global
85689d82c54SBarry Smith 
8572cfcea29SBarry Smith     Fortran Usage:
8582cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
8592cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
8602cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
8612cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
8622cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
8632cfcea29SBarry Smith 
8642cfcea29SBarry Smith 
86507b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
86607b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
86789d82c54SBarry Smith @*/
8686a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
86989d82c54SBarry Smith {
8706849ba73SBarry Smith   PetscErrorCode ierr;
871268a049cSStefano Zampini 
872268a049cSStefano Zampini   PetscFunctionBegin;
873268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
874268a049cSStefano Zampini   if (mapping->info_cached) {
875268a049cSStefano Zampini     *nproc = mapping->info_nproc;
876268a049cSStefano Zampini     *procs = mapping->info_procs;
877268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
878268a049cSStefano Zampini     *indices = mapping->info_indices;
879268a049cSStefano Zampini   } else {
880268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
881268a049cSStefano Zampini   }
882268a049cSStefano Zampini   PetscFunctionReturn(0);
883268a049cSStefano Zampini }
884268a049cSStefano Zampini 
885268a049cSStefano Zampini #undef __FUNCT__
886268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
887268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
888268a049cSStefano Zampini {
889268a049cSStefano Zampini   PetscErrorCode ierr;
89097f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
89132dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
89232dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
89397f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
89432dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
89532dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
89689d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
89730dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
898ce94432eSBarry Smith   MPI_Comm       comm;
899ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
90089d82c54SBarry Smith 
90189d82c54SBarry Smith   PetscFunctionBegin;
902ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
90324cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
90424cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
90524cf384cSBarry Smith   if (size == 1) {
90624cf384cSBarry Smith     *nproc         = 0;
9070298fd71SBarry Smith     *procs         = NULL;
90895dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
9091e2105dcSBarry Smith     (*numprocs)[0] = 0;
91095dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
9110298fd71SBarry Smith     (*indices)[0]  = NULL;
912268a049cSStefano Zampini     /* save info for reuse */
913268a049cSStefano Zampini     mapping->info_nproc = *nproc;
914268a049cSStefano Zampini     mapping->info_procs = *procs;
915268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
916268a049cSStefano Zampini     mapping->info_indices = *indices;
917268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
91824cf384cSBarry Smith     PetscFunctionReturn(0);
91924cf384cSBarry Smith   }
92024cf384cSBarry Smith 
921c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
92207b52d57SBarry Smith 
9233677ff5aSBarry Smith   /*
9246a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
9253677ff5aSBarry Smith 
9263677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
9273677ff5aSBarry Smith            numbering, just for this routine.
9283677ff5aSBarry Smith 
9293677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
9303677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
9313677ff5aSBarry Smith 
9323677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
9333677ff5aSBarry Smith 
9343677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
9353677ff5aSBarry Smith            local subdomain
9363677ff5aSBarry Smith   */
93724cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
93824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
93924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
94089d82c54SBarry Smith 
94189d82c54SBarry Smith   for (i=0; i<n; i++) {
94289d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
94389d82c54SBarry Smith   }
944b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
94578058e43SBarry Smith   Ng++;
94689d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
94789d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
948bc8ff85bSBarry Smith   scale  = Ng/size + 1;
949a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
950caba0dd0SBarry Smith   rstart = scale*rank;
95189d82c54SBarry Smith 
95289d82c54SBarry Smith   /* determine ownership ranges of global indices */
953785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
95432dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
95589d82c54SBarry Smith 
95689d82c54SBarry Smith   /* determine owners of each local node  */
957785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
95889d82c54SBarry Smith   for (i=0; i<n; i++) {
9593677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
96027c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
9613677ff5aSBarry Smith     owner[i]         = proc;
96227c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
96389d82c54SBarry Smith   }
96427c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
9657904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
96689d82c54SBarry Smith 
96789d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
96827c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9697904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
97089d82c54SBarry Smith 
97189d82c54SBarry Smith   /* post receives for owned rows */
972785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
973854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
97489d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
97532dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
97689d82c54SBarry Smith   }
97789d82c54SBarry Smith 
97889d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
979854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
980854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
98189d82c54SBarry Smith   starts[0] = 0;
982f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
98389d82c54SBarry Smith   for (i=0; i<n; i++) {
98489d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
98530dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
98689d82c54SBarry Smith   }
98789d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
98889d82c54SBarry Smith   starts[0] = 0;
989f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
99089d82c54SBarry Smith 
99189d82c54SBarry Smith   /* send the messages */
992854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
993854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
99489d82c54SBarry Smith   cnt = 0;
99589d82c54SBarry Smith   for (i=0; i<size; i++) {
99627c402fcSBarry Smith     if (nprocs[2*i]) {
99732dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
99830dcb7c9SBarry Smith       dest[cnt] = i;
99989d82c54SBarry Smith       cnt++;
100089d82c54SBarry Smith     }
100189d82c54SBarry Smith   }
100289d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
100389d82c54SBarry Smith 
100489d82c54SBarry Smith   /* wait on receives */
1005854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
1006854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
100789d82c54SBarry Smith   cnt  = nrecvs;
1008854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
100932dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
101089d82c54SBarry Smith   while (cnt) {
101189d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
101289d82c54SBarry Smith     /* unpack receives into our local space */
101332dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
101489d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
101530dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
1016caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
101730dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
101889d82c54SBarry Smith     cnt--;
101989d82c54SBarry Smith   }
102089d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
102189d82c54SBarry Smith 
102230dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1023bc8ff85bSBarry Smith   nowned  = 0;
1024bc8ff85bSBarry Smith   nownedm = 0;
1025bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
1026bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
1027bc8ff85bSBarry Smith   }
1028bc8ff85bSBarry Smith 
1029bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1030854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1031854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1032bc8ff85bSBarry Smith   starts[0] = 0;
1033bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1034bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1035bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1036bc8ff85bSBarry Smith   }
1037bc8ff85bSBarry Smith 
103830dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1039bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1040bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
104130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1042f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1043bc8ff85bSBarry Smith     }
1044bc8ff85bSBarry Smith   }
1045bc8ff85bSBarry Smith 
104607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
104730dcb7c9SBarry Smith     starts[0] = 0;
104830dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
104930dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
105030dcb7c9SBarry Smith       else starts[i] = starts[i-1];
105130dcb7c9SBarry Smith     }
105230dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
105330dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
10547904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
105530dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
10567904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
105730dcb7c9SBarry Smith         }
105830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
105930dcb7c9SBarry Smith       }
106030dcb7c9SBarry Smith     }
10610ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
106207b52d57SBarry Smith   } /* -----------------------------------  */
106330dcb7c9SBarry Smith 
10643677ff5aSBarry Smith   /* wait on original sends */
10653a96401aSBarry Smith   if (nsends) {
1066785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
10673a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10683a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10693a96401aSBarry Smith   }
107089d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10713a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
10723677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
10733677ff5aSBarry Smith 
10743677ff5aSBarry Smith   /* pack messages to send back to local owners */
107530dcb7c9SBarry Smith   starts[0] = 0;
107630dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
107730dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
107830dcb7c9SBarry Smith     else starts[i] = starts[i-1];
107930dcb7c9SBarry Smith   }
108030dcb7c9SBarry Smith   nsends2 = nrecvs;
1081854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
108230dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
108330dcb7c9SBarry Smith     nprocs[i] = 1;
108430dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
108530dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1086f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
108730dcb7c9SBarry Smith     }
108830dcb7c9SBarry Smith   }
1089f6e5521dSKarl Rupp   nt = 0;
1090f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1091f6e5521dSKarl Rupp 
1092854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1093854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1094f6e5521dSKarl Rupp 
1095f6e5521dSKarl Rupp   starts2[0] = 0;
1096f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
109730dcb7c9SBarry Smith   /*
109830dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
109930dcb7c9SBarry Smith        (0) the number of nodes being sent back
110030dcb7c9SBarry Smith        (1) the local node number,
110130dcb7c9SBarry Smith        (2) the number of processors sharing it,
110230dcb7c9SBarry Smith        (3) the processors sharing it
110330dcb7c9SBarry Smith   */
110430dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
110530dcb7c9SBarry Smith     cnt = 1;
110630dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
110730dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
110830dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
110930dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
111030dcb7c9SBarry Smith         sends2[starts2[i]]++;
111130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
111230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
111332dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
111430dcb7c9SBarry Smith         cnt += nownedsenders[node];
111530dcb7c9SBarry Smith       }
111630dcb7c9SBarry Smith     }
111730dcb7c9SBarry Smith   }
111830dcb7c9SBarry Smith 
111930dcb7c9SBarry Smith   /* receive the message lengths */
112030dcb7c9SBarry Smith   nrecvs2 = nsends;
1121854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1122854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1123854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
112430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1125d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
112630dcb7c9SBarry Smith   }
1127d44834fbSBarry Smith 
11288a8e0b3aSBarry Smith   /* send the message lengths */
11298a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
11308a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
11318a8e0b3aSBarry Smith   }
11328a8e0b3aSBarry Smith 
1133d44834fbSBarry Smith   /* wait on receives of lens */
11340c468ba9SBarry Smith   if (nrecvs2) {
1135785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1136d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1137d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11380c468ba9SBarry Smith   }
1139a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1140d44834fbSBarry Smith 
114130dcb7c9SBarry Smith   starts3[0] = 0;
1142d44834fbSBarry Smith   nt         = 0;
114330dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
114430dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1145d44834fbSBarry Smith     nt          += lens2[i];
114630dcb7c9SBarry Smith   }
114776466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1148d44834fbSBarry Smith 
1149854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1150854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
115152b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
115232dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
115330dcb7c9SBarry Smith   }
115430dcb7c9SBarry Smith 
115530dcb7c9SBarry Smith   /* send the messages */
1156854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
115730dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
115832dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
115930dcb7c9SBarry Smith   }
116030dcb7c9SBarry Smith 
116130dcb7c9SBarry Smith   /* wait on receives */
11620c468ba9SBarry Smith   if (nrecvs2) {
1163785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
116430dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
116530dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
11660c468ba9SBarry Smith   }
116730dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
116830dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
116930dcb7c9SBarry Smith 
117007b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
117130dcb7c9SBarry Smith     cnt = 0;
117230dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
117330dcb7c9SBarry Smith       nt = recvs2[cnt++];
117430dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
11757904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
117630dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
11777904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
117830dcb7c9SBarry Smith         }
117930dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
118030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
118130dcb7c9SBarry Smith       }
118230dcb7c9SBarry Smith     }
11830ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
118407b52d57SBarry Smith   } /* -----------------------------------  */
118530dcb7c9SBarry Smith 
118630dcb7c9SBarry Smith   /* count number subdomains for each local node */
1187785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
118832dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
118930dcb7c9SBarry Smith   cnt  = 0;
119030dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
119130dcb7c9SBarry Smith     nt = recvs2[cnt++];
119230dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1193f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
119430dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
119530dcb7c9SBarry Smith     }
119630dcb7c9SBarry Smith   }
119730dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
119830dcb7c9SBarry Smith   *nproc    = nt;
1199854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1200854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1201854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
12020298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1203785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
120430dcb7c9SBarry Smith   cnt  = 0;
120530dcb7c9SBarry Smith   for (i=0; i<size; i++) {
120630dcb7c9SBarry Smith     if (nprocs[i] > 0) {
120730dcb7c9SBarry Smith       bprocs[i]        = cnt;
120830dcb7c9SBarry Smith       (*procs)[cnt]    = i;
120930dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1210785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
121130dcb7c9SBarry Smith       cnt++;
121230dcb7c9SBarry Smith     }
121330dcb7c9SBarry Smith   }
121430dcb7c9SBarry Smith 
121530dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
121632dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
121730dcb7c9SBarry Smith   cnt  = 0;
121830dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
121930dcb7c9SBarry Smith     nt = recvs2[cnt++];
122030dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1221f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
122230dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
122330dcb7c9SBarry Smith     }
122430dcb7c9SBarry Smith   }
122530dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
122607b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
122730dcb7c9SBarry Smith 
122807b52d57SBarry Smith   /* sort the node indexing by their global numbers */
122907b52d57SBarry Smith   nt = *nproc;
123007b52d57SBarry Smith   for (i=0; i<nt; i++) {
1231854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1232f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
123307b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
123407b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
123507b52d57SBarry Smith   }
123607b52d57SBarry Smith 
123707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
123830dcb7c9SBarry Smith     nt = *nproc;
123930dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
12407904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
124130dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
12427904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
124330dcb7c9SBarry Smith       }
124430dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
124530dcb7c9SBarry Smith     }
12460ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
124707b52d57SBarry Smith   } /* -----------------------------------  */
124830dcb7c9SBarry Smith 
124930dcb7c9SBarry Smith   /* wait on sends */
125030dcb7c9SBarry Smith   if (nsends2) {
1251785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
125230dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
125330dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
125430dcb7c9SBarry Smith   }
125530dcb7c9SBarry Smith 
125630dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
125730dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
125830dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12593677ff5aSBarry Smith 
1260bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1261bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1262bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
126330dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
126430dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
126589d82c54SBarry Smith 
126689d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
126797f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
126889d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
12693a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
127030dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
127124cf384cSBarry Smith 
127224cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
127324cf384cSBarry Smith   first_procs    = (*procs)[0];
127424cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
127524cf384cSBarry Smith   first_indices  = (*indices)[0];
127624cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
127724cf384cSBarry Smith     if ((*procs)[i] == rank) {
127824cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
127924cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
128024cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
128124cf384cSBarry Smith       (*procs)[i]    = first_procs;
128224cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
128324cf384cSBarry Smith       (*indices)[i]  = first_indices;
128424cf384cSBarry Smith       break;
128524cf384cSBarry Smith     }
128624cf384cSBarry Smith   }
1287268a049cSStefano Zampini 
1288268a049cSStefano Zampini   /* save info for reuse */
1289268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1290268a049cSStefano Zampini   mapping->info_procs = *procs;
1291268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1292268a049cSStefano Zampini   mapping->info_indices = *indices;
1293268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
129489d82c54SBarry Smith   PetscFunctionReturn(0);
129589d82c54SBarry Smith }
129689d82c54SBarry Smith 
12974a2ae208SSatish Balay #undef __FUNCT__
12986a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
12996a818285SBarry Smith /*@C
13006a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
13016a818285SBarry Smith 
13026a818285SBarry Smith     Collective on ISLocalToGlobalMapping
13036a818285SBarry Smith 
13046a818285SBarry Smith     Input Parameters:
13056a818285SBarry Smith .   mapping - the mapping from local to global indexing
13066a818285SBarry Smith 
13076a818285SBarry Smith     Output Parameter:
13086a818285SBarry Smith +   nproc - number of processors that are connected to this one
13096a818285SBarry Smith .   proc - neighboring processors
13106a818285SBarry Smith .   numproc - number of indices for each processor
13116a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
13126a818285SBarry Smith 
13136a818285SBarry Smith     Level: advanced
13146a818285SBarry Smith 
13156a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13166a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
13176a818285SBarry Smith @*/
13186a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13196a818285SBarry Smith {
13206a818285SBarry Smith   PetscErrorCode ierr;
13216a818285SBarry Smith 
13226a818285SBarry Smith   PetscFunctionBegin;
1323cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1324268a049cSStefano Zampini   if (mapping->info_free) {
13256a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
13266a818285SBarry Smith     if (*indices) {
1327268a049cSStefano Zampini       PetscInt i;
1328268a049cSStefano Zampini 
13296a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
13306a818285SBarry Smith       for (i=1; i<*nproc; i++) {
13316a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
13326a818285SBarry Smith       }
13336a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
13346a818285SBarry Smith     }
1335268a049cSStefano Zampini   }
1336268a049cSStefano Zampini   *nproc = 0;
1337268a049cSStefano Zampini   *procs = NULL;
1338268a049cSStefano Zampini   *numprocs = NULL;
1339268a049cSStefano Zampini   *indices = NULL;
13406a818285SBarry Smith   PetscFunctionReturn(0);
13416a818285SBarry Smith }
13426a818285SBarry Smith 
13436a818285SBarry Smith #undef __FUNCT__
13446a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
13456a818285SBarry Smith /*@C
13466a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
13476a818285SBarry Smith      each index shared by more than one processor
13486a818285SBarry Smith 
13496a818285SBarry Smith     Collective on ISLocalToGlobalMapping
13506a818285SBarry Smith 
13516a818285SBarry Smith     Input Parameters:
13526a818285SBarry Smith .   mapping - the mapping from local to global indexing
13536a818285SBarry Smith 
13546a818285SBarry Smith     Output Parameter:
13556a818285SBarry Smith +   nproc - number of processors that are connected to this one
13566a818285SBarry Smith .   proc - neighboring processors
13576a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
13586a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
13596a818285SBarry Smith 
13606a818285SBarry Smith     Level: advanced
13616a818285SBarry Smith 
13626a818285SBarry Smith     Concepts: mapping^local to global
13636a818285SBarry Smith 
13646a818285SBarry Smith     Fortran Usage:
13656a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
13666a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
13676a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
13686a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
13696a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
13706a818285SBarry Smith 
13716a818285SBarry Smith 
13726a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
13736a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
13746a818285SBarry Smith @*/
13756a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
13766a818285SBarry Smith {
13776a818285SBarry Smith   PetscErrorCode ierr;
1378268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
13796a818285SBarry Smith 
13806a818285SBarry Smith   PetscFunctionBegin;
13816a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1382268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1383268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1384732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1385268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
13866a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1387268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1388268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
13896a818285SBarry Smith         for (k=0; k<bs; k++) {
13906a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
13916a818285SBarry Smith         }
13926a818285SBarry Smith       }
1393268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
13946a818285SBarry Smith     }
1395268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1396268a049cSStefano Zampini   } else {
1397268a049cSStefano Zampini     *numprocs = bnumprocs;
1398268a049cSStefano Zampini     *indices  = bindices;
13996a818285SBarry Smith   }
14006a818285SBarry Smith   PetscFunctionReturn(0);
14016a818285SBarry Smith }
14026a818285SBarry Smith 
14036a818285SBarry Smith #undef __FUNCT__
14044a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
140507b52d57SBarry Smith /*@C
140607b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
140789d82c54SBarry Smith 
140807b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
140907b52d57SBarry Smith 
141007b52d57SBarry Smith     Input Parameters:
141107b52d57SBarry Smith .   mapping - the mapping from local to global indexing
141207b52d57SBarry Smith 
141307b52d57SBarry Smith     Output Parameter:
141407b52d57SBarry Smith +   nproc - number of processors that are connected to this one
141507b52d57SBarry Smith .   proc - neighboring processors
141607b52d57SBarry Smith .   numproc - number of indices for each processor
141707b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
141807b52d57SBarry Smith 
141907b52d57SBarry Smith     Level: advanced
142007b52d57SBarry Smith 
142107b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
142207b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
142307b52d57SBarry Smith @*/
14247087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
142507b52d57SBarry Smith {
14266849ba73SBarry Smith   PetscErrorCode ierr;
142707b52d57SBarry Smith 
142807b52d57SBarry Smith   PetscFunctionBegin;
14296a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
143007b52d57SBarry Smith   PetscFunctionReturn(0);
143107b52d57SBarry Smith }
143286994e45SJed Brown 
143386994e45SJed Brown #undef __FUNCT__
143486994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
143586994e45SJed Brown /*@C
1436107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
143786994e45SJed Brown 
143886994e45SJed Brown    Not Collective
143986994e45SJed Brown 
144086994e45SJed Brown    Input Arguments:
144186994e45SJed Brown . ltog - local to global mapping
144286994e45SJed Brown 
144386994e45SJed Brown    Output Arguments:
1444565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
144586994e45SJed Brown 
144686994e45SJed Brown    Level: advanced
144786994e45SJed Brown 
1448107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1449107e9a97SBarry Smith 
1450107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
145186994e45SJed Brown @*/
14527087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
145386994e45SJed Brown {
145486994e45SJed Brown   PetscFunctionBegin;
145586994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
145686994e45SJed Brown   PetscValidPointer(array,2);
145745b6f7e9SBarry Smith   if (ltog->bs == 1) {
145886994e45SJed Brown     *array = ltog->indices;
145945b6f7e9SBarry Smith   } else {
146045b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
146145b6f7e9SBarry Smith     const PetscInt *ii;
146245b6f7e9SBarry Smith     PetscErrorCode ierr;
146345b6f7e9SBarry Smith 
146445b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
146545b6f7e9SBarry Smith     *array = jj;
146645b6f7e9SBarry Smith     k    = 0;
146745b6f7e9SBarry Smith     ii   = ltog->indices;
146845b6f7e9SBarry Smith     for (i=0; i<n; i++)
146945b6f7e9SBarry Smith       for (j=0; j<bs; j++)
147045b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
147145b6f7e9SBarry Smith   }
147286994e45SJed Brown   PetscFunctionReturn(0);
147386994e45SJed Brown }
147486994e45SJed Brown 
147586994e45SJed Brown #undef __FUNCT__
147686994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
147786994e45SJed Brown /*@C
1478193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
147986994e45SJed Brown 
148086994e45SJed Brown    Not Collective
148186994e45SJed Brown 
148286994e45SJed Brown    Input Arguments:
148386994e45SJed Brown + ltog - local to global mapping
148486994e45SJed Brown - array - array of indices
148586994e45SJed Brown 
148686994e45SJed Brown    Level: advanced
148786994e45SJed Brown 
148886994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
148986994e45SJed Brown @*/
14907087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
149186994e45SJed Brown {
149286994e45SJed Brown   PetscFunctionBegin;
149386994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
149486994e45SJed Brown   PetscValidPointer(array,2);
149545b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
149645b6f7e9SBarry Smith 
149745b6f7e9SBarry Smith   if (ltog->bs > 1) {
149845b6f7e9SBarry Smith     PetscErrorCode ierr;
149945b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
150045b6f7e9SBarry Smith   }
150145b6f7e9SBarry Smith   PetscFunctionReturn(0);
150245b6f7e9SBarry Smith }
150345b6f7e9SBarry Smith 
150445b6f7e9SBarry Smith #undef __FUNCT__
150545b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
150645b6f7e9SBarry Smith /*@C
150745b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
150845b6f7e9SBarry Smith 
150945b6f7e9SBarry Smith    Not Collective
151045b6f7e9SBarry Smith 
151145b6f7e9SBarry Smith    Input Arguments:
151245b6f7e9SBarry Smith . ltog - local to global mapping
151345b6f7e9SBarry Smith 
151445b6f7e9SBarry Smith    Output Arguments:
151545b6f7e9SBarry Smith . array - array of indices
151645b6f7e9SBarry Smith 
151745b6f7e9SBarry Smith    Level: advanced
151845b6f7e9SBarry Smith 
151945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
152045b6f7e9SBarry Smith @*/
152145b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
152245b6f7e9SBarry Smith {
152345b6f7e9SBarry Smith   PetscFunctionBegin;
152445b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
152545b6f7e9SBarry Smith   PetscValidPointer(array,2);
152645b6f7e9SBarry Smith   *array = ltog->indices;
152745b6f7e9SBarry Smith   PetscFunctionReturn(0);
152845b6f7e9SBarry Smith }
152945b6f7e9SBarry Smith 
153045b6f7e9SBarry Smith #undef __FUNCT__
153145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
153245b6f7e9SBarry Smith /*@C
153345b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
153445b6f7e9SBarry Smith 
153545b6f7e9SBarry Smith    Not Collective
153645b6f7e9SBarry Smith 
153745b6f7e9SBarry Smith    Input Arguments:
153845b6f7e9SBarry Smith + ltog - local to global mapping
153945b6f7e9SBarry Smith - array - array of indices
154045b6f7e9SBarry Smith 
154145b6f7e9SBarry Smith    Level: advanced
154245b6f7e9SBarry Smith 
154345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
154445b6f7e9SBarry Smith @*/
154545b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
154645b6f7e9SBarry Smith {
154745b6f7e9SBarry Smith   PetscFunctionBegin;
154845b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
154945b6f7e9SBarry Smith   PetscValidPointer(array,2);
155086994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
15510298fd71SBarry Smith   *array = NULL;
155286994e45SJed Brown   PetscFunctionReturn(0);
155386994e45SJed Brown }
1554f7efa3c7SJed Brown 
1555f7efa3c7SJed Brown #undef __FUNCT__
1556f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1557f7efa3c7SJed Brown /*@C
1558f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1559f7efa3c7SJed Brown 
1560f7efa3c7SJed Brown    Not Collective
1561f7efa3c7SJed Brown 
1562f7efa3c7SJed Brown    Input Arguments:
1563f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1564f7efa3c7SJed Brown . n - number of mappings to concatenate
1565f7efa3c7SJed Brown - ltogs - local to global mappings
1566f7efa3c7SJed Brown 
1567f7efa3c7SJed Brown    Output Arguments:
1568f7efa3c7SJed Brown . ltogcat - new mapping
1569f7efa3c7SJed Brown 
15709d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
15719d90f715SBarry Smith 
15729d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
15739d90f715SBarry Smith 
1574f7efa3c7SJed Brown    Level: advanced
1575f7efa3c7SJed Brown 
1576f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1577f7efa3c7SJed Brown @*/
1578f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1579f7efa3c7SJed Brown {
1580f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1581f7efa3c7SJed Brown   PetscErrorCode ierr;
1582f7efa3c7SJed Brown 
1583f7efa3c7SJed Brown   PetscFunctionBegin;
1584f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1585f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1586f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1587f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1588f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1589f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1590f7efa3c7SJed Brown     cnt += m;
1591f7efa3c7SJed Brown   }
1592785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1593f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1594f7efa3c7SJed Brown     const PetscInt *subidx;
1595f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1596f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1597f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1598f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1599f7efa3c7SJed Brown     cnt += m;
1600f7efa3c7SJed Brown   }
1601f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1602f7efa3c7SJed Brown   PetscFunctionReturn(0);
1603f7efa3c7SJed Brown }
160404a59952SBarry Smith 
160504a59952SBarry Smith 
1606