xref: /petsc/src/vec/is/utils/isltog.c (revision 193a2b413d3db3a90b41c3bb94c1df14707428c0)
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__
104a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize"
11565245c5SBarry Smith /*@
12107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
133b9aefa3SBarry Smith 
143b9aefa3SBarry Smith     Not Collective
153b9aefa3SBarry Smith 
163b9aefa3SBarry Smith     Input Parameter:
173b9aefa3SBarry Smith .   ltog - local to global mapping
183b9aefa3SBarry Smith 
193b9aefa3SBarry Smith     Output Parameter:
20107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
213b9aefa3SBarry Smith 
223b9aefa3SBarry Smith     Level: advanced
233b9aefa3SBarry Smith 
24273d9f13SBarry Smith     Concepts: mapping^local to global
253b9aefa3SBarry Smith 
263b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
273b9aefa3SBarry Smith @*/
287087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
293b9aefa3SBarry Smith {
303b9aefa3SBarry Smith   PetscFunctionBegin;
310700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
324482741eSBarry Smith   PetscValidIntPointer(n,2);
33107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
343b9aefa3SBarry Smith   PetscFunctionReturn(0);
353b9aefa3SBarry Smith }
363b9aefa3SBarry Smith 
374a2ae208SSatish Balay #undef __FUNCT__
384a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView"
395a5d4f66SBarry Smith /*@C
405a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
415a5d4f66SBarry Smith 
42b9cd556bSLois Curfman McInnes     Not Collective
43b9cd556bSLois Curfman McInnes 
445a5d4f66SBarry Smith     Input Parameters:
453b9aefa3SBarry Smith +   ltog - local to global mapping
463b9aefa3SBarry Smith -   viewer - viewer
475a5d4f66SBarry Smith 
48a997ad1aSLois Curfman McInnes     Level: advanced
49a997ad1aSLois Curfman McInnes 
50273d9f13SBarry Smith     Concepts: mapping^local to global
515a5d4f66SBarry Smith 
525a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
535a5d4f66SBarry Smith @*/
547087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
555a5d4f66SBarry Smith {
5632dcc486SBarry Smith   PetscInt       i;
5732dcc486SBarry Smith   PetscMPIInt    rank;
58ace3abfcSBarry Smith   PetscBool      iascii;
596849ba73SBarry Smith   PetscErrorCode ierr;
605a5d4f66SBarry Smith 
615a5d4f66SBarry Smith   PetscFunctionBegin;
620700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
633050cee2SBarry Smith   if (!viewer) {
64ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
653050cee2SBarry Smith   }
660700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
675a5d4f66SBarry Smith 
68ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
69251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
7032077d6dSBarry Smith   if (iascii) {
7198c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
721575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
735a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
747904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
756831982aSBarry Smith     }
76b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
771575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
781575c14dSBarry Smith   }
795a5d4f66SBarry Smith   PetscFunctionReturn(0);
805a5d4f66SBarry Smith }
815a5d4f66SBarry Smith 
824a2ae208SSatish Balay #undef __FUNCT__
834a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS"
841f428162SBarry Smith /*@
852bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
862bdab257SBarry Smith     ordering and a global parallel ordering.
872bdab257SBarry Smith 
880f5bd95cSBarry Smith     Not collective
89b9cd556bSLois Curfman McInnes 
90a997ad1aSLois Curfman McInnes     Input Parameter:
918c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
922bdab257SBarry Smith 
93a997ad1aSLois Curfman McInnes     Output Parameter:
942bdab257SBarry Smith .   mapping - new mapping data structure
952bdab257SBarry Smith 
96f0413b6fSBarry Smith     Notes: the block size of the IS determines the block size of the mapping
97a997ad1aSLois Curfman McInnes     Level: advanced
98a997ad1aSLois Curfman McInnes 
99273d9f13SBarry Smith     Concepts: mapping^local to global
1002bdab257SBarry Smith 
1012bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
1022bdab257SBarry Smith @*/
1037087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
1042bdab257SBarry Smith {
1056849ba73SBarry Smith   PetscErrorCode ierr;
1063bbf0e92SBarry Smith   PetscInt       n,bs;
1075d0c19d7SBarry Smith   const PetscInt *indices;
1082bdab257SBarry Smith   MPI_Comm       comm;
1093bbf0e92SBarry Smith   PetscBool      isblock;
1103a40ed3dSBarry Smith 
1113a40ed3dSBarry Smith   PetscFunctionBegin;
1120700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
1134482741eSBarry Smith   PetscValidPointer(mapping,2);
1142bdab257SBarry Smith 
1152bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
1163b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1173bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
1186006e8d2SBarry Smith   if (!isblock) {
119f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
120f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
1212bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
1226006e8d2SBarry Smith   } else {
1236006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
124f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
12528bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
126f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
1276006e8d2SBarry Smith   }
1283a40ed3dSBarry Smith   PetscFunctionReturn(0);
1292bdab257SBarry Smith }
1305a5d4f66SBarry Smith 
131a4d96a55SJed Brown #undef __FUNCT__
132a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF"
133a4d96a55SJed Brown /*@C
134a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
135a4d96a55SJed Brown     ordering and a global parallel ordering.
136a4d96a55SJed Brown 
137a4d96a55SJed Brown     Collective
138a4d96a55SJed Brown 
139a4d96a55SJed Brown     Input Parameter:
140a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
141a4d96a55SJed Brown -   start - first global index on this process
142a4d96a55SJed Brown 
143a4d96a55SJed Brown     Output Parameter:
144a4d96a55SJed Brown .   mapping - new mapping data structure
145a4d96a55SJed Brown 
146a4d96a55SJed Brown     Level: advanced
147a4d96a55SJed Brown 
148a4d96a55SJed Brown     Concepts: mapping^local to global
149a4d96a55SJed Brown 
150a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS()
151a4d96a55SJed Brown @*/
152a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
153a4d96a55SJed Brown {
154a4d96a55SJed Brown   PetscErrorCode ierr;
155a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
156a4d96a55SJed Brown   const PetscInt *ilocal;
157a4d96a55SJed Brown   MPI_Comm       comm;
158a4d96a55SJed Brown 
159a4d96a55SJed Brown   PetscFunctionBegin;
160a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
161a4d96a55SJed Brown   PetscValidPointer(mapping,3);
162a4d96a55SJed Brown 
163a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
1640298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
165f6e5521dSKarl Rupp   if (ilocal) {
166f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
167f6e5521dSKarl Rupp   }
168a4d96a55SJed Brown   else maxlocal = nleaves;
169785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
170785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
171a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
172a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
173a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
174a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
175f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
176a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
177a4d96a55SJed Brown   PetscFunctionReturn(0);
178a4d96a55SJed Brown }
179b46b645bSBarry Smith 
1804a2ae208SSatish Balay #undef __FUNCT__
18145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize"
18245b6f7e9SBarry Smith /*@
18345b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
18445b6f7e9SBarry Smith     ordering and a global parallel ordering.
18545b6f7e9SBarry Smith 
18645b6f7e9SBarry Smith     Not Collective
18745b6f7e9SBarry Smith 
18845b6f7e9SBarry Smith     Input Parameters:
18945b6f7e9SBarry Smith .   mapping - mapping data structure
19045b6f7e9SBarry Smith 
19145b6f7e9SBarry Smith     Output Parameter:
19245b6f7e9SBarry Smith .   bs - the blocksize
19345b6f7e9SBarry Smith 
19445b6f7e9SBarry Smith     Level: advanced
19545b6f7e9SBarry Smith 
19645b6f7e9SBarry Smith     Concepts: mapping^local to global
19745b6f7e9SBarry Smith 
19845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
19945b6f7e9SBarry Smith @*/
20045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
20145b6f7e9SBarry Smith {
20245b6f7e9SBarry Smith   PetscFunctionBegin;
203cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
20445b6f7e9SBarry Smith   *bs = mapping->bs;
20545b6f7e9SBarry Smith   PetscFunctionReturn(0);
20645b6f7e9SBarry Smith }
20745b6f7e9SBarry Smith 
20845b6f7e9SBarry Smith #undef __FUNCT__
2094a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate"
210ba5bb76aSSatish Balay /*@
21190f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
21290f02eecSBarry Smith     ordering and a global parallel ordering.
2132362add9SBarry Smith 
21489d82c54SBarry Smith     Not Collective, but communicator may have more than one process
215b9cd556bSLois Curfman McInnes 
2162362add9SBarry Smith     Input Parameters:
21789d82c54SBarry Smith +   comm - MPI communicator
218f0413b6fSBarry Smith .   bs - the block size
21928bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
22028bc9809SBarry 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
221d5ad8652SBarry Smith -   mode - see PetscCopyMode
2222362add9SBarry Smith 
223a997ad1aSLois Curfman McInnes     Output Parameter:
22490f02eecSBarry Smith .   mapping - new mapping data structure
2252362add9SBarry Smith 
226f0413b6fSBarry 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
227a997ad1aSLois Curfman McInnes     Level: advanced
228a997ad1aSLois Curfman McInnes 
229273d9f13SBarry Smith     Concepts: mapping^local to global
2302362add9SBarry Smith 
231d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
2322362add9SBarry Smith @*/
23360c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
2342362add9SBarry Smith {
2356849ba73SBarry Smith   PetscErrorCode ierr;
23632dcc486SBarry Smith   PetscInt       *in;
237b46b645bSBarry Smith 
238b46b645bSBarry Smith   PetscFunctionBegin;
23973911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
2404482741eSBarry Smith   PetscValidPointer(mapping,4);
241b46b645bSBarry Smith 
2420298fd71SBarry Smith   *mapping = NULL;
243607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
2442362add9SBarry Smith 
24573107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
24660c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
247d4bb536fSBarry Smith   (*mapping)->n             = n;
248f0413b6fSBarry Smith   (*mapping)->bs            = bs;
249268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
250268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
251268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
252268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
253268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
254d4bb536fSBarry Smith   /*
255d4bb536fSBarry Smith     Do not create the global to local mapping. This is only created if
256d4bb536fSBarry Smith     ISGlobalToLocalMapping() is called
257d4bb536fSBarry Smith   */
258d4bb536fSBarry Smith   (*mapping)->globals = 0;
259d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
260785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
261d5ad8652SBarry Smith     ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr);
262d5ad8652SBarry Smith     (*mapping)->indices = in;
2636389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2646389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
2656389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
2666389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
2676389a1a1SBarry Smith   }
26860c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
269d96308ebSBarry Smith   ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr);
2703a40ed3dSBarry Smith   PetscFunctionReturn(0);
2712362add9SBarry Smith }
2722362add9SBarry Smith 
2734a2ae208SSatish Balay #undef __FUNCT__
2744a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy"
27590f02eecSBarry Smith /*@
27690f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
27790f02eecSBarry Smith    ordering and a global parallel ordering.
27890f02eecSBarry Smith 
2790f5bd95cSBarry Smith    Note Collective
280b9cd556bSLois Curfman McInnes 
28190f02eecSBarry Smith    Input Parameters:
28290f02eecSBarry Smith .  mapping - mapping data structure
28390f02eecSBarry Smith 
284a997ad1aSLois Curfman McInnes    Level: advanced
285a997ad1aSLois Curfman McInnes 
2863acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
28790f02eecSBarry Smith @*/
2886bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
28990f02eecSBarry Smith {
290dfbe8321SBarry Smith   PetscErrorCode ierr;
2915fd66863SKarl Rupp 
2923a40ed3dSBarry Smith   PetscFunctionBegin;
2936bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
2946bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
295997056adSBarry Smith   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);}
2966bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
2976bf464f9SBarry Smith   ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr);
298268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
299268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
300268a049cSStefano Zampini   if ((*mapping)->info_indices) {
301268a049cSStefano Zampini     PetscInt i;
302268a049cSStefano Zampini 
303268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
304268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
305268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
306268a049cSStefano Zampini     }
307268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
308268a049cSStefano Zampini   }
309d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
310992144d0SBarry Smith   *mapping = 0;
3113a40ed3dSBarry Smith   PetscFunctionReturn(0);
31290f02eecSBarry Smith }
31390f02eecSBarry Smith 
3144a2ae208SSatish Balay #undef __FUNCT__
3154a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS"
31690f02eecSBarry Smith /*@
3173acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
3183acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
3193acfe500SLois Curfman McInnes     context.
32090f02eecSBarry Smith 
321b9cd556bSLois Curfman McInnes     Not collective
322b9cd556bSLois Curfman McInnes 
32390f02eecSBarry Smith     Input Parameters:
324b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
325b9cd556bSLois Curfman McInnes -   is - index set in local numbering
32690f02eecSBarry Smith 
32790f02eecSBarry Smith     Output Parameters:
32890f02eecSBarry Smith .   newis - index set in global numbering
32990f02eecSBarry Smith 
330a997ad1aSLois Curfman McInnes     Level: advanced
331a997ad1aSLois Curfman McInnes 
332273d9f13SBarry Smith     Concepts: mapping^local to global
3333acfe500SLois Curfman McInnes 
33490f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
335d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
33690f02eecSBarry Smith @*/
3377087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
33890f02eecSBarry Smith {
3396849ba73SBarry Smith   PetscErrorCode ierr;
340e24637baSBarry Smith   PetscInt       n,*idxout;
3415d0c19d7SBarry Smith   const PetscInt *idxin;
3423a40ed3dSBarry Smith 
3433a40ed3dSBarry Smith   PetscFunctionBegin;
3440700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3450700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
3464482741eSBarry Smith   PetscValidPointer(newis,3);
34790f02eecSBarry Smith 
3483b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
34990f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
350785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
351e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
3523b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
353543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
3543a40ed3dSBarry Smith   PetscFunctionReturn(0);
35590f02eecSBarry Smith }
35690f02eecSBarry Smith 
357afcb2eb5SJed Brown #undef __FUNCT__
358afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply"
359b89cb25eSSatish Balay /*@
3603acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
3613acfe500SLois Curfman McInnes    and converts them to the global numbering.
36290f02eecSBarry Smith 
363b9cd556bSLois Curfman McInnes    Not collective
364b9cd556bSLois Curfman McInnes 
365bb25748dSBarry Smith    Input Parameters:
366b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
367bb25748dSBarry Smith .  N - number of integers
368b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
369bb25748dSBarry Smith 
370bb25748dSBarry Smith    Output Parameter:
371bb25748dSBarry Smith .  out - indices in global numbering
372bb25748dSBarry Smith 
373b9cd556bSLois Curfman McInnes    Notes:
374b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
375d4bb536fSBarry Smith 
376a997ad1aSLois Curfman McInnes    Level: advanced
377a997ad1aSLois Curfman McInnes 
37845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
3790752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
380d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
381bb25748dSBarry Smith 
382273d9f13SBarry Smith     Concepts: mapping^local to global
383afcb2eb5SJed Brown @*/
384afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
385afcb2eb5SJed Brown {
386cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
38745b6f7e9SBarry Smith 
38845b6f7e9SBarry Smith   PetscFunctionBegin;
389cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
390cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
391cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
39245b6f7e9SBarry Smith   if (bs == 1) {
393cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
39445b6f7e9SBarry Smith     for (i=0; i<N; i++) {
39545b6f7e9SBarry Smith       if (in[i] < 0) {
39645b6f7e9SBarry Smith         out[i] = in[i];
39745b6f7e9SBarry Smith         continue;
39845b6f7e9SBarry Smith       }
399e24637baSBarry 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);
40045b6f7e9SBarry Smith       out[i] = idx[in[i]];
40145b6f7e9SBarry Smith     }
40245b6f7e9SBarry Smith   } else {
403cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
40445b6f7e9SBarry Smith     for (i=0; i<N; i++) {
40545b6f7e9SBarry Smith       if (in[i] < 0) {
40645b6f7e9SBarry Smith         out[i] = in[i];
40745b6f7e9SBarry Smith         continue;
40845b6f7e9SBarry Smith       }
409e24637baSBarry 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);
41045b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
41145b6f7e9SBarry Smith     }
41245b6f7e9SBarry Smith   }
41345b6f7e9SBarry Smith   PetscFunctionReturn(0);
41445b6f7e9SBarry Smith }
41545b6f7e9SBarry Smith 
41645b6f7e9SBarry Smith #undef __FUNCT__
41745b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock"
41845b6f7e9SBarry Smith /*@
4196006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering  and converts them to the global block numbering
42045b6f7e9SBarry Smith 
42145b6f7e9SBarry Smith    Not collective
42245b6f7e9SBarry Smith 
42345b6f7e9SBarry Smith    Input Parameters:
42445b6f7e9SBarry Smith +  mapping - the local to global mapping context
42545b6f7e9SBarry Smith .  N - number of integers
4266006e8d2SBarry Smith -  in - input indices in local block numbering
42745b6f7e9SBarry Smith 
42845b6f7e9SBarry Smith    Output Parameter:
4296006e8d2SBarry Smith .  out - indices in global block numbering
43045b6f7e9SBarry Smith 
43145b6f7e9SBarry Smith    Notes:
43245b6f7e9SBarry Smith    The in and out array parameters may be identical.
43345b6f7e9SBarry Smith 
4346006e8d2SBarry Smith    Example:
4356006e8d2SBarry 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
4366006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
4376006e8d2SBarry Smith 
43845b6f7e9SBarry Smith    Level: advanced
43945b6f7e9SBarry Smith 
44045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
44145b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
44245b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
44345b6f7e9SBarry Smith 
44445b6f7e9SBarry Smith     Concepts: mapping^local to global
44545b6f7e9SBarry Smith @*/
44645b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
44745b6f7e9SBarry Smith {
448cbc1caf0SMatthew G. Knepley 
449cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
450cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
451cbc1caf0SMatthew G. Knepley   {
452afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
453afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
454d4bb536fSBarry Smith 
455afcb2eb5SJed Brown     for (i=0; i<N; i++) {
456afcb2eb5SJed Brown       if (in[i] < 0) {
457afcb2eb5SJed Brown         out[i] = in[i];
458afcb2eb5SJed Brown         continue;
459afcb2eb5SJed Brown       }
460e24637baSBarry 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);
461afcb2eb5SJed Brown       out[i] = idx[in[i]];
462afcb2eb5SJed Brown     }
463cbc1caf0SMatthew G. Knepley   }
464afcb2eb5SJed Brown   PetscFunctionReturn(0);
465afcb2eb5SJed Brown }
466d4bb536fSBarry Smith 
467d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
468d4bb536fSBarry Smith 
4694a2ae208SSatish Balay #undef __FUNCT__
4704a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private"
471d4bb536fSBarry Smith /*
472d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
473d4bb536fSBarry Smith */
4746849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
475d4bb536fSBarry Smith {
4766849ba73SBarry Smith   PetscErrorCode ierr;
47732dcc486SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
478d4bb536fSBarry Smith 
4793a40ed3dSBarry Smith   PetscFunctionBegin;
480d4bb536fSBarry Smith   end   = 0;
481ec268f7cSJed Brown   start = PETSC_MAX_INT;
482d4bb536fSBarry Smith 
483d4bb536fSBarry Smith   for (i=0; i<n; i++) {
484d4bb536fSBarry Smith     if (idx[i] < 0) continue;
485d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
486d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
487d4bb536fSBarry Smith   }
488d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
489d4bb536fSBarry Smith   mapping->globalstart = start;
490d4bb536fSBarry Smith   mapping->globalend   = end;
491d4bb536fSBarry Smith 
492854ce69bSBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
493b0a32e0cSBarry Smith   mapping->globals = globals;
494f6e5521dSKarl Rupp   for (i=0; i<end-start+1; i++) globals[i] = -1;
495d4bb536fSBarry Smith   for (i=0; i<n; i++) {
496d4bb536fSBarry Smith     if (idx[i] < 0) continue;
497d4bb536fSBarry Smith     globals[idx[i] - start] = i;
498d4bb536fSBarry Smith   }
499d4bb536fSBarry Smith 
5003bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
5013a40ed3dSBarry Smith   PetscFunctionReturn(0);
502d4bb536fSBarry Smith }
503d4bb536fSBarry Smith 
5044a2ae208SSatish Balay #undef __FUNCT__
5054a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply"
506d4bb536fSBarry Smith /*@
507a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
508a997ad1aSLois Curfman McInnes     specified with a global numbering.
509d4bb536fSBarry Smith 
510b9cd556bSLois Curfman McInnes     Not collective
511b9cd556bSLois Curfman McInnes 
512d4bb536fSBarry Smith     Input Parameters:
513b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
514d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
515d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
516d4bb536fSBarry Smith .   n - number of global indices to map
517b9cd556bSLois Curfman McInnes -   idx - global indices to map
518d4bb536fSBarry Smith 
519d4bb536fSBarry Smith     Output Parameters:
520b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
521b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
522e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
5230298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
524e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
525e182c471SBarry Smith              a second time to set the values.
526d4bb536fSBarry Smith 
527b9cd556bSLois Curfman McInnes     Notes:
5280298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
529d4bb536fSBarry Smith 
5300f5bd95cSBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
5310f5bd95cSBarry Smith     array to compute these.
5320f5bd95cSBarry Smith 
533a997ad1aSLois Curfman McInnes     Level: advanced
534a997ad1aSLois Curfman McInnes 
53532fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
53632fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
53732fd6b96SBarry Smith 
538273d9f13SBarry Smith     Concepts: mapping^global to local
539d4bb536fSBarry Smith 
5409d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
541d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
542d4bb536fSBarry Smith @*/
5437087cfbeSBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
54432dcc486SBarry Smith                                             PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
545d4bb536fSBarry Smith {
5469d90f715SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end,bs;
5479d90f715SBarry Smith   PetscErrorCode ierr;
5489d90f715SBarry Smith 
5499d90f715SBarry Smith   PetscFunctionBegin;
5509d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
5519d90f715SBarry Smith   if (!mapping->globals) {
5529d90f715SBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
5539d90f715SBarry Smith   }
5549d90f715SBarry Smith   globals = mapping->globals;
5559d90f715SBarry Smith   start   = mapping->globalstart;
5569d90f715SBarry Smith   end     = mapping->globalend;
5579d90f715SBarry Smith   bs      = mapping->bs;
5589d90f715SBarry Smith 
5599d90f715SBarry Smith   if (type == IS_GTOLM_MASK) {
5609d90f715SBarry Smith     if (idxout) {
5619d90f715SBarry Smith       for (i=0; i<n; i++) {
5629d90f715SBarry Smith         if (idx[i] < 0)                   idxout[i] = idx[i];
5639d90f715SBarry Smith         else if (idx[i] < bs*start)       idxout[i] = -1;
564663bb84eSBarry Smith         else if (idx[i] > bs*(end+1)-1)   idxout[i] = -1;
5659d90f715SBarry Smith         else                              idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5669d90f715SBarry Smith       }
5679d90f715SBarry Smith     }
5689d90f715SBarry Smith     if (nout) *nout = n;
5699d90f715SBarry Smith   } else {
5709d90f715SBarry Smith     if (idxout) {
5719d90f715SBarry Smith       for (i=0; i<n; i++) {
5729d90f715SBarry Smith         if (idx[i] < 0) continue;
5739d90f715SBarry Smith         if (idx[i] < bs*start) continue;
574663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
5759d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5769d90f715SBarry Smith         if (tmp < 0) continue;
5779d90f715SBarry Smith         idxout[nf++] = tmp;
5789d90f715SBarry Smith       }
5799d90f715SBarry Smith     } else {
5809d90f715SBarry Smith       for (i=0; i<n; i++) {
5819d90f715SBarry Smith         if (idx[i] < 0) continue;
5829d90f715SBarry Smith         if (idx[i] < bs*start) continue;
583663bb84eSBarry Smith         if (idx[i] > bs*(end+1)-1) continue;
5849d90f715SBarry Smith         tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs);
5859d90f715SBarry Smith         if (tmp < 0) continue;
5869d90f715SBarry Smith         nf++;
5879d90f715SBarry Smith       }
5889d90f715SBarry Smith     }
5899d90f715SBarry Smith     if (nout) *nout = nf;
5909d90f715SBarry Smith   }
5919d90f715SBarry Smith   PetscFunctionReturn(0);
5929d90f715SBarry Smith }
5939d90f715SBarry Smith 
5949d90f715SBarry Smith #undef __FUNCT__
595d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS"
596d4fe737eSStefano Zampini /*@
597d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
598d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
599d4fe737eSStefano Zampini     context.
600d4fe737eSStefano Zampini 
601d4fe737eSStefano Zampini     Not collective
602d4fe737eSStefano Zampini 
603d4fe737eSStefano Zampini     Input Parameters:
604d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
605d4fe737eSStefano Zampini -   is - index set in global numbering
606d4fe737eSStefano Zampini 
607d4fe737eSStefano Zampini     Output Parameters:
608d4fe737eSStefano Zampini .   newis - index set in local numbering
609d4fe737eSStefano Zampini 
610d4fe737eSStefano Zampini     Level: advanced
611d4fe737eSStefano Zampini 
612d4fe737eSStefano Zampini     Concepts: mapping^local to global
613d4fe737eSStefano Zampini 
614d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
615d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
616d4fe737eSStefano Zampini @*/
617d4fe737eSStefano Zampini PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis)
618d4fe737eSStefano Zampini {
619d4fe737eSStefano Zampini   PetscErrorCode ierr;
620d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
621d4fe737eSStefano Zampini   const PetscInt *idxin;
622d4fe737eSStefano Zampini 
623d4fe737eSStefano Zampini   PetscFunctionBegin;
624d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
625d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
626d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
627d4fe737eSStefano Zampini 
628d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
629d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
630d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
631d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
632d4fe737eSStefano Zampini   } else {
633d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
634d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
635d4fe737eSStefano Zampini   }
636d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
637d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
638d4fe737eSStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
639d4fe737eSStefano Zampini   PetscFunctionReturn(0);
640d4fe737eSStefano Zampini }
641d4fe737eSStefano Zampini 
642d4fe737eSStefano Zampini #undef __FUNCT__
6439d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock"
6449d90f715SBarry Smith /*@
6459d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
6469d90f715SBarry Smith     specified with a block global numbering.
6479d90f715SBarry Smith 
6489d90f715SBarry Smith     Not collective
6499d90f715SBarry Smith 
6509d90f715SBarry Smith     Input Parameters:
6519d90f715SBarry Smith +   mapping - mapping between local and global numbering
6529d90f715SBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
6539d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
6549d90f715SBarry Smith .   n - number of global indices to map
6559d90f715SBarry Smith -   idx - global indices to map
6569d90f715SBarry Smith 
6579d90f715SBarry Smith     Output Parameters:
6589d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
6599d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
6609d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
6619d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
6629d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
6639d90f715SBarry Smith              a second time to set the values.
6649d90f715SBarry Smith 
6659d90f715SBarry Smith     Notes:
6669d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
6679d90f715SBarry Smith 
6689d90f715SBarry Smith     This is not scalable in memory usage. Each processor requires O(Nglobal) size
6699d90f715SBarry Smith     array to compute these.
6709d90f715SBarry Smith 
6719d90f715SBarry Smith     Level: advanced
6729d90f715SBarry Smith 
6739d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
6749d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
6759d90f715SBarry Smith 
6769d90f715SBarry Smith     Concepts: mapping^global to local
6779d90f715SBarry Smith 
6789d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
6799d90f715SBarry Smith           ISLocalToGlobalMappingDestroy()
6809d90f715SBarry Smith @*/
6819d90f715SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type,
6829d90f715SBarry Smith                                   PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
6839d90f715SBarry Smith {
68432dcc486SBarry Smith   PetscInt       i,*globals,nf = 0,tmp,start,end;
6856849ba73SBarry Smith   PetscErrorCode ierr;
686d4bb536fSBarry Smith 
6873a40ed3dSBarry Smith   PetscFunctionBegin;
6880700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
689d4bb536fSBarry Smith   if (!mapping->globals) {
690d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
691d4bb536fSBarry Smith   }
692d4bb536fSBarry Smith   globals = mapping->globals;
693d4bb536fSBarry Smith   start   = mapping->globalstart;
694d4bb536fSBarry Smith   end     = mapping->globalend;
695d4bb536fSBarry Smith 
696d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
697d4bb536fSBarry Smith     if (idxout) {
698d4bb536fSBarry Smith       for (i=0; i<n; i++) {
699d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
700d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
701d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
702d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
703d4bb536fSBarry Smith       }
704d4bb536fSBarry Smith     }
705d4bb536fSBarry Smith     if (nout) *nout = n;
706d4bb536fSBarry Smith   } else {
707d4bb536fSBarry Smith     if (idxout) {
708d4bb536fSBarry Smith       for (i=0; i<n; i++) {
709d4bb536fSBarry Smith         if (idx[i] < 0) continue;
710d4bb536fSBarry Smith         if (idx[i] < start) continue;
711d4bb536fSBarry Smith         if (idx[i] > end) continue;
712d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
713d4bb536fSBarry Smith         if (tmp < 0) continue;
714d4bb536fSBarry Smith         idxout[nf++] = tmp;
715d4bb536fSBarry Smith       }
716d4bb536fSBarry Smith     } else {
717d4bb536fSBarry Smith       for (i=0; i<n; i++) {
718d4bb536fSBarry Smith         if (idx[i] < 0) continue;
719d4bb536fSBarry Smith         if (idx[i] < start) continue;
720d4bb536fSBarry Smith         if (idx[i] > end) continue;
721d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
722d4bb536fSBarry Smith         if (tmp < 0) continue;
723d4bb536fSBarry Smith         nf++;
724d4bb536fSBarry Smith       }
725d4bb536fSBarry Smith     }
726d4bb536fSBarry Smith     if (nout) *nout = nf;
727d4bb536fSBarry Smith   }
7283a40ed3dSBarry Smith   PetscFunctionReturn(0);
729d4bb536fSBarry Smith }
73090f02eecSBarry Smith 
7314a2ae208SSatish Balay #undef __FUNCT__
7326a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo"
73389d82c54SBarry Smith /*@C
7346a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
73589d82c54SBarry Smith      each index shared by more than one processor
73689d82c54SBarry Smith 
73789d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
73889d82c54SBarry Smith 
73989d82c54SBarry Smith     Input Parameters:
74089d82c54SBarry Smith .   mapping - the mapping from local to global indexing
74189d82c54SBarry Smith 
74289d82c54SBarry Smith     Output Parameter:
74389d82c54SBarry Smith +   nproc - number of processors that are connected to this one
74489d82c54SBarry Smith .   proc - neighboring processors
74507b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
7463463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
74789d82c54SBarry Smith 
74889d82c54SBarry Smith     Level: advanced
74989d82c54SBarry Smith 
750273d9f13SBarry Smith     Concepts: mapping^local to global
75189d82c54SBarry Smith 
7522cfcea29SBarry Smith     Fortran Usage:
7532cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
7542cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
7552cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
7562cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
7572cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
7582cfcea29SBarry Smith 
7592cfcea29SBarry Smith 
76007b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
76107b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
76289d82c54SBarry Smith @*/
7636a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
76489d82c54SBarry Smith {
7656849ba73SBarry Smith   PetscErrorCode ierr;
766268a049cSStefano Zampini 
767268a049cSStefano Zampini   PetscFunctionBegin;
768268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
769268a049cSStefano Zampini   if (mapping->info_cached) {
770268a049cSStefano Zampini     *nproc = mapping->info_nproc;
771268a049cSStefano Zampini     *procs = mapping->info_procs;
772268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
773268a049cSStefano Zampini     *indices = mapping->info_indices;
774268a049cSStefano Zampini   } else {
775268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
776268a049cSStefano Zampini   }
777268a049cSStefano Zampini   PetscFunctionReturn(0);
778268a049cSStefano Zampini }
779268a049cSStefano Zampini 
780268a049cSStefano Zampini #undef __FUNCT__
781268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private"
782268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
783268a049cSStefano Zampini {
784268a049cSStefano Zampini   PetscErrorCode ierr;
78597f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
78632dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
78732dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
78897f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
78932dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
79032dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
79189d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
79230dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
793ce94432eSBarry Smith   MPI_Comm       comm;
794ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
79589d82c54SBarry Smith 
79689d82c54SBarry Smith   PetscFunctionBegin;
797ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
79824cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
79924cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
80024cf384cSBarry Smith   if (size == 1) {
80124cf384cSBarry Smith     *nproc         = 0;
8020298fd71SBarry Smith     *procs         = NULL;
80395dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
8041e2105dcSBarry Smith     (*numprocs)[0] = 0;
80595dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
8060298fd71SBarry Smith     (*indices)[0]  = NULL;
807268a049cSStefano Zampini     /* save info for reuse */
808268a049cSStefano Zampini     mapping->info_nproc = *nproc;
809268a049cSStefano Zampini     mapping->info_procs = *procs;
810268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
811268a049cSStefano Zampini     mapping->info_indices = *indices;
812268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
81324cf384cSBarry Smith     PetscFunctionReturn(0);
81424cf384cSBarry Smith   }
81524cf384cSBarry Smith 
816c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
81707b52d57SBarry Smith 
8183677ff5aSBarry Smith   /*
8196a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
8203677ff5aSBarry Smith 
8213677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
8223677ff5aSBarry Smith            numbering, just for this routine.
8233677ff5aSBarry Smith 
8243677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
8253677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
8263677ff5aSBarry Smith 
8273677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
8283677ff5aSBarry Smith 
8293677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
8303677ff5aSBarry Smith            local subdomain
8313677ff5aSBarry Smith   */
83224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
83324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
83424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
83589d82c54SBarry Smith 
83689d82c54SBarry Smith   for (i=0; i<n; i++) {
83789d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
83889d82c54SBarry Smith   }
839b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
84078058e43SBarry Smith   Ng++;
84189d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
84289d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
843bc8ff85bSBarry Smith   scale  = Ng/size + 1;
844a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
845caba0dd0SBarry Smith   rstart = scale*rank;
84689d82c54SBarry Smith 
84789d82c54SBarry Smith   /* determine ownership ranges of global indices */
848785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
84932dcc486SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
85089d82c54SBarry Smith 
85189d82c54SBarry Smith   /* determine owners of each local node  */
852785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
85389d82c54SBarry Smith   for (i=0; i<n; i++) {
8543677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
85527c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
8563677ff5aSBarry Smith     owner[i]         = proc;
85727c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
85889d82c54SBarry Smith   }
85927c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
8607904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
86189d82c54SBarry Smith 
86289d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
86327c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
8647904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
86589d82c54SBarry Smith 
86689d82c54SBarry Smith   /* post receives for owned rows */
867785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
868854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
86989d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
87032dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
87189d82c54SBarry Smith   }
87289d82c54SBarry Smith 
87389d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
874854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
875854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
87689d82c54SBarry Smith   starts[0] = 0;
877f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
87889d82c54SBarry Smith   for (i=0; i<n; i++) {
87989d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
88030dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
88189d82c54SBarry Smith   }
88289d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
88389d82c54SBarry Smith   starts[0] = 0;
884f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
88589d82c54SBarry Smith 
88689d82c54SBarry Smith   /* send the messages */
887854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
888854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
88989d82c54SBarry Smith   cnt = 0;
89089d82c54SBarry Smith   for (i=0; i<size; i++) {
89127c402fcSBarry Smith     if (nprocs[2*i]) {
89232dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
89330dcb7c9SBarry Smith       dest[cnt] = i;
89489d82c54SBarry Smith       cnt++;
89589d82c54SBarry Smith     }
89689d82c54SBarry Smith   }
89789d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
89889d82c54SBarry Smith 
89989d82c54SBarry Smith   /* wait on receives */
900854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
901854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
90289d82c54SBarry Smith   cnt  = nrecvs;
903854ce69bSBarry Smith   ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
90432dcc486SBarry Smith   ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr);
90589d82c54SBarry Smith   while (cnt) {
90689d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
90789d82c54SBarry Smith     /* unpack receives into our local space */
90832dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
90989d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
91030dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
911caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
91230dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
91389d82c54SBarry Smith     cnt--;
91489d82c54SBarry Smith   }
91589d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
91689d82c54SBarry Smith 
91730dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
918bc8ff85bSBarry Smith   nowned  = 0;
919bc8ff85bSBarry Smith   nownedm = 0;
920bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
921bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
922bc8ff85bSBarry Smith   }
923bc8ff85bSBarry Smith 
924bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
925854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
926854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
927bc8ff85bSBarry Smith   starts[0] = 0;
928bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
929bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
930bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
931bc8ff85bSBarry Smith   }
932bc8ff85bSBarry Smith 
93330dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
934bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
935bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
93630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
937f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
938bc8ff85bSBarry Smith     }
939bc8ff85bSBarry Smith   }
940bc8ff85bSBarry Smith 
94107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
94230dcb7c9SBarry Smith     starts[0] = 0;
94330dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
94430dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
94530dcb7c9SBarry Smith       else starts[i] = starts[i-1];
94630dcb7c9SBarry Smith     }
94730dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
94830dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
9497904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
95030dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
9517904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
95230dcb7c9SBarry Smith         }
95330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
95430dcb7c9SBarry Smith       }
95530dcb7c9SBarry Smith     }
9560ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
95707b52d57SBarry Smith   } /* -----------------------------------  */
95830dcb7c9SBarry Smith 
9593677ff5aSBarry Smith   /* wait on original sends */
9603a96401aSBarry Smith   if (nsends) {
961785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
9623a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
9633a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
9643a96401aSBarry Smith   }
96589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
9663a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
9673677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
9683677ff5aSBarry Smith 
9693677ff5aSBarry Smith   /* pack messages to send back to local owners */
97030dcb7c9SBarry Smith   starts[0] = 0;
97130dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
97230dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
97330dcb7c9SBarry Smith     else starts[i] = starts[i-1];
97430dcb7c9SBarry Smith   }
97530dcb7c9SBarry Smith   nsends2 = nrecvs;
976854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
97730dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
97830dcb7c9SBarry Smith     nprocs[i] = 1;
97930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
98030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
981f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
98230dcb7c9SBarry Smith     }
98330dcb7c9SBarry Smith   }
984f6e5521dSKarl Rupp   nt = 0;
985f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
986f6e5521dSKarl Rupp 
987854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
988854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
989f6e5521dSKarl Rupp 
990f6e5521dSKarl Rupp   starts2[0] = 0;
991f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
99230dcb7c9SBarry Smith   /*
99330dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
99430dcb7c9SBarry Smith        (0) the number of nodes being sent back
99530dcb7c9SBarry Smith        (1) the local node number,
99630dcb7c9SBarry Smith        (2) the number of processors sharing it,
99730dcb7c9SBarry Smith        (3) the processors sharing it
99830dcb7c9SBarry Smith   */
99930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
100030dcb7c9SBarry Smith     cnt = 1;
100130dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
100230dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
100330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
100430dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
100530dcb7c9SBarry Smith         sends2[starts2[i]]++;
100630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
100730dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
100832dcc486SBarry Smith         ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr);
100930dcb7c9SBarry Smith         cnt += nownedsenders[node];
101030dcb7c9SBarry Smith       }
101130dcb7c9SBarry Smith     }
101230dcb7c9SBarry Smith   }
101330dcb7c9SBarry Smith 
101430dcb7c9SBarry Smith   /* receive the message lengths */
101530dcb7c9SBarry Smith   nrecvs2 = nsends;
1016854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1017854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1018854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
101930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1020d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
102130dcb7c9SBarry Smith   }
1022d44834fbSBarry Smith 
10238a8e0b3aSBarry Smith   /* send the message lengths */
10248a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
10258a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
10268a8e0b3aSBarry Smith   }
10278a8e0b3aSBarry Smith 
1028d44834fbSBarry Smith   /* wait on receives of lens */
10290c468ba9SBarry Smith   if (nrecvs2) {
1030785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1031d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1032d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10330c468ba9SBarry Smith   }
1034a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1035d44834fbSBarry Smith 
103630dcb7c9SBarry Smith   starts3[0] = 0;
1037d44834fbSBarry Smith   nt         = 0;
103830dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
103930dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1040d44834fbSBarry Smith     nt          += lens2[i];
104130dcb7c9SBarry Smith   }
104276466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1043d44834fbSBarry Smith 
1044854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1045854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
104652b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
104732dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
104830dcb7c9SBarry Smith   }
104930dcb7c9SBarry Smith 
105030dcb7c9SBarry Smith   /* send the messages */
1051854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
105230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
105332dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
105430dcb7c9SBarry Smith   }
105530dcb7c9SBarry Smith 
105630dcb7c9SBarry Smith   /* wait on receives */
10570c468ba9SBarry Smith   if (nrecvs2) {
1058785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
105930dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
106030dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
10610c468ba9SBarry Smith   }
106230dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
106330dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
106430dcb7c9SBarry Smith 
106507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
106630dcb7c9SBarry Smith     cnt = 0;
106730dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
106830dcb7c9SBarry Smith       nt = recvs2[cnt++];
106930dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
10707904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
107130dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
10727904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
107330dcb7c9SBarry Smith         }
107430dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
107530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
107630dcb7c9SBarry Smith       }
107730dcb7c9SBarry Smith     }
10780ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
107907b52d57SBarry Smith   } /* -----------------------------------  */
108030dcb7c9SBarry Smith 
108130dcb7c9SBarry Smith   /* count number subdomains for each local node */
1082785e854fSJed Brown   ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr);
108332dcc486SBarry Smith   ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr);
108430dcb7c9SBarry Smith   cnt  = 0;
108530dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
108630dcb7c9SBarry Smith     nt = recvs2[cnt++];
108730dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1088f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
108930dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
109030dcb7c9SBarry Smith     }
109130dcb7c9SBarry Smith   }
109230dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
109330dcb7c9SBarry Smith   *nproc    = nt;
1094854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1095854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1096854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
10970298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1098785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
109930dcb7c9SBarry Smith   cnt  = 0;
110030dcb7c9SBarry Smith   for (i=0; i<size; i++) {
110130dcb7c9SBarry Smith     if (nprocs[i] > 0) {
110230dcb7c9SBarry Smith       bprocs[i]        = cnt;
110330dcb7c9SBarry Smith       (*procs)[cnt]    = i;
110430dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1105785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
110630dcb7c9SBarry Smith       cnt++;
110730dcb7c9SBarry Smith     }
110830dcb7c9SBarry Smith   }
110930dcb7c9SBarry Smith 
111030dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
111132dcc486SBarry Smith   ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr);
111230dcb7c9SBarry Smith   cnt  = 0;
111330dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
111430dcb7c9SBarry Smith     nt = recvs2[cnt++];
111530dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1116f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
111730dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
111830dcb7c9SBarry Smith     }
111930dcb7c9SBarry Smith   }
112030dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
112107b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
112230dcb7c9SBarry Smith 
112307b52d57SBarry Smith   /* sort the node indexing by their global numbers */
112407b52d57SBarry Smith   nt = *nproc;
112507b52d57SBarry Smith   for (i=0; i<nt; i++) {
1126854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1127f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
112807b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
112907b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
113007b52d57SBarry Smith   }
113107b52d57SBarry Smith 
113207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
113330dcb7c9SBarry Smith     nt = *nproc;
113430dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
11357904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
113630dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
11377904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
113830dcb7c9SBarry Smith       }
113930dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
114030dcb7c9SBarry Smith     }
11410ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
114207b52d57SBarry Smith   } /* -----------------------------------  */
114330dcb7c9SBarry Smith 
114430dcb7c9SBarry Smith   /* wait on sends */
114530dcb7c9SBarry Smith   if (nsends2) {
1146785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
114730dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
114830dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
114930dcb7c9SBarry Smith   }
115030dcb7c9SBarry Smith 
115130dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
115230dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
115330dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
11543677ff5aSBarry Smith 
1155bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1156bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1157bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
115830dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
115930dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
116089d82c54SBarry Smith 
116189d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
116297f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
116389d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
11643a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
116530dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
116624cf384cSBarry Smith 
116724cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
116824cf384cSBarry Smith   first_procs    = (*procs)[0];
116924cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
117024cf384cSBarry Smith   first_indices  = (*indices)[0];
117124cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
117224cf384cSBarry Smith     if ((*procs)[i] == rank) {
117324cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
117424cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
117524cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
117624cf384cSBarry Smith       (*procs)[i]    = first_procs;
117724cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
117824cf384cSBarry Smith       (*indices)[i]  = first_indices;
117924cf384cSBarry Smith       break;
118024cf384cSBarry Smith     }
118124cf384cSBarry Smith   }
1182268a049cSStefano Zampini 
1183268a049cSStefano Zampini   /* save info for reuse */
1184268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1185268a049cSStefano Zampini   mapping->info_procs = *procs;
1186268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1187268a049cSStefano Zampini   mapping->info_indices = *indices;
1188268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
118989d82c54SBarry Smith   PetscFunctionReturn(0);
119089d82c54SBarry Smith }
119189d82c54SBarry Smith 
11924a2ae208SSatish Balay #undef __FUNCT__
11936a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo"
11946a818285SBarry Smith /*@C
11956a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
11966a818285SBarry Smith 
11976a818285SBarry Smith     Collective on ISLocalToGlobalMapping
11986a818285SBarry Smith 
11996a818285SBarry Smith     Input Parameters:
12006a818285SBarry Smith .   mapping - the mapping from local to global indexing
12016a818285SBarry Smith 
12026a818285SBarry Smith     Output Parameter:
12036a818285SBarry Smith +   nproc - number of processors that are connected to this one
12046a818285SBarry Smith .   proc - neighboring processors
12056a818285SBarry Smith .   numproc - number of indices for each processor
12066a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
12076a818285SBarry Smith 
12086a818285SBarry Smith     Level: advanced
12096a818285SBarry Smith 
12106a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12116a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
12126a818285SBarry Smith @*/
12136a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12146a818285SBarry Smith {
12156a818285SBarry Smith   PetscErrorCode ierr;
12166a818285SBarry Smith 
12176a818285SBarry Smith   PetscFunctionBegin;
1218cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1219268a049cSStefano Zampini   if (mapping->info_free) {
12206a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
12216a818285SBarry Smith     if (*indices) {
1222268a049cSStefano Zampini       PetscInt i;
1223268a049cSStefano Zampini 
12246a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
12256a818285SBarry Smith       for (i=1; i<*nproc; i++) {
12266a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
12276a818285SBarry Smith       }
12286a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
12296a818285SBarry Smith     }
1230268a049cSStefano Zampini   }
1231268a049cSStefano Zampini   *nproc = 0;
1232268a049cSStefano Zampini   *procs = NULL;
1233268a049cSStefano Zampini   *numprocs = NULL;
1234268a049cSStefano Zampini   *indices = NULL;
12356a818285SBarry Smith   PetscFunctionReturn(0);
12366a818285SBarry Smith }
12376a818285SBarry Smith 
12386a818285SBarry Smith #undef __FUNCT__
12396a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo"
12406a818285SBarry Smith /*@C
12416a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
12426a818285SBarry Smith      each index shared by more than one processor
12436a818285SBarry Smith 
12446a818285SBarry Smith     Collective on ISLocalToGlobalMapping
12456a818285SBarry Smith 
12466a818285SBarry Smith     Input Parameters:
12476a818285SBarry Smith .   mapping - the mapping from local to global indexing
12486a818285SBarry Smith 
12496a818285SBarry Smith     Output Parameter:
12506a818285SBarry Smith +   nproc - number of processors that are connected to this one
12516a818285SBarry Smith .   proc - neighboring processors
12526a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
12536a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
12546a818285SBarry Smith 
12556a818285SBarry Smith     Level: advanced
12566a818285SBarry Smith 
12576a818285SBarry Smith     Concepts: mapping^local to global
12586a818285SBarry Smith 
12596a818285SBarry Smith     Fortran Usage:
12606a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
12616a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
12626a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
12636a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
12646a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
12656a818285SBarry Smith 
12666a818285SBarry Smith 
12676a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
12686a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
12696a818285SBarry Smith @*/
12706a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
12716a818285SBarry Smith {
12726a818285SBarry Smith   PetscErrorCode ierr;
1273268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
12746a818285SBarry Smith 
12756a818285SBarry Smith   PetscFunctionBegin;
12766a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1277268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1278268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1279732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1280268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
12816a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1282268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1283268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
12846a818285SBarry Smith         for (k=0; k<bs; k++) {
12856a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
12866a818285SBarry Smith         }
12876a818285SBarry Smith       }
1288268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
12896a818285SBarry Smith     }
1290268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1291268a049cSStefano Zampini   } else {
1292268a049cSStefano Zampini     *numprocs = bnumprocs;
1293268a049cSStefano Zampini     *indices  = bindices;
12946a818285SBarry Smith   }
12956a818285SBarry Smith   PetscFunctionReturn(0);
12966a818285SBarry Smith }
12976a818285SBarry Smith 
12986a818285SBarry Smith #undef __FUNCT__
12994a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo"
130007b52d57SBarry Smith /*@C
130107b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
130289d82c54SBarry Smith 
130307b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
130407b52d57SBarry Smith 
130507b52d57SBarry Smith     Input Parameters:
130607b52d57SBarry Smith .   mapping - the mapping from local to global indexing
130707b52d57SBarry Smith 
130807b52d57SBarry Smith     Output Parameter:
130907b52d57SBarry Smith +   nproc - number of processors that are connected to this one
131007b52d57SBarry Smith .   proc - neighboring processors
131107b52d57SBarry Smith .   numproc - number of indices for each processor
131207b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
131307b52d57SBarry Smith 
131407b52d57SBarry Smith     Level: advanced
131507b52d57SBarry Smith 
131607b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
131707b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
131807b52d57SBarry Smith @*/
13197087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
132007b52d57SBarry Smith {
13216849ba73SBarry Smith   PetscErrorCode ierr;
132207b52d57SBarry Smith 
132307b52d57SBarry Smith   PetscFunctionBegin;
13246a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
132507b52d57SBarry Smith   PetscFunctionReturn(0);
132607b52d57SBarry Smith }
132786994e45SJed Brown 
132886994e45SJed Brown #undef __FUNCT__
132986994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices"
133086994e45SJed Brown /*@C
1331107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
133286994e45SJed Brown 
133386994e45SJed Brown    Not Collective
133486994e45SJed Brown 
133586994e45SJed Brown    Input Arguments:
133686994e45SJed Brown . ltog - local to global mapping
133786994e45SJed Brown 
133886994e45SJed Brown    Output Arguments:
1339565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
134086994e45SJed Brown 
134186994e45SJed Brown    Level: advanced
134286994e45SJed Brown 
1343107e9a97SBarry Smith    Notes: ISLocalToGlobalMappingGetSize() returns the length the this array
1344107e9a97SBarry Smith 
1345107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
134686994e45SJed Brown @*/
13477087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
134886994e45SJed Brown {
134986994e45SJed Brown   PetscFunctionBegin;
135086994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
135186994e45SJed Brown   PetscValidPointer(array,2);
135245b6f7e9SBarry Smith   if (ltog->bs == 1) {
135386994e45SJed Brown     *array = ltog->indices;
135445b6f7e9SBarry Smith   } else {
135545b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
135645b6f7e9SBarry Smith     const PetscInt *ii;
135745b6f7e9SBarry Smith     PetscErrorCode ierr;
135845b6f7e9SBarry Smith 
135945b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
136045b6f7e9SBarry Smith     *array = jj;
136145b6f7e9SBarry Smith     k    = 0;
136245b6f7e9SBarry Smith     ii   = ltog->indices;
136345b6f7e9SBarry Smith     for (i=0; i<n; i++)
136445b6f7e9SBarry Smith       for (j=0; j<bs; j++)
136545b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
136645b6f7e9SBarry Smith   }
136786994e45SJed Brown   PetscFunctionReturn(0);
136886994e45SJed Brown }
136986994e45SJed Brown 
137086994e45SJed Brown #undef __FUNCT__
137186994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices"
137286994e45SJed Brown /*@C
1373*193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
137486994e45SJed Brown 
137586994e45SJed Brown    Not Collective
137686994e45SJed Brown 
137786994e45SJed Brown    Input Arguments:
137886994e45SJed Brown + ltog - local to global mapping
137986994e45SJed Brown - array - array of indices
138086994e45SJed Brown 
138186994e45SJed Brown    Level: advanced
138286994e45SJed Brown 
138386994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
138486994e45SJed Brown @*/
13857087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
138686994e45SJed Brown {
138786994e45SJed Brown   PetscFunctionBegin;
138886994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
138986994e45SJed Brown   PetscValidPointer(array,2);
139045b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
139145b6f7e9SBarry Smith 
139245b6f7e9SBarry Smith   if (ltog->bs > 1) {
139345b6f7e9SBarry Smith     PetscErrorCode ierr;
139445b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
139545b6f7e9SBarry Smith   }
139645b6f7e9SBarry Smith   PetscFunctionReturn(0);
139745b6f7e9SBarry Smith }
139845b6f7e9SBarry Smith 
139945b6f7e9SBarry Smith #undef __FUNCT__
140045b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices"
140145b6f7e9SBarry Smith /*@C
140245b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
140345b6f7e9SBarry Smith 
140445b6f7e9SBarry Smith    Not Collective
140545b6f7e9SBarry Smith 
140645b6f7e9SBarry Smith    Input Arguments:
140745b6f7e9SBarry Smith . ltog - local to global mapping
140845b6f7e9SBarry Smith 
140945b6f7e9SBarry Smith    Output Arguments:
141045b6f7e9SBarry Smith . array - array of indices
141145b6f7e9SBarry Smith 
141245b6f7e9SBarry Smith    Level: advanced
141345b6f7e9SBarry Smith 
141445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
141545b6f7e9SBarry Smith @*/
141645b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
141745b6f7e9SBarry Smith {
141845b6f7e9SBarry Smith   PetscFunctionBegin;
141945b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
142045b6f7e9SBarry Smith   PetscValidPointer(array,2);
142145b6f7e9SBarry Smith   *array = ltog->indices;
142245b6f7e9SBarry Smith   PetscFunctionReturn(0);
142345b6f7e9SBarry Smith }
142445b6f7e9SBarry Smith 
142545b6f7e9SBarry Smith #undef __FUNCT__
142645b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices"
142745b6f7e9SBarry Smith /*@C
142845b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
142945b6f7e9SBarry Smith 
143045b6f7e9SBarry Smith    Not Collective
143145b6f7e9SBarry Smith 
143245b6f7e9SBarry Smith    Input Arguments:
143345b6f7e9SBarry Smith + ltog - local to global mapping
143445b6f7e9SBarry Smith - array - array of indices
143545b6f7e9SBarry Smith 
143645b6f7e9SBarry Smith    Level: advanced
143745b6f7e9SBarry Smith 
143845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
143945b6f7e9SBarry Smith @*/
144045b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
144145b6f7e9SBarry Smith {
144245b6f7e9SBarry Smith   PetscFunctionBegin;
144345b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
144445b6f7e9SBarry Smith   PetscValidPointer(array,2);
144586994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
14460298fd71SBarry Smith   *array = NULL;
144786994e45SJed Brown   PetscFunctionReturn(0);
144886994e45SJed Brown }
1449f7efa3c7SJed Brown 
1450f7efa3c7SJed Brown #undef __FUNCT__
1451f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate"
1452f7efa3c7SJed Brown /*@C
1453f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1454f7efa3c7SJed Brown 
1455f7efa3c7SJed Brown    Not Collective
1456f7efa3c7SJed Brown 
1457f7efa3c7SJed Brown    Input Arguments:
1458f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1459f7efa3c7SJed Brown . n - number of mappings to concatenate
1460f7efa3c7SJed Brown - ltogs - local to global mappings
1461f7efa3c7SJed Brown 
1462f7efa3c7SJed Brown    Output Arguments:
1463f7efa3c7SJed Brown . ltogcat - new mapping
1464f7efa3c7SJed Brown 
14659d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
14669d90f715SBarry Smith 
14679d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
14689d90f715SBarry Smith 
1469f7efa3c7SJed Brown    Level: advanced
1470f7efa3c7SJed Brown 
1471f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1472f7efa3c7SJed Brown @*/
1473f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1474f7efa3c7SJed Brown {
1475f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1476f7efa3c7SJed Brown   PetscErrorCode ierr;
1477f7efa3c7SJed Brown 
1478f7efa3c7SJed Brown   PetscFunctionBegin;
1479f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1480f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1481f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1482f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1483f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1484f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1485f7efa3c7SJed Brown     cnt += m;
1486f7efa3c7SJed Brown   }
1487785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1488f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1489f7efa3c7SJed Brown     const PetscInt *subidx;
1490f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1491f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1492f7efa3c7SJed Brown     ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr);
1493f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1494f7efa3c7SJed Brown     cnt += m;
1495f7efa3c7SJed Brown   }
1496f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1497f7efa3c7SJed Brown   PetscFunctionReturn(0);
1498f7efa3c7SJed Brown }
149904a59952SBarry Smith 
150004a59952SBarry Smith 
1501