xref: /petsc/src/vec/is/utils/isltog.c (revision 4c8fdceaee2187f6ed586d920f30b56dbb227b33)
12362add9SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>    /*I "petscis.h"  I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashmapi.h>
40c312b8eSJed Brown #include <petscsf.h>
5665c2dedSJed Brown #include <petscviewer.h>
62362add9SBarry Smith 
77087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID;
8268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***);
98e58c17dSMatthew Knepley 
10413f72f0SBarry Smith typedef struct {
11413f72f0SBarry Smith   PetscInt *globals;
12413f72f0SBarry Smith } ISLocalToGlobalMapping_Basic;
13413f72f0SBarry Smith 
14413f72f0SBarry Smith typedef struct {
15e8f14785SLisandro Dalcin   PetscHMapI globalht;
16413f72f0SBarry Smith } ISLocalToGlobalMapping_Hash;
17413f72f0SBarry Smith 
18413f72f0SBarry Smith 
199305a4c7SMatthew G. Knepley PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
209305a4c7SMatthew G. Knepley {
219305a4c7SMatthew G. Knepley   PetscInt       numCells, step = 1;
229305a4c7SMatthew G. Knepley   PetscBool      isStride;
239305a4c7SMatthew G. Knepley   PetscErrorCode ierr;
249305a4c7SMatthew G. Knepley 
259305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
269305a4c7SMatthew G. Knepley   *pStart = 0;
279305a4c7SMatthew G. Knepley   *points = NULL;
289305a4c7SMatthew G. Knepley   ierr = ISGetLocalSize(pointIS, &numCells);CHKERRQ(ierr);
299305a4c7SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr);
309305a4c7SMatthew G. Knepley   if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);}
319305a4c7SMatthew G. Knepley   *pEnd   = *pStart + numCells;
329305a4c7SMatthew G. Knepley   if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);}
339305a4c7SMatthew G. Knepley   PetscFunctionReturn(0);
349305a4c7SMatthew G. Knepley }
359305a4c7SMatthew G. Knepley 
369305a4c7SMatthew G. Knepley PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
379305a4c7SMatthew G. Knepley {
389305a4c7SMatthew G. Knepley   PetscInt       step = 1;
399305a4c7SMatthew G. Knepley   PetscBool      isStride;
409305a4c7SMatthew G. Knepley   PetscErrorCode ierr;
419305a4c7SMatthew G. Knepley 
429305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
439305a4c7SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr);
449305a4c7SMatthew G. Knepley   if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);}
459305a4c7SMatthew G. Knepley   if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);}
469305a4c7SMatthew G. Knepley   PetscFunctionReturn(0);
479305a4c7SMatthew G. Knepley }
489305a4c7SMatthew G. Knepley 
499305a4c7SMatthew G. Knepley PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points)
509305a4c7SMatthew G. Knepley {
519305a4c7SMatthew G. Knepley   PetscErrorCode ierr;
529305a4c7SMatthew G. Knepley 
539305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
549305a4c7SMatthew G. Knepley   if (points) {
559305a4c7SMatthew G. Knepley     ierr = ISSetType(subpointIS, ISGENERAL);CHKERRQ(ierr);
569305a4c7SMatthew G. Knepley     ierr = ISGeneralSetIndices(subpointIS, pEnd-pStart, &points[pStart], PETSC_USE_POINTER);CHKERRQ(ierr);
579305a4c7SMatthew G. Knepley   } else {
589305a4c7SMatthew G. Knepley     ierr = ISSetType(subpointIS, ISSTRIDE);CHKERRQ(ierr);
599305a4c7SMatthew G. Knepley     ierr = ISStrideSetStride(subpointIS, pEnd-pStart, pStart, 1);CHKERRQ(ierr);
609305a4c7SMatthew G. Knepley   }
619305a4c7SMatthew G. Knepley   PetscFunctionReturn(0);
629305a4c7SMatthew G. Knepley }
639305a4c7SMatthew G. Knepley 
64413f72f0SBarry Smith /* -----------------------------------------------------------------------------------------*/
65413f72f0SBarry Smith 
66413f72f0SBarry Smith /*
67413f72f0SBarry Smith     Creates the global mapping information in the ISLocalToGlobalMapping structure
68413f72f0SBarry Smith 
69413f72f0SBarry Smith     If the user has not selected how to handle the global to local mapping then use HASH for "large" problems
70413f72f0SBarry Smith */
71413f72f0SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping)
72413f72f0SBarry Smith {
73413f72f0SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start;
74413f72f0SBarry Smith   PetscErrorCode ierr;
75413f72f0SBarry Smith 
76413f72f0SBarry Smith   PetscFunctionBegin;
77413f72f0SBarry Smith   if (mapping->data) PetscFunctionReturn(0);
78413f72f0SBarry Smith   end   = 0;
79413f72f0SBarry Smith   start = PETSC_MAX_INT;
80413f72f0SBarry Smith 
81413f72f0SBarry Smith   for (i=0; i<n; i++) {
82413f72f0SBarry Smith     if (idx[i] < 0) continue;
83413f72f0SBarry Smith     if (idx[i] < start) start = idx[i];
84413f72f0SBarry Smith     if (idx[i] > end)   end   = idx[i];
85413f72f0SBarry Smith   }
86413f72f0SBarry Smith   if (start > end) {start = 0; end = -1;}
87413f72f0SBarry Smith   mapping->globalstart = start;
88413f72f0SBarry Smith   mapping->globalend   = end;
89413f72f0SBarry Smith   if (!((PetscObject)mapping)->type_name) {
90413f72f0SBarry Smith     if ((end - start) > PetscMax(4*n,1000000)) {
917f79407eSBarry Smith       ierr = ISLocalToGlobalMappingSetType(mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
92413f72f0SBarry Smith     } else {
937f79407eSBarry Smith       ierr = ISLocalToGlobalMappingSetType(mapping,ISLOCALTOGLOBALMAPPINGBASIC);CHKERRQ(ierr);
94413f72f0SBarry Smith     }
95413f72f0SBarry Smith   }
96413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingsetup)(mapping);CHKERRQ(ierr);
97413f72f0SBarry Smith   PetscFunctionReturn(0);
98413f72f0SBarry Smith }
99413f72f0SBarry Smith 
100413f72f0SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping)
101413f72f0SBarry Smith {
102413f72f0SBarry Smith   PetscErrorCode              ierr;
103413f72f0SBarry Smith   PetscInt                    i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
104413f72f0SBarry Smith   ISLocalToGlobalMapping_Basic *map;
105413f72f0SBarry Smith 
106413f72f0SBarry Smith   PetscFunctionBegin;
107413f72f0SBarry Smith   start            = mapping->globalstart;
108413f72f0SBarry Smith   end              = mapping->globalend;
109413f72f0SBarry Smith   ierr             = PetscNew(&map);CHKERRQ(ierr);
110413f72f0SBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
111413f72f0SBarry Smith   map->globals     = globals;
112413f72f0SBarry Smith   for (i=0; i<end-start+1; i++) globals[i] = -1;
113413f72f0SBarry Smith   for (i=0; i<n; i++) {
114413f72f0SBarry Smith     if (idx[i] < 0) continue;
115413f72f0SBarry Smith     globals[idx[i] - start] = i;
116413f72f0SBarry Smith   }
117413f72f0SBarry Smith   mapping->data = (void*)map;
118413f72f0SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
119413f72f0SBarry Smith   PetscFunctionReturn(0);
120413f72f0SBarry Smith }
121413f72f0SBarry Smith 
122413f72f0SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping)
123413f72f0SBarry Smith {
124413f72f0SBarry Smith   PetscErrorCode              ierr;
125413f72f0SBarry Smith   PetscInt                    i,*idx = mapping->indices,n = mapping->n;
126413f72f0SBarry Smith   ISLocalToGlobalMapping_Hash *map;
127413f72f0SBarry Smith 
128413f72f0SBarry Smith   PetscFunctionBegin;
129413f72f0SBarry Smith   ierr = PetscNew(&map);CHKERRQ(ierr);
130e8f14785SLisandro Dalcin   ierr = PetscHMapICreate(&map->globalht);CHKERRQ(ierr);
131413f72f0SBarry Smith   for (i=0; i<n; i++ ) {
132413f72f0SBarry Smith     if (idx[i] < 0) continue;
133e8f14785SLisandro Dalcin     ierr = PetscHMapISet(map->globalht,idx[i],i);CHKERRQ(ierr);
134413f72f0SBarry Smith   }
135413f72f0SBarry Smith   mapping->data = (void*)map;
136413f72f0SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,2*n*sizeof(PetscInt));CHKERRQ(ierr);
137413f72f0SBarry Smith   PetscFunctionReturn(0);
138413f72f0SBarry Smith }
139413f72f0SBarry Smith 
140413f72f0SBarry Smith static PetscErrorCode ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping)
141413f72f0SBarry Smith {
142413f72f0SBarry Smith   PetscErrorCode              ierr;
143413f72f0SBarry Smith   ISLocalToGlobalMapping_Basic *map  = (ISLocalToGlobalMapping_Basic *)mapping->data;
144413f72f0SBarry Smith 
145413f72f0SBarry Smith   PetscFunctionBegin;
146413f72f0SBarry Smith   if (!map) PetscFunctionReturn(0);
147413f72f0SBarry Smith   ierr = PetscFree(map->globals);CHKERRQ(ierr);
148413f72f0SBarry Smith   ierr = PetscFree(mapping->data);CHKERRQ(ierr);
149413f72f0SBarry Smith   PetscFunctionReturn(0);
150413f72f0SBarry Smith }
151413f72f0SBarry Smith 
152413f72f0SBarry Smith static PetscErrorCode ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping)
153413f72f0SBarry Smith {
154413f72f0SBarry Smith   PetscErrorCode              ierr;
155413f72f0SBarry Smith   ISLocalToGlobalMapping_Hash *map  = (ISLocalToGlobalMapping_Hash*)mapping->data;
156413f72f0SBarry Smith 
157413f72f0SBarry Smith   PetscFunctionBegin;
158413f72f0SBarry Smith   if (!map) PetscFunctionReturn(0);
159e8f14785SLisandro Dalcin   ierr = PetscHMapIDestroy(&map->globalht);CHKERRQ(ierr);
160413f72f0SBarry Smith   ierr = PetscFree(mapping->data);CHKERRQ(ierr);
161413f72f0SBarry Smith   PetscFunctionReturn(0);
162413f72f0SBarry Smith }
163413f72f0SBarry Smith 
164413f72f0SBarry Smith #define GTOLTYPE _Basic
165413f72f0SBarry Smith #define GTOLNAME _Basic
166541bf97eSAdrian Croucher #define GTOLBS mapping->bs
167413f72f0SBarry Smith #define GTOL(g, local) do {                  \
168413f72f0SBarry Smith     local = map->globals[g/bs - start];      \
1690040bde1SJunchao Zhang     if (local >= 0) local = bs*local + (g % bs); \
170413f72f0SBarry Smith   } while (0)
171541bf97eSAdrian Croucher 
172413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
173413f72f0SBarry Smith 
174413f72f0SBarry Smith #define GTOLTYPE _Basic
175413f72f0SBarry Smith #define GTOLNAME Block_Basic
176541bf97eSAdrian Croucher #define GTOLBS 1
177413f72f0SBarry Smith #define GTOL(g, local) do {                  \
178413f72f0SBarry Smith     local = map->globals[g - start];         \
179413f72f0SBarry Smith   } while (0)
180413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
181413f72f0SBarry Smith 
182413f72f0SBarry Smith #define GTOLTYPE _Hash
183413f72f0SBarry Smith #define GTOLNAME _Hash
184541bf97eSAdrian Croucher #define GTOLBS mapping->bs
185413f72f0SBarry Smith #define GTOL(g, local) do {                         \
186e8f14785SLisandro Dalcin     (void)PetscHMapIGet(map->globalht,g/bs,&local); \
1870040bde1SJunchao Zhang     if (local >= 0) local = bs*local + (g % bs);   \
188413f72f0SBarry Smith    } while (0)
189413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
190413f72f0SBarry Smith 
191413f72f0SBarry Smith #define GTOLTYPE _Hash
192413f72f0SBarry Smith #define GTOLNAME Block_Hash
193541bf97eSAdrian Croucher #define GTOLBS 1
194413f72f0SBarry Smith #define GTOL(g, local) do {                         \
195e8f14785SLisandro Dalcin     (void)PetscHMapIGet(map->globalht,g,&local);    \
196413f72f0SBarry Smith   } while (0)
197413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
198413f72f0SBarry Smith 
1996658fb44Sstefano_zampini /*@
2006658fb44Sstefano_zampini     ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
2016658fb44Sstefano_zampini 
2026658fb44Sstefano_zampini     Not Collective
2036658fb44Sstefano_zampini 
2046658fb44Sstefano_zampini     Input Parameter:
2056658fb44Sstefano_zampini .   ltog - local to global mapping
2066658fb44Sstefano_zampini 
2076658fb44Sstefano_zampini     Output Parameter:
2086658fb44Sstefano_zampini .   nltog - the duplicated local to global mapping
2096658fb44Sstefano_zampini 
2106658fb44Sstefano_zampini     Level: advanced
2116658fb44Sstefano_zampini 
2126658fb44Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
2136658fb44Sstefano_zampini @*/
2146658fb44Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping* nltog)
2156658fb44Sstefano_zampini {
2166658fb44Sstefano_zampini   PetscErrorCode ierr;
2176658fb44Sstefano_zampini 
2186658fb44Sstefano_zampini   PetscFunctionBegin;
2196658fb44Sstefano_zampini   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
2206658fb44Sstefano_zampini   ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog),ltog->bs,ltog->n,ltog->indices,PETSC_COPY_VALUES,nltog);CHKERRQ(ierr);
2216658fb44Sstefano_zampini   PetscFunctionReturn(0);
2226658fb44Sstefano_zampini }
2236658fb44Sstefano_zampini 
224565245c5SBarry Smith /*@
225107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
2263b9aefa3SBarry Smith 
2273b9aefa3SBarry Smith     Not Collective
2283b9aefa3SBarry Smith 
2293b9aefa3SBarry Smith     Input Parameter:
2303b9aefa3SBarry Smith .   ltog - local to global mapping
2313b9aefa3SBarry Smith 
2323b9aefa3SBarry Smith     Output Parameter:
233107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
2343b9aefa3SBarry Smith 
2353b9aefa3SBarry Smith     Level: advanced
2363b9aefa3SBarry Smith 
2373b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
2383b9aefa3SBarry Smith @*/
2397087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
2403b9aefa3SBarry Smith {
2413b9aefa3SBarry Smith   PetscFunctionBegin;
2420700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
2434482741eSBarry Smith   PetscValidIntPointer(n,2);
244107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
2453b9aefa3SBarry Smith   PetscFunctionReturn(0);
2463b9aefa3SBarry Smith }
2473b9aefa3SBarry Smith 
2485a5d4f66SBarry Smith /*@C
249fe2efc57SMark    ISLocalToGlobalMappingViewFromOptions - View from Options
250fe2efc57SMark 
251fe2efc57SMark    Collective on ISLocalToGlobalMapping
252fe2efc57SMark 
253fe2efc57SMark    Input Parameters:
254fe2efc57SMark +  A - the local to global mapping object
255736c3998SJose E. Roman .  obj - Optional object
256736c3998SJose E. Roman -  name - command line option
257fe2efc57SMark 
258fe2efc57SMark    Level: intermediate
259fe2efc57SMark .seealso:  ISLocalToGlobalMapping, ISLocalToGlobalMappingView, PetscObjectViewFromOptions(), ISLocalToGlobalMappingCreate()
260fe2efc57SMark @*/
261fe2efc57SMark PetscErrorCode  ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A,PetscObject obj,const char name[])
262fe2efc57SMark {
263fe2efc57SMark   PetscErrorCode ierr;
264fe2efc57SMark 
265fe2efc57SMark   PetscFunctionBegin;
266fe2efc57SMark   PetscValidHeaderSpecific(A,IS_LTOGM_CLASSID,1);
267fe2efc57SMark   ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr);
268fe2efc57SMark   PetscFunctionReturn(0);
269fe2efc57SMark }
270fe2efc57SMark 
271fe2efc57SMark /*@C
2725a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
2735a5d4f66SBarry Smith 
274b9cd556bSLois Curfman McInnes     Not Collective
275b9cd556bSLois Curfman McInnes 
2765a5d4f66SBarry Smith     Input Parameters:
2773b9aefa3SBarry Smith +   ltog - local to global mapping
2783b9aefa3SBarry Smith -   viewer - viewer
2795a5d4f66SBarry Smith 
280a997ad1aSLois Curfman McInnes     Level: advanced
281a997ad1aSLois Curfman McInnes 
2825a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
2835a5d4f66SBarry Smith @*/
2847087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
2855a5d4f66SBarry Smith {
28632dcc486SBarry Smith   PetscInt       i;
28732dcc486SBarry Smith   PetscMPIInt    rank;
288ace3abfcSBarry Smith   PetscBool      iascii;
2896849ba73SBarry Smith   PetscErrorCode ierr;
2905a5d4f66SBarry Smith 
2915a5d4f66SBarry Smith   PetscFunctionBegin;
2920700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
2933050cee2SBarry Smith   if (!viewer) {
294ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
2953050cee2SBarry Smith   }
2960700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2975a5d4f66SBarry Smith 
298ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr);
299251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
30032077d6dSBarry Smith   if (iascii) {
30198c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
3021575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
3035a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
3047904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
3056831982aSBarry Smith     }
306b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3071575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
3081575c14dSBarry Smith   }
3095a5d4f66SBarry Smith   PetscFunctionReturn(0);
3105a5d4f66SBarry Smith }
3115a5d4f66SBarry Smith 
3121f428162SBarry Smith /*@
3132bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
3142bdab257SBarry Smith     ordering and a global parallel ordering.
3152bdab257SBarry Smith 
3160f5bd95cSBarry Smith     Not collective
317b9cd556bSLois Curfman McInnes 
318a997ad1aSLois Curfman McInnes     Input Parameter:
3198c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
3202bdab257SBarry Smith 
321a997ad1aSLois Curfman McInnes     Output Parameter:
3222bdab257SBarry Smith .   mapping - new mapping data structure
3232bdab257SBarry Smith 
32495452b02SPatrick Sanan     Notes:
32595452b02SPatrick Sanan     the block size of the IS determines the block size of the mapping
326a997ad1aSLois Curfman McInnes     Level: advanced
327a997ad1aSLois Curfman McInnes 
3287e99dc12SLawrence Mitchell .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetFromOptions()
3292bdab257SBarry Smith @*/
3307087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
3312bdab257SBarry Smith {
3326849ba73SBarry Smith   PetscErrorCode ierr;
3333bbf0e92SBarry Smith   PetscInt       n,bs;
3345d0c19d7SBarry Smith   const PetscInt *indices;
3352bdab257SBarry Smith   MPI_Comm       comm;
3363bbf0e92SBarry Smith   PetscBool      isblock;
3373a40ed3dSBarry Smith 
3383a40ed3dSBarry Smith   PetscFunctionBegin;
3390700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
3404482741eSBarry Smith   PetscValidPointer(mapping,2);
3412bdab257SBarry Smith 
3422bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
3433b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
3443bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
3456006e8d2SBarry Smith   if (!isblock) {
346f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
347f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
3482bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
3496006e8d2SBarry Smith   } else {
3506006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
351f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
35228bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
353f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
3546006e8d2SBarry Smith   }
3553a40ed3dSBarry Smith   PetscFunctionReturn(0);
3562bdab257SBarry Smith }
3575a5d4f66SBarry Smith 
358a4d96a55SJed Brown /*@C
359a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
360a4d96a55SJed Brown     ordering and a global parallel ordering.
361a4d96a55SJed Brown 
362a4d96a55SJed Brown     Collective
363a4d96a55SJed Brown 
364a4d96a55SJed Brown     Input Parameter:
365a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
366a4d96a55SJed Brown -   start - first global index on this process
367a4d96a55SJed Brown 
368a4d96a55SJed Brown     Output Parameter:
369a4d96a55SJed Brown .   mapping - new mapping data structure
370a4d96a55SJed Brown 
371a4d96a55SJed Brown     Level: advanced
372a4d96a55SJed Brown 
3737e99dc12SLawrence Mitchell .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingSetFromOptions()
374a4d96a55SJed Brown @*/
375a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
376a4d96a55SJed Brown {
377a4d96a55SJed Brown   PetscErrorCode ierr;
378a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
379a4d96a55SJed Brown   const PetscInt *ilocal;
380a4d96a55SJed Brown   MPI_Comm       comm;
381a4d96a55SJed Brown 
382a4d96a55SJed Brown   PetscFunctionBegin;
383a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
384a4d96a55SJed Brown   PetscValidPointer(mapping,3);
385a4d96a55SJed Brown 
386a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
3870298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
388f6e5521dSKarl Rupp   if (ilocal) {
389f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
390f6e5521dSKarl Rupp   }
391a4d96a55SJed Brown   else maxlocal = nleaves;
392785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
393785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
394a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
395a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
396a4d96a55SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
397a4d96a55SJed Brown   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr);
398f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
399a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
400a4d96a55SJed Brown   PetscFunctionReturn(0);
401a4d96a55SJed Brown }
402b46b645bSBarry Smith 
40363fa5c83Sstefano_zampini /*@
40463fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
40563fa5c83Sstefano_zampini 
40663fa5c83Sstefano_zampini     Not collective
40763fa5c83Sstefano_zampini 
40863fa5c83Sstefano_zampini     Input Parameters:
409a2b725a8SWilliam Gropp +   mapping - mapping data structure
410a2b725a8SWilliam Gropp -   bs - the blocksize
41163fa5c83Sstefano_zampini 
41263fa5c83Sstefano_zampini     Level: advanced
41363fa5c83Sstefano_zampini 
41463fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
41563fa5c83Sstefano_zampini @*/
41663fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
41763fa5c83Sstefano_zampini {
418a59f3c4dSstefano_zampini   PetscInt       *nid;
419a59f3c4dSstefano_zampini   const PetscInt *oid;
420a59f3c4dSstefano_zampini   PetscInt       i,cn,on,obs,nn;
42163fa5c83Sstefano_zampini   PetscErrorCode ierr;
42263fa5c83Sstefano_zampini 
42363fa5c83Sstefano_zampini   PetscFunctionBegin;
42463fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
42563fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
42663fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
42763fa5c83Sstefano_zampini   on  = mapping->n;
42863fa5c83Sstefano_zampini   obs = mapping->bs;
42963fa5c83Sstefano_zampini   oid = mapping->indices;
43063fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
43163fa5c83Sstefano_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);
432a59f3c4dSstefano_zampini 
43363fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
434a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingGetIndices(mapping,&oid);CHKERRQ(ierr);
435a59f3c4dSstefano_zampini   for (i=0;i<nn;i++) {
436a59f3c4dSstefano_zampini     PetscInt j;
437a59f3c4dSstefano_zampini     for (j=0,cn=0;j<bs-1;j++) {
438a59f3c4dSstefano_zampini       if (oid[i*bs+j] < 0) { cn++; continue; }
439a59f3c4dSstefano_zampini       if (oid[i*bs+j] != oid[i*bs+j+1]-1) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices %D %D",bs,obs,oid[i*bs+j],oid[i*bs+j+1]);
440a59f3c4dSstefano_zampini     }
441a59f3c4dSstefano_zampini     if (oid[i*bs+j] < 0) cn++;
4428b7cb0e6Sstefano_zampini     if (cn) {
443a59f3c4dSstefano_zampini       if (cn != bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: invalid number of negative entries in block %D",bs,obs,cn);
444a59f3c4dSstefano_zampini       nid[i] = -1;
4458b7cb0e6Sstefano_zampini     } else {
446a59f3c4dSstefano_zampini       nid[i] = oid[i*bs]/bs;
44763fa5c83Sstefano_zampini     }
44863fa5c83Sstefano_zampini   }
449a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(mapping,&oid);CHKERRQ(ierr);
450a59f3c4dSstefano_zampini 
45163fa5c83Sstefano_zampini   mapping->n           = nn;
45263fa5c83Sstefano_zampini   mapping->bs          = bs;
45363fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
45463fa5c83Sstefano_zampini   mapping->indices     = nid;
455c9345713Sstefano_zampini   mapping->globalstart = 0;
456c9345713Sstefano_zampini   mapping->globalend   = 0;
4571bd0b88eSStefano Zampini 
4581bd0b88eSStefano Zampini   /* reset the cached information */
4591bd0b88eSStefano Zampini   ierr = PetscFree(mapping->info_procs);CHKERRQ(ierr);
4601bd0b88eSStefano Zampini   ierr = PetscFree(mapping->info_numprocs);CHKERRQ(ierr);
4611bd0b88eSStefano Zampini   if (mapping->info_indices) {
4621bd0b88eSStefano Zampini     PetscInt i;
4631bd0b88eSStefano Zampini 
4641bd0b88eSStefano Zampini     ierr = PetscFree((mapping->info_indices)[0]);CHKERRQ(ierr);
4651bd0b88eSStefano Zampini     for (i=1; i<mapping->info_nproc; i++) {
4661bd0b88eSStefano Zampini       ierr = PetscFree(mapping->info_indices[i]);CHKERRQ(ierr);
4671bd0b88eSStefano Zampini     }
4681bd0b88eSStefano Zampini     ierr = PetscFree(mapping->info_indices);CHKERRQ(ierr);
4691bd0b88eSStefano Zampini   }
4701bd0b88eSStefano Zampini   mapping->info_cached = PETSC_FALSE;
4711bd0b88eSStefano Zampini 
472413f72f0SBarry Smith   if (mapping->ops->destroy) {
473413f72f0SBarry Smith     ierr = (*mapping->ops->destroy)(mapping);CHKERRQ(ierr);
474413f72f0SBarry Smith   }
47563fa5c83Sstefano_zampini   PetscFunctionReturn(0);
47663fa5c83Sstefano_zampini }
47763fa5c83Sstefano_zampini 
47845b6f7e9SBarry Smith /*@
47945b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
48045b6f7e9SBarry Smith     ordering and a global parallel ordering.
48145b6f7e9SBarry Smith 
48245b6f7e9SBarry Smith     Not Collective
48345b6f7e9SBarry Smith 
48445b6f7e9SBarry Smith     Input Parameters:
48545b6f7e9SBarry Smith .   mapping - mapping data structure
48645b6f7e9SBarry Smith 
48745b6f7e9SBarry Smith     Output Parameter:
48845b6f7e9SBarry Smith .   bs - the blocksize
48945b6f7e9SBarry Smith 
49045b6f7e9SBarry Smith     Level: advanced
49145b6f7e9SBarry Smith 
49245b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
49345b6f7e9SBarry Smith @*/
49445b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
49545b6f7e9SBarry Smith {
49645b6f7e9SBarry Smith   PetscFunctionBegin;
497cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
49845b6f7e9SBarry Smith   *bs = mapping->bs;
49945b6f7e9SBarry Smith   PetscFunctionReturn(0);
50045b6f7e9SBarry Smith }
50145b6f7e9SBarry Smith 
502ba5bb76aSSatish Balay /*@
50390f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
50490f02eecSBarry Smith     ordering and a global parallel ordering.
5052362add9SBarry Smith 
50689d82c54SBarry Smith     Not Collective, but communicator may have more than one process
507b9cd556bSLois Curfman McInnes 
5082362add9SBarry Smith     Input Parameters:
50989d82c54SBarry Smith +   comm - MPI communicator
510f0413b6fSBarry Smith .   bs - the block size
51128bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
51228bc9809SBarry 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
513d5ad8652SBarry Smith -   mode - see PetscCopyMode
5142362add9SBarry Smith 
515a997ad1aSLois Curfman McInnes     Output Parameter:
51690f02eecSBarry Smith .   mapping - new mapping data structure
5172362add9SBarry Smith 
51895452b02SPatrick Sanan     Notes:
51995452b02SPatrick Sanan     There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
520413f72f0SBarry Smith 
5219a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
522413f72f0SBarry Smith     this uses more memory but is faster; this approach is not scalable for extremely large mappings. For large problems ISLOCALTOGLOBALMAPPINGHASH is used, this is scalable.
523413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
524413f72f0SBarry Smith 
525a997ad1aSLois Curfman McInnes     Level: advanced
526a997ad1aSLois Curfman McInnes 
527413f72f0SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingSetFromOptions(), ISLOCALTOGLOBALMAPPINGBASIC, ISLOCALTOGLOBALMAPPINGHASH
528413f72f0SBarry Smith           ISLocalToGlobalMappingSetType(), ISLocalToGlobalMappingType
5292362add9SBarry Smith @*/
53060c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
5312362add9SBarry Smith {
5326849ba73SBarry Smith   PetscErrorCode ierr;
53332dcc486SBarry Smith   PetscInt       *in;
534b46b645bSBarry Smith 
535b46b645bSBarry Smith   PetscFunctionBegin;
53673911063SBarry Smith   if (n) PetscValidIntPointer(indices,3);
5374482741eSBarry Smith   PetscValidPointer(mapping,4);
538b46b645bSBarry Smith 
5390298fd71SBarry Smith   *mapping = NULL;
540607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
5412362add9SBarry Smith 
54273107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
54360c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
544d4bb536fSBarry Smith   (*mapping)->n             = n;
545f0413b6fSBarry Smith   (*mapping)->bs            = bs;
546268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
547268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
548268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
549268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
550268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
5511bd0b88eSStefano Zampini   (*mapping)->info_nodec    = NULL;
5521bd0b88eSStefano Zampini   (*mapping)->info_nodei    = NULL;
553413f72f0SBarry Smith 
554413f72f0SBarry Smith   (*mapping)->ops->globaltolocalmappingapply      = NULL;
555413f72f0SBarry Smith   (*mapping)->ops->globaltolocalmappingapplyblock = NULL;
556413f72f0SBarry Smith   (*mapping)->ops->destroy                        = NULL;
557d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
558785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
559580bdb30SBarry Smith     ierr = PetscArraycpy(in,indices,n);CHKERRQ(ierr);
560d5ad8652SBarry Smith     (*mapping)->indices = in;
5616389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
5626389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
5636389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
5646389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
5656389a1a1SBarry Smith   }
56660c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
5673a40ed3dSBarry Smith   PetscFunctionReturn(0);
5682362add9SBarry Smith }
5692362add9SBarry Smith 
570413f72f0SBarry Smith PetscFunctionList ISLocalToGlobalMappingList = NULL;
571413f72f0SBarry Smith 
572413f72f0SBarry Smith 
57390f02eecSBarry Smith /*@
5747e99dc12SLawrence Mitchell    ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database.
5757e99dc12SLawrence Mitchell 
5767e99dc12SLawrence Mitchell    Not collective
5777e99dc12SLawrence Mitchell 
5787e99dc12SLawrence Mitchell    Input Parameters:
5797e99dc12SLawrence Mitchell .  mapping - mapping data structure
5807e99dc12SLawrence Mitchell 
5817e99dc12SLawrence Mitchell    Level: advanced
5827e99dc12SLawrence Mitchell 
5837e99dc12SLawrence Mitchell @*/
5847e99dc12SLawrence Mitchell PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)
5857e99dc12SLawrence Mitchell {
5867e99dc12SLawrence Mitchell   PetscErrorCode             ierr;
587413f72f0SBarry Smith   char                       type[256];
588413f72f0SBarry Smith   ISLocalToGlobalMappingType defaulttype = "Not set";
5897e99dc12SLawrence Mitchell   PetscBool                  flg;
5907e99dc12SLawrence Mitchell 
5917e99dc12SLawrence Mitchell   PetscFunctionBegin;
5927e99dc12SLawrence Mitchell   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
593413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegisterAll();CHKERRQ(ierr);
5947e99dc12SLawrence Mitchell   ierr = PetscObjectOptionsBegin((PetscObject)mapping);CHKERRQ(ierr);
595413f72f0SBarry Smith   ierr = PetscOptionsFList("-islocaltoglobalmapping_type","ISLocalToGlobalMapping method","ISLocalToGlobalMappingSetType",ISLocalToGlobalMappingList,(char*)(((PetscObject)mapping)->type_name) ? ((PetscObject)mapping)->type_name : defaulttype,type,256,&flg);CHKERRQ(ierr);
596413f72f0SBarry Smith   if (flg) {
597413f72f0SBarry Smith     ierr = ISLocalToGlobalMappingSetType(mapping,type);CHKERRQ(ierr);
598413f72f0SBarry Smith   }
5997e99dc12SLawrence Mitchell   ierr = PetscOptionsEnd();CHKERRQ(ierr);
6007e99dc12SLawrence Mitchell   PetscFunctionReturn(0);
6017e99dc12SLawrence Mitchell }
6027e99dc12SLawrence Mitchell 
6037e99dc12SLawrence Mitchell /*@
60490f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
60590f02eecSBarry Smith    ordering and a global parallel ordering.
60690f02eecSBarry Smith 
6070f5bd95cSBarry Smith    Note Collective
608b9cd556bSLois Curfman McInnes 
60990f02eecSBarry Smith    Input Parameters:
61090f02eecSBarry Smith .  mapping - mapping data structure
61190f02eecSBarry Smith 
612a997ad1aSLois Curfman McInnes    Level: advanced
613a997ad1aSLois Curfman McInnes 
6143acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
61590f02eecSBarry Smith @*/
6166bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
61790f02eecSBarry Smith {
618dfbe8321SBarry Smith   PetscErrorCode ierr;
6195fd66863SKarl Rupp 
6203a40ed3dSBarry Smith   PetscFunctionBegin;
6216bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
6226bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
623*4c8fdceaSLisandro Dalcin   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = NULL;PetscFunctionReturn(0);}
6246bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
625268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
626268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
627268a049cSStefano Zampini   if ((*mapping)->info_indices) {
628268a049cSStefano Zampini     PetscInt i;
629268a049cSStefano Zampini 
630268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
631268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
632268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
633268a049cSStefano Zampini     }
634268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
635268a049cSStefano Zampini   }
6361bd0b88eSStefano Zampini   if ((*mapping)->info_nodei) {
6371bd0b88eSStefano Zampini     ierr = PetscFree(((*mapping)->info_nodei)[0]);CHKERRQ(ierr);
6381bd0b88eSStefano Zampini   }
639071fcb05SBarry Smith   ierr = PetscFree2((*mapping)->info_nodec,(*mapping)->info_nodei);CHKERRQ(ierr);
640413f72f0SBarry Smith   if ((*mapping)->ops->destroy) {
641413f72f0SBarry Smith     ierr = (*(*mapping)->ops->destroy)(*mapping);CHKERRQ(ierr);
642413f72f0SBarry Smith   }
643d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
644*4c8fdceaSLisandro Dalcin   *mapping = NULL;
6453a40ed3dSBarry Smith   PetscFunctionReturn(0);
64690f02eecSBarry Smith }
64790f02eecSBarry Smith 
64890f02eecSBarry Smith /*@
6493acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
6503acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
6513acfe500SLois Curfman McInnes     context.
65290f02eecSBarry Smith 
6534cb36875SStefano Zampini     Collective on is
654b9cd556bSLois Curfman McInnes 
65590f02eecSBarry Smith     Input Parameters:
656b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
657b9cd556bSLois Curfman McInnes -   is - index set in local numbering
65890f02eecSBarry Smith 
65990f02eecSBarry Smith     Output Parameters:
66090f02eecSBarry Smith .   newis - index set in global numbering
66190f02eecSBarry Smith 
6624cb36875SStefano Zampini     Notes:
6634cb36875SStefano Zampini     The output IS will have the same communicator of the input IS.
6644cb36875SStefano Zampini 
665a997ad1aSLois Curfman McInnes     Level: advanced
666a997ad1aSLois Curfman McInnes 
66790f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
668d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
66990f02eecSBarry Smith @*/
6707087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
67190f02eecSBarry Smith {
6726849ba73SBarry Smith   PetscErrorCode ierr;
673e24637baSBarry Smith   PetscInt       n,*idxout;
6745d0c19d7SBarry Smith   const PetscInt *idxin;
6753a40ed3dSBarry Smith 
6763a40ed3dSBarry Smith   PetscFunctionBegin;
6770700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
6780700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
6794482741eSBarry Smith   PetscValidPointer(newis,3);
68090f02eecSBarry Smith 
6813b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
68290f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
683785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
684e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
6853b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
686543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
6873a40ed3dSBarry Smith   PetscFunctionReturn(0);
68890f02eecSBarry Smith }
68990f02eecSBarry Smith 
690b89cb25eSSatish Balay /*@
6913acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
6923acfe500SLois Curfman McInnes    and converts them to the global numbering.
69390f02eecSBarry Smith 
694b9cd556bSLois Curfman McInnes    Not collective
695b9cd556bSLois Curfman McInnes 
696bb25748dSBarry Smith    Input Parameters:
697b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
698bb25748dSBarry Smith .  N - number of integers
699b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
700bb25748dSBarry Smith 
701bb25748dSBarry Smith    Output Parameter:
702bb25748dSBarry Smith .  out - indices in global numbering
703bb25748dSBarry Smith 
704b9cd556bSLois Curfman McInnes    Notes:
705b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
706d4bb536fSBarry Smith 
707a997ad1aSLois Curfman McInnes    Level: advanced
708a997ad1aSLois Curfman McInnes 
70945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
7100752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
711d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
712bb25748dSBarry Smith 
713afcb2eb5SJed Brown @*/
714afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
715afcb2eb5SJed Brown {
716cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
71745b6f7e9SBarry Smith 
71845b6f7e9SBarry Smith   PetscFunctionBegin;
719cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
720cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
721cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
72245b6f7e9SBarry Smith   if (bs == 1) {
723cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
72445b6f7e9SBarry Smith     for (i=0; i<N; i++) {
72545b6f7e9SBarry Smith       if (in[i] < 0) {
72645b6f7e9SBarry Smith         out[i] = in[i];
72745b6f7e9SBarry Smith         continue;
72845b6f7e9SBarry Smith       }
729e24637baSBarry 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);
73045b6f7e9SBarry Smith       out[i] = idx[in[i]];
73145b6f7e9SBarry Smith     }
73245b6f7e9SBarry Smith   } else {
733cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
73445b6f7e9SBarry Smith     for (i=0; i<N; i++) {
73545b6f7e9SBarry Smith       if (in[i] < 0) {
73645b6f7e9SBarry Smith         out[i] = in[i];
73745b6f7e9SBarry Smith         continue;
73845b6f7e9SBarry Smith       }
739e24637baSBarry 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);
74045b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
74145b6f7e9SBarry Smith     }
74245b6f7e9SBarry Smith   }
74345b6f7e9SBarry Smith   PetscFunctionReturn(0);
74445b6f7e9SBarry Smith }
74545b6f7e9SBarry Smith 
74645b6f7e9SBarry Smith /*@
7476006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
74845b6f7e9SBarry Smith 
74945b6f7e9SBarry Smith    Not collective
75045b6f7e9SBarry Smith 
75145b6f7e9SBarry Smith    Input Parameters:
75245b6f7e9SBarry Smith +  mapping - the local to global mapping context
75345b6f7e9SBarry Smith .  N - number of integers
7546006e8d2SBarry Smith -  in - input indices in local block numbering
75545b6f7e9SBarry Smith 
75645b6f7e9SBarry Smith    Output Parameter:
7576006e8d2SBarry Smith .  out - indices in global block numbering
75845b6f7e9SBarry Smith 
75945b6f7e9SBarry Smith    Notes:
76045b6f7e9SBarry Smith    The in and out array parameters may be identical.
76145b6f7e9SBarry Smith 
7626006e8d2SBarry Smith    Example:
7636006e8d2SBarry 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
7646006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
7656006e8d2SBarry Smith 
76645b6f7e9SBarry Smith    Level: advanced
76745b6f7e9SBarry Smith 
76845b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
76945b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
77045b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
77145b6f7e9SBarry Smith 
77245b6f7e9SBarry Smith @*/
77345b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
77445b6f7e9SBarry Smith {
775cbc1caf0SMatthew G. Knepley 
776cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
777cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
778cbc1caf0SMatthew G. Knepley   {
779afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
780afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
781d4bb536fSBarry Smith 
782afcb2eb5SJed Brown     for (i=0; i<N; i++) {
783afcb2eb5SJed Brown       if (in[i] < 0) {
784afcb2eb5SJed Brown         out[i] = in[i];
785afcb2eb5SJed Brown         continue;
786afcb2eb5SJed Brown       }
787e24637baSBarry 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);
788afcb2eb5SJed Brown       out[i] = idx[in[i]];
789afcb2eb5SJed Brown     }
790cbc1caf0SMatthew G. Knepley   }
791afcb2eb5SJed Brown   PetscFunctionReturn(0);
792afcb2eb5SJed Brown }
793d4bb536fSBarry Smith 
7947e99dc12SLawrence Mitchell /*@
795a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
796a997ad1aSLois Curfman McInnes     specified with a global numbering.
797d4bb536fSBarry Smith 
798b9cd556bSLois Curfman McInnes     Not collective
799b9cd556bSLois Curfman McInnes 
800d4bb536fSBarry Smith     Input Parameters:
801b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
8020040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
803d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
804d4bb536fSBarry Smith .   n - number of global indices to map
805b9cd556bSLois Curfman McInnes -   idx - global indices to map
806d4bb536fSBarry Smith 
807d4bb536fSBarry Smith     Output Parameters:
808b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
809b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
810e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
8110298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
812e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
813e182c471SBarry Smith              a second time to set the values.
814d4bb536fSBarry Smith 
815b9cd556bSLois Curfman McInnes     Notes:
8160298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
817d4bb536fSBarry Smith 
8189a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
819413f72f0SBarry Smith     this uses more memory but is faster; this approach is not scalable for extremely large mappings. For large problems ISLOCALTOGLOBALMAPPINGHASH is used, this is scalable.
820413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
8210f5bd95cSBarry Smith 
822a997ad1aSLois Curfman McInnes     Level: advanced
823a997ad1aSLois Curfman McInnes 
82432fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
82532fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
82632fd6b96SBarry Smith 
8279d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
828413f72f0SBarry Smith           ISLocalToGlobalMappingDestroy()
829d4bb536fSBarry Smith @*/
830413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
831d4bb536fSBarry Smith {
8329d90f715SBarry Smith   PetscErrorCode ierr;
8339d90f715SBarry Smith 
8349d90f715SBarry Smith   PetscFunctionBegin;
8359d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
836413f72f0SBarry Smith   if (!mapping->data) {
837413f72f0SBarry Smith     ierr = ISGlobalToLocalMappingSetUp(mapping);CHKERRQ(ierr);
8389d90f715SBarry Smith   }
839413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingapply)(mapping,type,n,idx,nout,idxout);CHKERRQ(ierr);
8409d90f715SBarry Smith   PetscFunctionReturn(0);
8419d90f715SBarry Smith }
8429d90f715SBarry Smith 
843d4fe737eSStefano Zampini /*@
844d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
845d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
846d4fe737eSStefano Zampini     context.
847d4fe737eSStefano Zampini 
848d4fe737eSStefano Zampini     Not collective
849d4fe737eSStefano Zampini 
850d4fe737eSStefano Zampini     Input Parameters:
851d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
8520040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
8532785b321SStefano Zampini            IS_GTOLM_DROP - drops the indices with no local value from the output list
854d4fe737eSStefano Zampini -   is - index set in global numbering
855d4fe737eSStefano Zampini 
856d4fe737eSStefano Zampini     Output Parameters:
857d4fe737eSStefano Zampini .   newis - index set in local numbering
858d4fe737eSStefano Zampini 
8594cb36875SStefano Zampini     Notes:
8604cb36875SStefano Zampini     The output IS will be sequential, as it encodes a purely local operation
8614cb36875SStefano Zampini 
862d4fe737eSStefano Zampini     Level: advanced
863d4fe737eSStefano Zampini 
864d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
865d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
866d4fe737eSStefano Zampini @*/
867413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,IS is,IS *newis)
868d4fe737eSStefano Zampini {
869d4fe737eSStefano Zampini   PetscErrorCode ierr;
870d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
871d4fe737eSStefano Zampini   const PetscInt *idxin;
872d4fe737eSStefano Zampini 
873d4fe737eSStefano Zampini   PetscFunctionBegin;
874d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
875d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
876d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
877d4fe737eSStefano Zampini 
878d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
879d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
880d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
881d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
882d4fe737eSStefano Zampini   } else {
883d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
884d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
885d4fe737eSStefano Zampini   }
886d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
887d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
8884cb36875SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
889d4fe737eSStefano Zampini   PetscFunctionReturn(0);
890d4fe737eSStefano Zampini }
891d4fe737eSStefano Zampini 
8929d90f715SBarry Smith /*@
8939d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
8949d90f715SBarry Smith     specified with a block global numbering.
8959d90f715SBarry Smith 
8969d90f715SBarry Smith     Not collective
8979d90f715SBarry Smith 
8989d90f715SBarry Smith     Input Parameters:
8999d90f715SBarry Smith +   mapping - mapping between local and global numbering
9000040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
9019d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
9029d90f715SBarry Smith .   n - number of global indices to map
9039d90f715SBarry Smith -   idx - global indices to map
9049d90f715SBarry Smith 
9059d90f715SBarry Smith     Output Parameters:
9069d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
9079d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
9089d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
9099d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
9109d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
9119d90f715SBarry Smith              a second time to set the values.
9129d90f715SBarry Smith 
9139d90f715SBarry Smith     Notes:
9149d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
9159d90f715SBarry Smith 
9169a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
917413f72f0SBarry Smith     this uses more memory but is faster; this approach is not scalable for extremely large mappings. For large problems ISLOCALTOGLOBALMAPPINGHASH is used, this is scalable.
918413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
9199d90f715SBarry Smith 
9209d90f715SBarry Smith     Level: advanced
9219d90f715SBarry Smith 
9229d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
9239d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
9249d90f715SBarry Smith 
9259d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
926413f72f0SBarry Smith           ISLocalToGlobalMappingDestroy()
9279d90f715SBarry Smith @*/
928413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,
9299d90f715SBarry Smith                                                  PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
9309d90f715SBarry Smith {
9316849ba73SBarry Smith   PetscErrorCode ierr;
932d4bb536fSBarry Smith 
9333a40ed3dSBarry Smith   PetscFunctionBegin;
9340700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
935413f72f0SBarry Smith   if (!mapping->data) {
936413f72f0SBarry Smith     ierr = ISGlobalToLocalMappingSetUp(mapping);CHKERRQ(ierr);
937d4bb536fSBarry Smith   }
938413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingapplyblock)(mapping,type,n,idx,nout,idxout);CHKERRQ(ierr);
9393a40ed3dSBarry Smith   PetscFunctionReturn(0);
940d4bb536fSBarry Smith }
94190f02eecSBarry Smith 
942413f72f0SBarry Smith 
94389d82c54SBarry Smith /*@C
9446a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
94589d82c54SBarry Smith      each index shared by more than one processor
94689d82c54SBarry Smith 
94789d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
94889d82c54SBarry Smith 
94989d82c54SBarry Smith     Input Parameters:
95089d82c54SBarry Smith .   mapping - the mapping from local to global indexing
95189d82c54SBarry Smith 
95289d82c54SBarry Smith     Output Parameter:
95389d82c54SBarry Smith +   nproc - number of processors that are connected to this one
95489d82c54SBarry Smith .   proc - neighboring processors
95507b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
9563463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
95789d82c54SBarry Smith 
95889d82c54SBarry Smith     Level: advanced
95989d82c54SBarry Smith 
9602cfcea29SBarry Smith     Fortran Usage:
9612cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
9622cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
9632cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
9642cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
9652cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
9662cfcea29SBarry Smith 
9672cfcea29SBarry Smith 
96807b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
96907b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
97089d82c54SBarry Smith @*/
9716a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
97289d82c54SBarry Smith {
9736849ba73SBarry Smith   PetscErrorCode ierr;
974268a049cSStefano Zampini 
975268a049cSStefano Zampini   PetscFunctionBegin;
976268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
977268a049cSStefano Zampini   if (mapping->info_cached) {
978268a049cSStefano Zampini     *nproc    = mapping->info_nproc;
979268a049cSStefano Zampini     *procs    = mapping->info_procs;
980268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
981268a049cSStefano Zampini     *indices  = mapping->info_indices;
982268a049cSStefano Zampini   } else {
983268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
984268a049cSStefano Zampini   }
985268a049cSStefano Zampini   PetscFunctionReturn(0);
986268a049cSStefano Zampini }
987268a049cSStefano Zampini 
988268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
989268a049cSStefano Zampini {
990268a049cSStefano Zampini   PetscErrorCode ierr;
99197f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
99232dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
99332dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
99497f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
99532dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
99632dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
99789d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
99830dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
999ce94432eSBarry Smith   MPI_Comm       comm;
1000ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
100189d82c54SBarry Smith 
100289d82c54SBarry Smith   PetscFunctionBegin;
1003ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
100424cf384cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
100524cf384cSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
100624cf384cSBarry Smith   if (size == 1) {
100724cf384cSBarry Smith     *nproc         = 0;
10080298fd71SBarry Smith     *procs         = NULL;
100995dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
10101e2105dcSBarry Smith     (*numprocs)[0] = 0;
101195dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
10120298fd71SBarry Smith     (*indices)[0]  = NULL;
1013268a049cSStefano Zampini     /* save info for reuse */
1014268a049cSStefano Zampini     mapping->info_nproc = *nproc;
1015268a049cSStefano Zampini     mapping->info_procs = *procs;
1016268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
1017268a049cSStefano Zampini     mapping->info_indices = *indices;
1018268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
101924cf384cSBarry Smith     PetscFunctionReturn(0);
102024cf384cSBarry Smith   }
102124cf384cSBarry Smith 
1022c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
102307b52d57SBarry Smith 
10243677ff5aSBarry Smith   /*
10256a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
10263677ff5aSBarry Smith 
10273677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
10283677ff5aSBarry Smith            numbering, just for this routine.
10293677ff5aSBarry Smith 
10303677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
10313677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
10323677ff5aSBarry Smith 
10333677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
10343677ff5aSBarry Smith 
10353677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
10363677ff5aSBarry Smith            local subdomain
10373677ff5aSBarry Smith   */
103824cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
103924cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
104024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
104189d82c54SBarry Smith 
104289d82c54SBarry Smith   for (i=0; i<n; i++) {
104389d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
104489d82c54SBarry Smith   }
1045b2566f29SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
104678058e43SBarry Smith   Ng++;
104789d82c54SBarry Smith   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
104889d82c54SBarry Smith   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1049bc8ff85bSBarry Smith   scale  = Ng/size + 1;
1050a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
1051caba0dd0SBarry Smith   rstart = scale*rank;
105289d82c54SBarry Smith 
105389d82c54SBarry Smith   /* determine ownership ranges of global indices */
1054785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
1055580bdb30SBarry Smith   ierr = PetscArrayzero(nprocs,2*size);CHKERRQ(ierr);
105689d82c54SBarry Smith 
105789d82c54SBarry Smith   /* determine owners of each local node  */
1058785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
105989d82c54SBarry Smith   for (i=0; i<n; i++) {
10603677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
106127c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
10623677ff5aSBarry Smith     owner[i]         = proc;
106327c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
106489d82c54SBarry Smith   }
106527c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
10667904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
106789d82c54SBarry Smith 
106889d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
106927c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
10707904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
107189d82c54SBarry Smith 
107289d82c54SBarry Smith   /* post receives for owned rows */
1073785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
1074854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
107589d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
107632dcc486SBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr);
107789d82c54SBarry Smith   }
107889d82c54SBarry Smith 
107989d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
1080854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
1081854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
108289d82c54SBarry Smith   starts[0] = 0;
1083f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
108489d82c54SBarry Smith   for (i=0; i<n; i++) {
108589d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
108630dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
108789d82c54SBarry Smith   }
108889d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
108989d82c54SBarry Smith   starts[0] = 0;
1090f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
109189d82c54SBarry Smith 
109289d82c54SBarry Smith   /* send the messages */
1093854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
1094854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
109589d82c54SBarry Smith   cnt = 0;
109689d82c54SBarry Smith   for (i=0; i<size; i++) {
109727c402fcSBarry Smith     if (nprocs[2*i]) {
109832dcc486SBarry Smith       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr);
109930dcb7c9SBarry Smith       dest[cnt] = i;
110089d82c54SBarry Smith       cnt++;
110189d82c54SBarry Smith     }
110289d82c54SBarry Smith   }
110389d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
110489d82c54SBarry Smith 
110589d82c54SBarry Smith   /* wait on receives */
1106854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
1107854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
110889d82c54SBarry Smith   cnt  = nrecvs;
1109580bdb30SBarry Smith   ierr = PetscCalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
111089d82c54SBarry Smith   while (cnt) {
111189d82c54SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
111289d82c54SBarry Smith     /* unpack receives into our local space */
111332dcc486SBarry Smith     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr);
111489d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
111530dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
1116caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
111730dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
111889d82c54SBarry Smith     cnt--;
111989d82c54SBarry Smith   }
112089d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
112189d82c54SBarry Smith 
112230dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1123bc8ff85bSBarry Smith   nowned  = 0;
1124bc8ff85bSBarry Smith   nownedm = 0;
1125bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
1126bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
1127bc8ff85bSBarry Smith   }
1128bc8ff85bSBarry Smith 
1129bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1130854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1131854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1132bc8ff85bSBarry Smith   starts[0] = 0;
1133bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1134bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1135bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1136bc8ff85bSBarry Smith   }
1137bc8ff85bSBarry Smith 
113830dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1139bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1140bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
114130dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1142f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1143bc8ff85bSBarry Smith     }
1144bc8ff85bSBarry Smith   }
1145bc8ff85bSBarry Smith 
114607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
114730dcb7c9SBarry Smith     starts[0] = 0;
114830dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
114930dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
115030dcb7c9SBarry Smith       else starts[i] = starts[i-1];
115130dcb7c9SBarry Smith     }
115230dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
115330dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
11547904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
115530dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
11567904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
115730dcb7c9SBarry Smith         }
115830dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
115930dcb7c9SBarry Smith       }
116030dcb7c9SBarry Smith     }
11610ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
116207b52d57SBarry Smith   } /* -----------------------------------  */
116330dcb7c9SBarry Smith 
11643677ff5aSBarry Smith   /* wait on original sends */
11653a96401aSBarry Smith   if (nsends) {
1166785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
11673a96401aSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
11683a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
11693a96401aSBarry Smith   }
117089d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
11713a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
11723677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
11733677ff5aSBarry Smith 
11743677ff5aSBarry Smith   /* pack messages to send back to local owners */
117530dcb7c9SBarry Smith   starts[0] = 0;
117630dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
117730dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
117830dcb7c9SBarry Smith     else starts[i] = starts[i-1];
117930dcb7c9SBarry Smith   }
118030dcb7c9SBarry Smith   nsends2 = nrecvs;
1181854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
118230dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
118330dcb7c9SBarry Smith     nprocs[i] = 1;
118430dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
118530dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1186f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
118730dcb7c9SBarry Smith     }
118830dcb7c9SBarry Smith   }
1189f6e5521dSKarl Rupp   nt = 0;
1190f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1191f6e5521dSKarl Rupp 
1192854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1193854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1194f6e5521dSKarl Rupp 
1195f6e5521dSKarl Rupp   starts2[0] = 0;
1196f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
119730dcb7c9SBarry Smith   /*
119830dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
119930dcb7c9SBarry Smith        (0) the number of nodes being sent back
120030dcb7c9SBarry Smith        (1) the local node number,
120130dcb7c9SBarry Smith        (2) the number of processors sharing it,
120230dcb7c9SBarry Smith        (3) the processors sharing it
120330dcb7c9SBarry Smith   */
120430dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
120530dcb7c9SBarry Smith     cnt = 1;
120630dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
120730dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
120830dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
120930dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
121030dcb7c9SBarry Smith         sends2[starts2[i]]++;
121130dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
121230dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
1213580bdb30SBarry Smith         ierr = PetscArraycpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]);CHKERRQ(ierr);
121430dcb7c9SBarry Smith         cnt += nownedsenders[node];
121530dcb7c9SBarry Smith       }
121630dcb7c9SBarry Smith     }
121730dcb7c9SBarry Smith   }
121830dcb7c9SBarry Smith 
121930dcb7c9SBarry Smith   /* receive the message lengths */
122030dcb7c9SBarry Smith   nrecvs2 = nsends;
1221854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1222854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1223854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
122430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1225d44834fbSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr);
122630dcb7c9SBarry Smith   }
1227d44834fbSBarry Smith 
12288a8e0b3aSBarry Smith   /* send the message lengths */
12298a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
12308a8e0b3aSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr);
12318a8e0b3aSBarry Smith   }
12328a8e0b3aSBarry Smith 
1233d44834fbSBarry Smith   /* wait on receives of lens */
12340c468ba9SBarry Smith   if (nrecvs2) {
1235785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1236d44834fbSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
1237d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
12380c468ba9SBarry Smith   }
1239a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1240d44834fbSBarry Smith 
124130dcb7c9SBarry Smith   starts3[0] = 0;
1242d44834fbSBarry Smith   nt         = 0;
124330dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
124430dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1245d44834fbSBarry Smith     nt          += lens2[i];
124630dcb7c9SBarry Smith   }
124776466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1248d44834fbSBarry Smith 
1249854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1250854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
125152b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
125232dcc486SBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr);
125330dcb7c9SBarry Smith   }
125430dcb7c9SBarry Smith 
125530dcb7c9SBarry Smith   /* send the messages */
1256854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
125730dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
125832dcc486SBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr);
125930dcb7c9SBarry Smith   }
126030dcb7c9SBarry Smith 
126130dcb7c9SBarry Smith   /* wait on receives */
12620c468ba9SBarry Smith   if (nrecvs2) {
1263785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
126430dcb7c9SBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr);
126530dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
12660c468ba9SBarry Smith   }
126730dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
126830dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
126930dcb7c9SBarry Smith 
127007b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
127130dcb7c9SBarry Smith     cnt = 0;
127230dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
127330dcb7c9SBarry Smith       nt = recvs2[cnt++];
127430dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
12757904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
127630dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
12777904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
127830dcb7c9SBarry Smith         }
127930dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
128030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
128130dcb7c9SBarry Smith       }
128230dcb7c9SBarry Smith     }
12830ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
128407b52d57SBarry Smith   } /* -----------------------------------  */
128530dcb7c9SBarry Smith 
128630dcb7c9SBarry Smith   /* count number subdomains for each local node */
1287580bdb30SBarry Smith   ierr = PetscCalloc1(size,&nprocs);CHKERRQ(ierr);
128830dcb7c9SBarry Smith   cnt  = 0;
128930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
129030dcb7c9SBarry Smith     nt = recvs2[cnt++];
129130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1292f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
129330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
129430dcb7c9SBarry Smith     }
129530dcb7c9SBarry Smith   }
129630dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
129730dcb7c9SBarry Smith   *nproc    = nt;
1298854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1299854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1300854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
13010298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1302785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
130330dcb7c9SBarry Smith   cnt  = 0;
130430dcb7c9SBarry Smith   for (i=0; i<size; i++) {
130530dcb7c9SBarry Smith     if (nprocs[i] > 0) {
130630dcb7c9SBarry Smith       bprocs[i]        = cnt;
130730dcb7c9SBarry Smith       (*procs)[cnt]    = i;
130830dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1309785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
131030dcb7c9SBarry Smith       cnt++;
131130dcb7c9SBarry Smith     }
131230dcb7c9SBarry Smith   }
131330dcb7c9SBarry Smith 
131430dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
1315580bdb30SBarry Smith   ierr = PetscArrayzero(*numprocs,nt);CHKERRQ(ierr);
131630dcb7c9SBarry Smith   cnt  = 0;
131730dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
131830dcb7c9SBarry Smith     nt = recvs2[cnt++];
131930dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1320f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
132130dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
132230dcb7c9SBarry Smith     }
132330dcb7c9SBarry Smith   }
132430dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
132507b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
132630dcb7c9SBarry Smith 
132707b52d57SBarry Smith   /* sort the node indexing by their global numbers */
132807b52d57SBarry Smith   nt = *nproc;
132907b52d57SBarry Smith   for (i=0; i<nt; i++) {
1330854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1331f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
133207b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
133307b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
133407b52d57SBarry Smith   }
133507b52d57SBarry Smith 
133607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
133730dcb7c9SBarry Smith     nt = *nproc;
133830dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
13397904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
134030dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
13417904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
134230dcb7c9SBarry Smith       }
134330dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
134430dcb7c9SBarry Smith     }
13450ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
134607b52d57SBarry Smith   } /* -----------------------------------  */
134730dcb7c9SBarry Smith 
134830dcb7c9SBarry Smith   /* wait on sends */
134930dcb7c9SBarry Smith   if (nsends2) {
1350785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
135130dcb7c9SBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr);
135230dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
135330dcb7c9SBarry Smith   }
135430dcb7c9SBarry Smith 
135530dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
135630dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
135730dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
13583677ff5aSBarry Smith 
1359bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1360bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1361bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
136230dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
136330dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
136489d82c54SBarry Smith 
136589d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
136697f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
136789d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
13683a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
136930dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
137024cf384cSBarry Smith 
137124cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
137224cf384cSBarry Smith   first_procs    = (*procs)[0];
137324cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
137424cf384cSBarry Smith   first_indices  = (*indices)[0];
137524cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
137624cf384cSBarry Smith     if ((*procs)[i] == rank) {
137724cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
137824cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
137924cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
138024cf384cSBarry Smith       (*procs)[i]    = first_procs;
138124cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
138224cf384cSBarry Smith       (*indices)[i]  = first_indices;
138324cf384cSBarry Smith       break;
138424cf384cSBarry Smith     }
138524cf384cSBarry Smith   }
1386268a049cSStefano Zampini 
1387268a049cSStefano Zampini   /* save info for reuse */
1388268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1389268a049cSStefano Zampini   mapping->info_procs = *procs;
1390268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1391268a049cSStefano Zampini   mapping->info_indices = *indices;
1392268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
139389d82c54SBarry Smith   PetscFunctionReturn(0);
139489d82c54SBarry Smith }
139589d82c54SBarry Smith 
13966a818285SBarry Smith /*@C
13976a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
13986a818285SBarry Smith 
13996a818285SBarry Smith     Collective on ISLocalToGlobalMapping
14006a818285SBarry Smith 
14016a818285SBarry Smith     Input Parameters:
14026a818285SBarry Smith .   mapping - the mapping from local to global indexing
14036a818285SBarry Smith 
14046a818285SBarry Smith     Output Parameter:
14056a818285SBarry Smith +   nproc - number of processors that are connected to this one
14066a818285SBarry Smith .   proc - neighboring processors
14076a818285SBarry Smith .   numproc - number of indices for each processor
14086a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
14096a818285SBarry Smith 
14106a818285SBarry Smith     Level: advanced
14116a818285SBarry Smith 
14126a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
14136a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
14146a818285SBarry Smith @*/
14156a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
14166a818285SBarry Smith {
14176a818285SBarry Smith   PetscErrorCode ierr;
14186a818285SBarry Smith 
14196a818285SBarry Smith   PetscFunctionBegin;
1420cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1421268a049cSStefano Zampini   if (mapping->info_free) {
14226a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
14236a818285SBarry Smith     if (*indices) {
1424268a049cSStefano Zampini       PetscInt i;
1425268a049cSStefano Zampini 
14266a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
14276a818285SBarry Smith       for (i=1; i<*nproc; i++) {
14286a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
14296a818285SBarry Smith       }
14306a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
14316a818285SBarry Smith     }
1432268a049cSStefano Zampini   }
1433268a049cSStefano Zampini   *nproc    = 0;
1434268a049cSStefano Zampini   *procs    = NULL;
1435268a049cSStefano Zampini   *numprocs = NULL;
1436268a049cSStefano Zampini   *indices  = NULL;
14376a818285SBarry Smith   PetscFunctionReturn(0);
14386a818285SBarry Smith }
14396a818285SBarry Smith 
14406a818285SBarry Smith /*@C
14416a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
14426a818285SBarry Smith      each index shared by more than one processor
14436a818285SBarry Smith 
14446a818285SBarry Smith     Collective on ISLocalToGlobalMapping
14456a818285SBarry Smith 
14466a818285SBarry Smith     Input Parameters:
14476a818285SBarry Smith .   mapping - the mapping from local to global indexing
14486a818285SBarry Smith 
14496a818285SBarry Smith     Output Parameter:
14506a818285SBarry Smith +   nproc - number of processors that are connected to this one
14516a818285SBarry Smith .   proc - neighboring processors
14526a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
14536a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
14546a818285SBarry Smith 
14556a818285SBarry Smith     Level: advanced
14566a818285SBarry Smith 
14571bd0b88eSStefano Zampini     Notes: The user needs to call ISLocalToGlobalMappingRestoreInfo when the data is no longer needed.
14581bd0b88eSStefano Zampini 
14596a818285SBarry Smith     Fortran Usage:
14606a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
14616a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
14626a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
14636a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
14646a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
14656a818285SBarry Smith 
14666a818285SBarry Smith 
14676a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
14686a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
14696a818285SBarry Smith @*/
14706a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
14716a818285SBarry Smith {
14726a818285SBarry Smith   PetscErrorCode ierr;
1473268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
14746a818285SBarry Smith 
14756a818285SBarry Smith   PetscFunctionBegin;
14766a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1477268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1478268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1479732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1480268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
14816a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1482268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1483268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
14846a818285SBarry Smith         for (k=0; k<bs; k++) {
14856a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
14866a818285SBarry Smith         }
14876a818285SBarry Smith       }
1488268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
14896a818285SBarry Smith     }
1490268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1491268a049cSStefano Zampini   } else {
1492268a049cSStefano Zampini     *numprocs = bnumprocs;
1493268a049cSStefano Zampini     *indices  = bindices;
14946a818285SBarry Smith   }
14956a818285SBarry Smith   PetscFunctionReturn(0);
14966a818285SBarry Smith }
14976a818285SBarry Smith 
149807b52d57SBarry Smith /*@C
149907b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
150089d82c54SBarry Smith 
150107b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
150207b52d57SBarry Smith 
150307b52d57SBarry Smith     Input Parameters:
150407b52d57SBarry Smith .   mapping - the mapping from local to global indexing
150507b52d57SBarry Smith 
150607b52d57SBarry Smith     Output Parameter:
150707b52d57SBarry Smith +   nproc - number of processors that are connected to this one
150807b52d57SBarry Smith .   proc - neighboring processors
150907b52d57SBarry Smith .   numproc - number of indices for each processor
151007b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
151107b52d57SBarry Smith 
151207b52d57SBarry Smith     Level: advanced
151307b52d57SBarry Smith 
151407b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
151507b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
151607b52d57SBarry Smith @*/
15177087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
151807b52d57SBarry Smith {
15196849ba73SBarry Smith   PetscErrorCode ierr;
152007b52d57SBarry Smith 
152107b52d57SBarry Smith   PetscFunctionBegin;
15226a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
152307b52d57SBarry Smith   PetscFunctionReturn(0);
152407b52d57SBarry Smith }
152586994e45SJed Brown 
152686994e45SJed Brown /*@C
15271bd0b88eSStefano Zampini     ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information for each node
15281bd0b88eSStefano Zampini 
15291bd0b88eSStefano Zampini     Collective on ISLocalToGlobalMapping
15301bd0b88eSStefano Zampini 
15311bd0b88eSStefano Zampini     Input Parameters:
15321bd0b88eSStefano Zampini .   mapping - the mapping from local to global indexing
15331bd0b88eSStefano Zampini 
15341bd0b88eSStefano Zampini     Output Parameter:
15351bd0b88eSStefano Zampini +   nnodes - number of local nodes (same ISLocalToGlobalMappingGetSize())
15361bd0b88eSStefano Zampini .   count - number of neighboring processors per node
15371bd0b88eSStefano Zampini -   indices - indices of processes sharing the node (sorted)
15381bd0b88eSStefano Zampini 
15391bd0b88eSStefano Zampini     Level: advanced
15401bd0b88eSStefano Zampini 
15411bd0b88eSStefano Zampini     Notes: The user needs to call ISLocalToGlobalMappingRestoreInfo when the data is no longer needed.
15421bd0b88eSStefano Zampini 
15431bd0b88eSStefano Zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
15441bd0b88eSStefano Zampini           ISLocalToGlobalMappingGetInfo(), ISLocalToGlobalMappingRestoreNodeInfo()
15451bd0b88eSStefano Zampini @*/
15461bd0b88eSStefano Zampini PetscErrorCode  ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping,PetscInt *nnodes,PetscInt *count[],PetscInt **indices[])
15471bd0b88eSStefano Zampini {
15481bd0b88eSStefano Zampini   PetscInt       n;
15491bd0b88eSStefano Zampini   PetscErrorCode ierr;
15501bd0b88eSStefano Zampini 
15511bd0b88eSStefano Zampini   PetscFunctionBegin;
15521bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
15531bd0b88eSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mapping,&n);CHKERRQ(ierr);
15541bd0b88eSStefano Zampini   if (!mapping->info_nodec) {
15551bd0b88eSStefano Zampini     PetscInt i,m,n_neigh,*neigh,*n_shared,**shared;
15561bd0b88eSStefano Zampini 
1557071fcb05SBarry Smith     ierr = PetscMalloc2(n+1,&mapping->info_nodec,n,&mapping->info_nodei);CHKERRQ(ierr);
15581bd0b88eSStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1559071fcb05SBarry Smith     for (i=0;i<n;i++) { mapping->info_nodec[i] = 1;}
1560071fcb05SBarry Smith     m = n;
1561071fcb05SBarry Smith     mapping->info_nodec[n] = 0;
15621bd0b88eSStefano Zampini     for (i=1;i<n_neigh;i++) {
15631bd0b88eSStefano Zampini       PetscInt j;
15641bd0b88eSStefano Zampini 
15651bd0b88eSStefano Zampini       m += n_shared[i];
15661bd0b88eSStefano Zampini       for (j=0;j<n_shared[i];j++) mapping->info_nodec[shared[i][j]] += 1;
15671bd0b88eSStefano Zampini     }
15681bd0b88eSStefano Zampini     if (n) { ierr = PetscMalloc1(m,&mapping->info_nodei[0]);CHKERRQ(ierr); }
15691bd0b88eSStefano Zampini     for (i=1;i<n;i++) mapping->info_nodei[i] = mapping->info_nodei[i-1] + mapping->info_nodec[i-1];
1570580bdb30SBarry Smith     ierr = PetscArrayzero(mapping->info_nodec,n);CHKERRQ(ierr);
15711bd0b88eSStefano Zampini     for (i=0;i<n;i++) { mapping->info_nodec[i] = 1; mapping->info_nodei[i][0] = neigh[0]; }
15721bd0b88eSStefano Zampini     for (i=1;i<n_neigh;i++) {
15731bd0b88eSStefano Zampini       PetscInt j;
15741bd0b88eSStefano Zampini 
15751bd0b88eSStefano Zampini       for (j=0;j<n_shared[i];j++) {
15761bd0b88eSStefano Zampini         PetscInt k = shared[i][j];
15771bd0b88eSStefano Zampini 
15781bd0b88eSStefano Zampini         mapping->info_nodei[k][mapping->info_nodec[k]] = neigh[i];
15791bd0b88eSStefano Zampini         mapping->info_nodec[k] += 1;
15801bd0b88eSStefano Zampini       }
15811bd0b88eSStefano Zampini     }
15821bd0b88eSStefano Zampini     for (i=0;i<n;i++) { ierr = PetscSortRemoveDupsInt(&mapping->info_nodec[i],mapping->info_nodei[i]);CHKERRQ(ierr); }
15831bd0b88eSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
15841bd0b88eSStefano Zampini   }
15851bd0b88eSStefano Zampini   if (nnodes)  *nnodes  = n;
15861bd0b88eSStefano Zampini   if (count)   *count   = mapping->info_nodec;
15871bd0b88eSStefano Zampini   if (indices) *indices = mapping->info_nodei;
15881bd0b88eSStefano Zampini   PetscFunctionReturn(0);
15891bd0b88eSStefano Zampini }
15901bd0b88eSStefano Zampini 
15911bd0b88eSStefano Zampini /*@C
15921bd0b88eSStefano Zampini     ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by ISLocalToGlobalMappingGetNodeInfo()
15931bd0b88eSStefano Zampini 
15941bd0b88eSStefano Zampini     Collective on ISLocalToGlobalMapping
15951bd0b88eSStefano Zampini 
15961bd0b88eSStefano Zampini     Input Parameters:
15971bd0b88eSStefano Zampini .   mapping - the mapping from local to global indexing
15981bd0b88eSStefano Zampini 
15991bd0b88eSStefano Zampini     Output Parameter:
16001bd0b88eSStefano Zampini +   nnodes - number of local nodes
16011bd0b88eSStefano Zampini .   count - number of neighboring processors per node
16021bd0b88eSStefano Zampini -   indices - indices of processes sharing the node (sorted)
16031bd0b88eSStefano Zampini 
16041bd0b88eSStefano Zampini     Level: advanced
16051bd0b88eSStefano Zampini 
16061bd0b88eSStefano Zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
16071bd0b88eSStefano Zampini           ISLocalToGlobalMappingGetInfo()
16081bd0b88eSStefano Zampini @*/
16091bd0b88eSStefano Zampini PetscErrorCode  ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping,PetscInt *nnodes,PetscInt *count[],PetscInt **indices[])
16101bd0b88eSStefano Zampini {
16111bd0b88eSStefano Zampini   PetscFunctionBegin;
16121bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
16131bd0b88eSStefano Zampini   if (nnodes)  *nnodes  = 0;
16141bd0b88eSStefano Zampini   if (count)   *count   = NULL;
16151bd0b88eSStefano Zampini   if (indices) *indices = NULL;
16161bd0b88eSStefano Zampini   PetscFunctionReturn(0);
16171bd0b88eSStefano Zampini }
16181bd0b88eSStefano Zampini 
16191bd0b88eSStefano Zampini /*@C
1620107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
162186994e45SJed Brown 
162286994e45SJed Brown    Not Collective
162386994e45SJed Brown 
162486994e45SJed Brown    Input Arguments:
162586994e45SJed Brown . ltog - local to global mapping
162686994e45SJed Brown 
162786994e45SJed Brown    Output Arguments:
1628565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
162986994e45SJed Brown 
163086994e45SJed Brown    Level: advanced
163186994e45SJed Brown 
163295452b02SPatrick Sanan    Notes:
163395452b02SPatrick Sanan     ISLocalToGlobalMappingGetSize() returns the length the this array
1634107e9a97SBarry Smith 
1635107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
163686994e45SJed Brown @*/
16377087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
163886994e45SJed Brown {
163986994e45SJed Brown   PetscFunctionBegin;
164086994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
164186994e45SJed Brown   PetscValidPointer(array,2);
164245b6f7e9SBarry Smith   if (ltog->bs == 1) {
164386994e45SJed Brown     *array = ltog->indices;
164445b6f7e9SBarry Smith   } else {
164545b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
164645b6f7e9SBarry Smith     const PetscInt *ii;
164745b6f7e9SBarry Smith     PetscErrorCode ierr;
164845b6f7e9SBarry Smith 
164945b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
165045b6f7e9SBarry Smith     *array = jj;
165145b6f7e9SBarry Smith     k    = 0;
165245b6f7e9SBarry Smith     ii   = ltog->indices;
165345b6f7e9SBarry Smith     for (i=0; i<n; i++)
165445b6f7e9SBarry Smith       for (j=0; j<bs; j++)
165545b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
165645b6f7e9SBarry Smith   }
165786994e45SJed Brown   PetscFunctionReturn(0);
165886994e45SJed Brown }
165986994e45SJed Brown 
166086994e45SJed Brown /*@C
1661193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
166286994e45SJed Brown 
166386994e45SJed Brown    Not Collective
166486994e45SJed Brown 
166586994e45SJed Brown    Input Arguments:
166686994e45SJed Brown + ltog - local to global mapping
166786994e45SJed Brown - array - array of indices
166886994e45SJed Brown 
166986994e45SJed Brown    Level: advanced
167086994e45SJed Brown 
167186994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
167286994e45SJed Brown @*/
16737087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
167486994e45SJed Brown {
167586994e45SJed Brown   PetscFunctionBegin;
167686994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
167786994e45SJed Brown   PetscValidPointer(array,2);
167845b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
167945b6f7e9SBarry Smith 
168045b6f7e9SBarry Smith   if (ltog->bs > 1) {
168145b6f7e9SBarry Smith     PetscErrorCode ierr;
168245b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
168345b6f7e9SBarry Smith   }
168445b6f7e9SBarry Smith   PetscFunctionReturn(0);
168545b6f7e9SBarry Smith }
168645b6f7e9SBarry Smith 
168745b6f7e9SBarry Smith /*@C
168845b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
168945b6f7e9SBarry Smith 
169045b6f7e9SBarry Smith    Not Collective
169145b6f7e9SBarry Smith 
169245b6f7e9SBarry Smith    Input Arguments:
169345b6f7e9SBarry Smith . ltog - local to global mapping
169445b6f7e9SBarry Smith 
169545b6f7e9SBarry Smith    Output Arguments:
169645b6f7e9SBarry Smith . array - array of indices
169745b6f7e9SBarry Smith 
169845b6f7e9SBarry Smith    Level: advanced
169945b6f7e9SBarry Smith 
170045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
170145b6f7e9SBarry Smith @*/
170245b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
170345b6f7e9SBarry Smith {
170445b6f7e9SBarry Smith   PetscFunctionBegin;
170545b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
170645b6f7e9SBarry Smith   PetscValidPointer(array,2);
170745b6f7e9SBarry Smith   *array = ltog->indices;
170845b6f7e9SBarry Smith   PetscFunctionReturn(0);
170945b6f7e9SBarry Smith }
171045b6f7e9SBarry Smith 
171145b6f7e9SBarry Smith /*@C
171245b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
171345b6f7e9SBarry Smith 
171445b6f7e9SBarry Smith    Not Collective
171545b6f7e9SBarry Smith 
171645b6f7e9SBarry Smith    Input Arguments:
171745b6f7e9SBarry Smith + ltog - local to global mapping
171845b6f7e9SBarry Smith - array - array of indices
171945b6f7e9SBarry Smith 
172045b6f7e9SBarry Smith    Level: advanced
172145b6f7e9SBarry Smith 
172245b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
172345b6f7e9SBarry Smith @*/
172445b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
172545b6f7e9SBarry Smith {
172645b6f7e9SBarry Smith   PetscFunctionBegin;
172745b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
172845b6f7e9SBarry Smith   PetscValidPointer(array,2);
172986994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
17300298fd71SBarry Smith   *array = NULL;
173186994e45SJed Brown   PetscFunctionReturn(0);
173286994e45SJed Brown }
1733f7efa3c7SJed Brown 
1734f7efa3c7SJed Brown /*@C
1735f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1736f7efa3c7SJed Brown 
1737f7efa3c7SJed Brown    Not Collective
1738f7efa3c7SJed Brown 
1739f7efa3c7SJed Brown    Input Arguments:
1740f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1741f7efa3c7SJed Brown . n - number of mappings to concatenate
1742f7efa3c7SJed Brown - ltogs - local to global mappings
1743f7efa3c7SJed Brown 
1744f7efa3c7SJed Brown    Output Arguments:
1745f7efa3c7SJed Brown . ltogcat - new mapping
1746f7efa3c7SJed Brown 
17479d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
17489d90f715SBarry Smith 
17499d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
17509d90f715SBarry Smith 
1751f7efa3c7SJed Brown    Level: advanced
1752f7efa3c7SJed Brown 
1753f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1754f7efa3c7SJed Brown @*/
1755f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1756f7efa3c7SJed Brown {
1757f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1758f7efa3c7SJed Brown   PetscErrorCode ierr;
1759f7efa3c7SJed Brown 
1760f7efa3c7SJed Brown   PetscFunctionBegin;
1761f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1762f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1763f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1764f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1765f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1766f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1767f7efa3c7SJed Brown     cnt += m;
1768f7efa3c7SJed Brown   }
1769785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1770f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1771f7efa3c7SJed Brown     const PetscInt *subidx;
1772f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1773f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1774580bdb30SBarry Smith     ierr = PetscArraycpy(&idx[cnt],subidx,m);CHKERRQ(ierr);
1775f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1776f7efa3c7SJed Brown     cnt += m;
1777f7efa3c7SJed Brown   }
1778f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1779f7efa3c7SJed Brown   PetscFunctionReturn(0);
1780f7efa3c7SJed Brown }
178104a59952SBarry Smith 
1782413f72f0SBarry Smith /*MC
1783413f72f0SBarry Smith       ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the ISLocalToGlobalMapping object. When ISGlobalToLocalMappingApply() is
1784413f72f0SBarry Smith                                     used this is good for only small and moderate size problems.
1785413f72f0SBarry Smith 
1786413f72f0SBarry Smith    Options Database Keys:
1787a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type basic - select this method
1788413f72f0SBarry Smith 
1789413f72f0SBarry Smith    Level: beginner
1790413f72f0SBarry Smith 
1791413f72f0SBarry Smith .seealso:  ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetType(), ISLOCALTOGLOBALMAPPINGHASH
1792413f72f0SBarry Smith M*/
1793413f72f0SBarry Smith PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)
1794413f72f0SBarry Smith {
1795413f72f0SBarry Smith   PetscFunctionBegin;
1796413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Basic;
1797413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Basic;
1798413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic;
1799413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Basic;
1800413f72f0SBarry Smith   PetscFunctionReturn(0);
1801413f72f0SBarry Smith }
1802413f72f0SBarry Smith 
1803413f72f0SBarry Smith /*MC
1804413f72f0SBarry Smith       ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the ISLocalToGlobalMapping object. When ISGlobalToLocalMappingApply() is
1805ed56e8eaSBarry Smith                                     used this is good for large memory problems.
1806413f72f0SBarry Smith 
1807413f72f0SBarry Smith    Options Database Keys:
1808a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type hash - select this method
1809413f72f0SBarry Smith 
1810ed56e8eaSBarry Smith 
181195452b02SPatrick Sanan    Notes:
181295452b02SPatrick Sanan     This is selected automatically for large problems if the user does not set the type.
1813ed56e8eaSBarry Smith 
1814413f72f0SBarry Smith    Level: beginner
1815413f72f0SBarry Smith 
1816413f72f0SBarry Smith .seealso:  ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetType(), ISLOCALTOGLOBALMAPPINGHASH
1817413f72f0SBarry Smith M*/
1818413f72f0SBarry Smith PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)
1819413f72f0SBarry Smith {
1820413f72f0SBarry Smith   PetscFunctionBegin;
1821413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Hash;
1822413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Hash;
1823413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash;
1824413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Hash;
1825413f72f0SBarry Smith   PetscFunctionReturn(0);
1826413f72f0SBarry Smith }
1827413f72f0SBarry Smith 
1828413f72f0SBarry Smith 
1829413f72f0SBarry Smith /*@C
1830413f72f0SBarry Smith     ISLocalToGlobalMappingRegister -  Adds a method for applying a global to local mapping with an ISLocalToGlobalMapping
1831413f72f0SBarry Smith 
1832413f72f0SBarry Smith    Not Collective
1833413f72f0SBarry Smith 
1834413f72f0SBarry Smith    Input Parameters:
1835413f72f0SBarry Smith +  sname - name of a new method
1836413f72f0SBarry Smith -  routine_create - routine to create method context
1837413f72f0SBarry Smith 
1838413f72f0SBarry Smith    Notes:
1839ed56e8eaSBarry Smith    ISLocalToGlobalMappingRegister() may be called multiple times to add several user-defined mappings.
1840413f72f0SBarry Smith 
1841413f72f0SBarry Smith    Sample usage:
1842413f72f0SBarry Smith .vb
1843413f72f0SBarry Smith    ISLocalToGlobalMappingRegister("my_mapper",MyCreate);
1844413f72f0SBarry Smith .ve
1845413f72f0SBarry Smith 
1846ed56e8eaSBarry Smith    Then, your mapping can be chosen with the procedural interface via
1847413f72f0SBarry Smith $     ISLocalToGlobalMappingSetType(ltog,"my_mapper")
1848413f72f0SBarry Smith    or at runtime via the option
1849ed56e8eaSBarry Smith $     -islocaltoglobalmapping_type my_mapper
1850413f72f0SBarry Smith 
1851413f72f0SBarry Smith    Level: advanced
1852413f72f0SBarry Smith 
1853413f72f0SBarry Smith .seealso: ISLocalToGlobalMappingRegisterAll(), ISLocalToGlobalMappingRegisterDestroy(), ISLOCALTOGLOBALMAPPINGBASIC, ISLOCALTOGLOBALMAPPINGHASH
1854413f72f0SBarry Smith 
1855413f72f0SBarry Smith @*/
1856413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRegister(const char sname[],PetscErrorCode (*function)(ISLocalToGlobalMapping))
1857413f72f0SBarry Smith {
1858413f72f0SBarry Smith   PetscErrorCode ierr;
1859413f72f0SBarry Smith 
1860413f72f0SBarry Smith   PetscFunctionBegin;
18611d36bdfdSBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
1862413f72f0SBarry Smith   ierr = PetscFunctionListAdd(&ISLocalToGlobalMappingList,sname,function);CHKERRQ(ierr);
1863413f72f0SBarry Smith   PetscFunctionReturn(0);
1864413f72f0SBarry Smith }
1865413f72f0SBarry Smith 
1866413f72f0SBarry Smith /*@C
1867ed56e8eaSBarry Smith    ISLocalToGlobalMappingSetType - Builds ISLocalToGlobalMapping for a particular global to local mapping approach.
1868413f72f0SBarry Smith 
1869413f72f0SBarry Smith    Logically Collective on ISLocalToGlobalMapping
1870413f72f0SBarry Smith 
1871413f72f0SBarry Smith    Input Parameters:
1872413f72f0SBarry Smith +  ltog - the ISLocalToGlobalMapping object
1873413f72f0SBarry Smith -  type - a known method
1874413f72f0SBarry Smith 
1875413f72f0SBarry Smith    Options Database Key:
1876ed56e8eaSBarry Smith .  -islocaltoglobalmapping_type  <method> - Sets the method; use -help for a list
1877413f72f0SBarry Smith     of available methods (for instance, basic or hash)
1878413f72f0SBarry Smith 
1879413f72f0SBarry Smith    Notes:
1880413f72f0SBarry Smith    See "petsc/include/petscis.h" for available methods
1881413f72f0SBarry Smith 
1882413f72f0SBarry Smith   Normally, it is best to use the ISLocalToGlobalMappingSetFromOptions() command and
1883413f72f0SBarry Smith   then set the ISLocalToGlobalMapping type from the options database rather than by using
1884413f72f0SBarry Smith   this routine.
1885413f72f0SBarry Smith 
1886413f72f0SBarry Smith   Level: intermediate
1887413f72f0SBarry Smith 
1888413f72f0SBarry Smith   Developer Note: ISLocalToGlobalMappingRegister() is used to add new types to ISLocalToGlobalMappingList from which they
1889413f72f0SBarry Smith   are accessed by ISLocalToGlobalMappingSetType().
1890413f72f0SBarry Smith 
1891413f72f0SBarry Smith .seealso: PCSetType(), ISLocalToGlobalMappingType, ISLocalToGlobalMappingRegister(), ISLocalToGlobalMappingCreate()
1892413f72f0SBarry Smith 
1893413f72f0SBarry Smith @*/
1894413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type)
1895413f72f0SBarry Smith {
1896413f72f0SBarry Smith   PetscErrorCode ierr,(*r)(ISLocalToGlobalMapping);
1897413f72f0SBarry Smith   PetscBool      match;
1898413f72f0SBarry Smith 
1899413f72f0SBarry Smith   PetscFunctionBegin;
1900413f72f0SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
1901413f72f0SBarry Smith   PetscValidCharPointer(type,2);
1902413f72f0SBarry Smith 
1903413f72f0SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)ltog,type,&match);CHKERRQ(ierr);
1904413f72f0SBarry Smith   if (match) PetscFunctionReturn(0);
1905413f72f0SBarry Smith 
1906413f72f0SBarry Smith   ierr =  PetscFunctionListFind(ISLocalToGlobalMappingList,type,&r);CHKERRQ(ierr);
1907413f72f0SBarry Smith   if (!r) SETERRQ1(PetscObjectComm((PetscObject)ltog),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested ISLocalToGlobalMapping type %s",type);
1908413f72f0SBarry Smith   /* Destroy the previous private LTOG context */
1909413f72f0SBarry Smith   if (ltog->ops->destroy) {
1910413f72f0SBarry Smith     ierr              = (*ltog->ops->destroy)(ltog);CHKERRQ(ierr);
1911413f72f0SBarry Smith     ltog->ops->destroy = NULL;
1912413f72f0SBarry Smith   }
1913413f72f0SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)ltog,type);CHKERRQ(ierr);
1914413f72f0SBarry Smith   ierr = (*r)(ltog);CHKERRQ(ierr);
1915413f72f0SBarry Smith   PetscFunctionReturn(0);
1916413f72f0SBarry Smith }
1917413f72f0SBarry Smith 
1918413f72f0SBarry Smith PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE;
1919413f72f0SBarry Smith 
1920413f72f0SBarry Smith /*@C
1921413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the IS package.
1922413f72f0SBarry Smith 
1923413f72f0SBarry Smith   Not Collective
1924413f72f0SBarry Smith 
1925413f72f0SBarry Smith   Level: advanced
1926413f72f0SBarry Smith 
1927413f72f0SBarry Smith .seealso:  ISRegister(),  ISLocalToGlobalRegister()
1928413f72f0SBarry Smith @*/
1929413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRegisterAll(void)
1930413f72f0SBarry Smith {
1931413f72f0SBarry Smith   PetscErrorCode ierr;
1932413f72f0SBarry Smith 
1933413f72f0SBarry Smith   PetscFunctionBegin;
1934413f72f0SBarry Smith   if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(0);
1935413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE;
1936413f72f0SBarry Smith 
1937413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic);CHKERRQ(ierr);
1938413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash);CHKERRQ(ierr);
1939413f72f0SBarry Smith   PetscFunctionReturn(0);
1940413f72f0SBarry Smith }
194104a59952SBarry Smith 
1942