xref: /petsc/src/vec/is/utils/isltog.c (revision d8d19677bbccf95218448bee62e6b87f4513e133)
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 
186528b96dSMatthew G. Knepley /*@C
196528b96dSMatthew G. Knepley   ISGetPointRange - Returns a description of the points in an IS suitable for traversal
20413f72f0SBarry Smith 
216528b96dSMatthew G. Knepley   Not collective
226528b96dSMatthew G. Knepley 
236528b96dSMatthew G. Knepley   Input Parameter:
246528b96dSMatthew G. Knepley . pointIS - The IS object
256528b96dSMatthew G. Knepley 
266528b96dSMatthew G. Knepley   Output Parameters:
276528b96dSMatthew G. Knepley + pStart - The first index, see notes
286528b96dSMatthew G. Knepley . pEnd   - One past the last index, see notes
296528b96dSMatthew G. Knepley - points - The indices, see notes
306528b96dSMatthew G. Knepley 
316528b96dSMatthew G. Knepley   Notes:
326528b96dSMatthew G. Knepley   If the IS contains contiguous indices in an ISSTRIDE, then the indices are contained in [pStart, pEnd) and points = NULL. Otherwise, pStart = 0, pEnd = numIndices, and points is an array of the indices. This supports the following pattern
336528b96dSMatthew G. Knepley $ ISGetPointRange(is, &pStart, &pEnd, &points);
346528b96dSMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) {
356528b96dSMatthew G. Knepley $   const PetscInt point = points ? points[p] : p;
366528b96dSMatthew G. Knepley $ }
376528b96dSMatthew G. Knepley $ ISRestorePointRange(is, &pstart, &pEnd, &points);
386528b96dSMatthew G. Knepley 
396528b96dSMatthew G. Knepley   Level: intermediate
406528b96dSMatthew G. Knepley 
416528b96dSMatthew G. Knepley .seealso: ISRestorePointRange(), ISGetPointSubrange(), ISGetIndices(), ISCreateStride()
426528b96dSMatthew G. Knepley @*/
439305a4c7SMatthew G. Knepley PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
449305a4c7SMatthew G. Knepley {
459305a4c7SMatthew G. Knepley   PetscInt       numCells, step = 1;
469305a4c7SMatthew G. Knepley   PetscBool      isStride;
479305a4c7SMatthew G. Knepley   PetscErrorCode ierr;
489305a4c7SMatthew G. Knepley 
499305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
509305a4c7SMatthew G. Knepley   *pStart = 0;
519305a4c7SMatthew G. Knepley   *points = NULL;
529305a4c7SMatthew G. Knepley   ierr = ISGetLocalSize(pointIS, &numCells);CHKERRQ(ierr);
539305a4c7SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr);
549305a4c7SMatthew G. Knepley   if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);}
559305a4c7SMatthew G. Knepley   *pEnd   = *pStart + numCells;
569305a4c7SMatthew G. Knepley   if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);}
579305a4c7SMatthew G. Knepley   PetscFunctionReturn(0);
589305a4c7SMatthew G. Knepley }
599305a4c7SMatthew G. Knepley 
606528b96dSMatthew G. Knepley /*@C
616528b96dSMatthew G. Knepley   ISRestorePointRange - Destroys the traversal description
626528b96dSMatthew G. Knepley 
636528b96dSMatthew G. Knepley   Not collective
646528b96dSMatthew G. Knepley 
656528b96dSMatthew G. Knepley   Input Parameters:
666528b96dSMatthew G. Knepley + pointIS - The IS object
676528b96dSMatthew G. Knepley . pStart  - The first index, from ISGetPointRange()
686528b96dSMatthew G. Knepley . pEnd    - One past the last index, from ISGetPointRange()
696528b96dSMatthew G. Knepley - points  - The indices, from ISGetPointRange()
706528b96dSMatthew G. Knepley 
716528b96dSMatthew G. Knepley   Notes:
726528b96dSMatthew G. Knepley   If the IS contains contiguous indices in an ISSTRIDE, then the indices are contained in [pStart, pEnd) and points = NULL. Otherwise, pStart = 0, pEnd = numIndices, and points is an array of the indices. This supports the following pattern
736528b96dSMatthew G. Knepley $ ISGetPointRange(is, &pStart, &pEnd, &points);
746528b96dSMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) {
756528b96dSMatthew G. Knepley $   const PetscInt point = points ? points[p] : p;
766528b96dSMatthew G. Knepley $ }
776528b96dSMatthew G. Knepley $ ISRestorePointRange(is, &pstart, &pEnd, &points);
786528b96dSMatthew G. Knepley 
796528b96dSMatthew G. Knepley   Level: intermediate
806528b96dSMatthew G. Knepley 
816528b96dSMatthew G. Knepley .seealso: ISGetPointRange(), ISGetPointSubrange(), ISGetIndices(), ISCreateStride()
826528b96dSMatthew G. Knepley @*/
839305a4c7SMatthew G. Knepley PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
849305a4c7SMatthew G. Knepley {
859305a4c7SMatthew G. Knepley   PetscInt       step = 1;
869305a4c7SMatthew G. Knepley   PetscBool      isStride;
879305a4c7SMatthew G. Knepley   PetscErrorCode ierr;
889305a4c7SMatthew G. Knepley 
899305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
909305a4c7SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr);
919305a4c7SMatthew G. Knepley   if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);}
929305a4c7SMatthew G. Knepley   if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);}
939305a4c7SMatthew G. Knepley   PetscFunctionReturn(0);
949305a4c7SMatthew G. Knepley }
959305a4c7SMatthew G. Knepley 
966528b96dSMatthew G. Knepley /*@C
976528b96dSMatthew G. Knepley   ISGetPointSubrange - Configures the input IS to be a subrange for the traversal information given
986528b96dSMatthew G. Knepley 
996528b96dSMatthew G. Knepley   Not collective
1006528b96dSMatthew G. Knepley 
1016528b96dSMatthew G. Knepley   Input Parameters:
1026528b96dSMatthew G. Knepley + subpointIS - The IS object to be configured
1036528b96dSMatthew G. Knepley . pStar   t  - The first index of the subrange
1046528b96dSMatthew G. Knepley . pEnd       - One past the last index for the subrange
1056528b96dSMatthew G. Knepley - points     - The indices for the entire range, from ISGetPointRange()
1066528b96dSMatthew G. Knepley 
1076528b96dSMatthew G. Knepley   Output Parameters:
1086528b96dSMatthew G. Knepley . subpointIS - The IS object now configured to be a subrange
1096528b96dSMatthew G. Knepley 
1106528b96dSMatthew G. Knepley   Notes:
1116528b96dSMatthew G. Knepley   The input IS will now respond properly to calls to ISGetPointRange() and return the subrange.
1126528b96dSMatthew G. Knepley 
1136528b96dSMatthew G. Knepley   Level: intermediate
1146528b96dSMatthew G. Knepley 
1156528b96dSMatthew G. Knepley .seealso: ISGetPointRange(), ISRestorePointRange(), ISGetIndices(), ISCreateStride()
1166528b96dSMatthew G. Knepley @*/
1179305a4c7SMatthew G. Knepley PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points)
1189305a4c7SMatthew G. Knepley {
1199305a4c7SMatthew G. Knepley   PetscErrorCode ierr;
1209305a4c7SMatthew G. Knepley 
1219305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
1229305a4c7SMatthew G. Knepley   if (points) {
1239305a4c7SMatthew G. Knepley     ierr = ISSetType(subpointIS, ISGENERAL);CHKERRQ(ierr);
1249305a4c7SMatthew G. Knepley     ierr = ISGeneralSetIndices(subpointIS, pEnd-pStart, &points[pStart], PETSC_USE_POINTER);CHKERRQ(ierr);
1259305a4c7SMatthew G. Knepley   } else {
1269305a4c7SMatthew G. Knepley     ierr = ISSetType(subpointIS, ISSTRIDE);CHKERRQ(ierr);
1279305a4c7SMatthew G. Knepley     ierr = ISStrideSetStride(subpointIS, pEnd-pStart, pStart, 1);CHKERRQ(ierr);
1289305a4c7SMatthew G. Knepley   }
1299305a4c7SMatthew G. Knepley   PetscFunctionReturn(0);
1309305a4c7SMatthew G. Knepley }
1319305a4c7SMatthew G. Knepley 
132413f72f0SBarry Smith /* -----------------------------------------------------------------------------------------*/
133413f72f0SBarry Smith 
134413f72f0SBarry Smith /*
135413f72f0SBarry Smith     Creates the global mapping information in the ISLocalToGlobalMapping structure
136413f72f0SBarry Smith 
137413f72f0SBarry Smith     If the user has not selected how to handle the global to local mapping then use HASH for "large" problems
138413f72f0SBarry Smith */
139413f72f0SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping)
140413f72f0SBarry Smith {
141413f72f0SBarry Smith   PetscInt       i,*idx = mapping->indices,n = mapping->n,end,start;
142413f72f0SBarry Smith   PetscErrorCode ierr;
143413f72f0SBarry Smith 
144413f72f0SBarry Smith   PetscFunctionBegin;
145413f72f0SBarry Smith   if (mapping->data) PetscFunctionReturn(0);
146413f72f0SBarry Smith   end   = 0;
147413f72f0SBarry Smith   start = PETSC_MAX_INT;
148413f72f0SBarry Smith 
149413f72f0SBarry Smith   for (i=0; i<n; i++) {
150413f72f0SBarry Smith     if (idx[i] < 0) continue;
151413f72f0SBarry Smith     if (idx[i] < start) start = idx[i];
152413f72f0SBarry Smith     if (idx[i] > end)   end   = idx[i];
153413f72f0SBarry Smith   }
154413f72f0SBarry Smith   if (start > end) {start = 0; end = -1;}
155413f72f0SBarry Smith   mapping->globalstart = start;
156413f72f0SBarry Smith   mapping->globalend   = end;
157413f72f0SBarry Smith   if (!((PetscObject)mapping)->type_name) {
158413f72f0SBarry Smith     if ((end - start) > PetscMax(4*n,1000000)) {
1597f79407eSBarry Smith       ierr = ISLocalToGlobalMappingSetType(mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
160413f72f0SBarry Smith     } else {
1617f79407eSBarry Smith       ierr = ISLocalToGlobalMappingSetType(mapping,ISLOCALTOGLOBALMAPPINGBASIC);CHKERRQ(ierr);
162413f72f0SBarry Smith     }
163413f72f0SBarry Smith   }
164413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingsetup)(mapping);CHKERRQ(ierr);
165413f72f0SBarry Smith   PetscFunctionReturn(0);
166413f72f0SBarry Smith }
167413f72f0SBarry Smith 
168413f72f0SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping)
169413f72f0SBarry Smith {
170413f72f0SBarry Smith   PetscErrorCode              ierr;
171413f72f0SBarry Smith   PetscInt                    i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
172413f72f0SBarry Smith   ISLocalToGlobalMapping_Basic *map;
173413f72f0SBarry Smith 
174413f72f0SBarry Smith   PetscFunctionBegin;
175413f72f0SBarry Smith   start            = mapping->globalstart;
176413f72f0SBarry Smith   end              = mapping->globalend;
177413f72f0SBarry Smith   ierr             = PetscNew(&map);CHKERRQ(ierr);
178413f72f0SBarry Smith   ierr             = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr);
179413f72f0SBarry Smith   map->globals     = globals;
180413f72f0SBarry Smith   for (i=0; i<end-start+1; i++) globals[i] = -1;
181413f72f0SBarry Smith   for (i=0; i<n; i++) {
182413f72f0SBarry Smith     if (idx[i] < 0) continue;
183413f72f0SBarry Smith     globals[idx[i] - start] = i;
184413f72f0SBarry Smith   }
185413f72f0SBarry Smith   mapping->data = (void*)map;
186413f72f0SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr);
187413f72f0SBarry Smith   PetscFunctionReturn(0);
188413f72f0SBarry Smith }
189413f72f0SBarry Smith 
190413f72f0SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping)
191413f72f0SBarry Smith {
192413f72f0SBarry Smith   PetscErrorCode              ierr;
193413f72f0SBarry Smith   PetscInt                    i,*idx = mapping->indices,n = mapping->n;
194413f72f0SBarry Smith   ISLocalToGlobalMapping_Hash *map;
195413f72f0SBarry Smith 
196413f72f0SBarry Smith   PetscFunctionBegin;
197413f72f0SBarry Smith   ierr = PetscNew(&map);CHKERRQ(ierr);
198e8f14785SLisandro Dalcin   ierr = PetscHMapICreate(&map->globalht);CHKERRQ(ierr);
199413f72f0SBarry Smith   for (i=0; i<n; i++) {
200413f72f0SBarry Smith     if (idx[i] < 0) continue;
201e8f14785SLisandro Dalcin     ierr = PetscHMapISet(map->globalht,idx[i],i);CHKERRQ(ierr);
202413f72f0SBarry Smith   }
203413f72f0SBarry Smith   mapping->data = (void*)map;
204413f72f0SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)mapping,2*n*sizeof(PetscInt));CHKERRQ(ierr);
205413f72f0SBarry Smith   PetscFunctionReturn(0);
206413f72f0SBarry Smith }
207413f72f0SBarry Smith 
208413f72f0SBarry Smith static PetscErrorCode ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping)
209413f72f0SBarry Smith {
210413f72f0SBarry Smith   PetscErrorCode              ierr;
211413f72f0SBarry Smith   ISLocalToGlobalMapping_Basic *map  = (ISLocalToGlobalMapping_Basic *)mapping->data;
212413f72f0SBarry Smith 
213413f72f0SBarry Smith   PetscFunctionBegin;
214413f72f0SBarry Smith   if (!map) PetscFunctionReturn(0);
215413f72f0SBarry Smith   ierr = PetscFree(map->globals);CHKERRQ(ierr);
216413f72f0SBarry Smith   ierr = PetscFree(mapping->data);CHKERRQ(ierr);
217413f72f0SBarry Smith   PetscFunctionReturn(0);
218413f72f0SBarry Smith }
219413f72f0SBarry Smith 
220413f72f0SBarry Smith static PetscErrorCode ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping)
221413f72f0SBarry Smith {
222413f72f0SBarry Smith   PetscErrorCode              ierr;
223413f72f0SBarry Smith   ISLocalToGlobalMapping_Hash *map  = (ISLocalToGlobalMapping_Hash*)mapping->data;
224413f72f0SBarry Smith 
225413f72f0SBarry Smith   PetscFunctionBegin;
226413f72f0SBarry Smith   if (!map) PetscFunctionReturn(0);
227e8f14785SLisandro Dalcin   ierr = PetscHMapIDestroy(&map->globalht);CHKERRQ(ierr);
228413f72f0SBarry Smith   ierr = PetscFree(mapping->data);CHKERRQ(ierr);
229413f72f0SBarry Smith   PetscFunctionReturn(0);
230413f72f0SBarry Smith }
231413f72f0SBarry Smith 
232413f72f0SBarry Smith #define GTOLTYPE _Basic
233413f72f0SBarry Smith #define GTOLNAME _Basic
234541bf97eSAdrian Croucher #define GTOLBS mapping->bs
235413f72f0SBarry Smith #define GTOL(g, local) do {                  \
236413f72f0SBarry Smith     local = map->globals[g/bs - start];      \
2370040bde1SJunchao Zhang     if (local >= 0) local = bs*local + (g % bs); \
238413f72f0SBarry Smith   } while (0)
239541bf97eSAdrian Croucher 
240413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
241413f72f0SBarry Smith 
242413f72f0SBarry Smith #define GTOLTYPE _Basic
243413f72f0SBarry Smith #define GTOLNAME Block_Basic
244541bf97eSAdrian Croucher #define GTOLBS 1
245413f72f0SBarry Smith #define GTOL(g, local) do {                  \
246413f72f0SBarry Smith     local = map->globals[g - start];         \
247413f72f0SBarry Smith   } while (0)
248413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
249413f72f0SBarry Smith 
250413f72f0SBarry Smith #define GTOLTYPE _Hash
251413f72f0SBarry Smith #define GTOLNAME _Hash
252541bf97eSAdrian Croucher #define GTOLBS mapping->bs
253413f72f0SBarry Smith #define GTOL(g, local) do {                         \
254e8f14785SLisandro Dalcin     (void)PetscHMapIGet(map->globalht,g/bs,&local); \
2550040bde1SJunchao Zhang     if (local >= 0) local = bs*local + (g % bs);   \
256413f72f0SBarry Smith    } while (0)
257413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
258413f72f0SBarry Smith 
259413f72f0SBarry Smith #define GTOLTYPE _Hash
260413f72f0SBarry Smith #define GTOLNAME Block_Hash
261541bf97eSAdrian Croucher #define GTOLBS 1
262413f72f0SBarry Smith #define GTOL(g, local) do {                         \
263e8f14785SLisandro Dalcin     (void)PetscHMapIGet(map->globalht,g,&local);    \
264413f72f0SBarry Smith   } while (0)
265413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
266413f72f0SBarry Smith 
2676658fb44Sstefano_zampini /*@
2686658fb44Sstefano_zampini     ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
2696658fb44Sstefano_zampini 
2706658fb44Sstefano_zampini     Not Collective
2716658fb44Sstefano_zampini 
2726658fb44Sstefano_zampini     Input Parameter:
2736658fb44Sstefano_zampini .   ltog - local to global mapping
2746658fb44Sstefano_zampini 
2756658fb44Sstefano_zampini     Output Parameter:
2766658fb44Sstefano_zampini .   nltog - the duplicated local to global mapping
2776658fb44Sstefano_zampini 
2786658fb44Sstefano_zampini     Level: advanced
2796658fb44Sstefano_zampini 
2806658fb44Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
2816658fb44Sstefano_zampini @*/
2826658fb44Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping* nltog)
2836658fb44Sstefano_zampini {
2846658fb44Sstefano_zampini   PetscErrorCode ierr;
2856658fb44Sstefano_zampini 
2866658fb44Sstefano_zampini   PetscFunctionBegin;
2876658fb44Sstefano_zampini   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
2886658fb44Sstefano_zampini   ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog),ltog->bs,ltog->n,ltog->indices,PETSC_COPY_VALUES,nltog);CHKERRQ(ierr);
2896658fb44Sstefano_zampini   PetscFunctionReturn(0);
2906658fb44Sstefano_zampini }
2916658fb44Sstefano_zampini 
292565245c5SBarry Smith /*@
293107e9a97SBarry Smith     ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
2943b9aefa3SBarry Smith 
2953b9aefa3SBarry Smith     Not Collective
2963b9aefa3SBarry Smith 
2973b9aefa3SBarry Smith     Input Parameter:
2983b9aefa3SBarry Smith .   ltog - local to global mapping
2993b9aefa3SBarry Smith 
3003b9aefa3SBarry Smith     Output Parameter:
301107e9a97SBarry Smith .   n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length
3023b9aefa3SBarry Smith 
3033b9aefa3SBarry Smith     Level: advanced
3043b9aefa3SBarry Smith 
3053b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
3063b9aefa3SBarry Smith @*/
3077087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n)
3083b9aefa3SBarry Smith {
3093b9aefa3SBarry Smith   PetscFunctionBegin;
3100700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3114482741eSBarry Smith   PetscValidIntPointer(n,2);
312107e9a97SBarry Smith   *n = mapping->bs*mapping->n;
3133b9aefa3SBarry Smith   PetscFunctionReturn(0);
3143b9aefa3SBarry Smith }
3153b9aefa3SBarry Smith 
3165a5d4f66SBarry Smith /*@C
317fe2efc57SMark    ISLocalToGlobalMappingViewFromOptions - View from Options
318fe2efc57SMark 
319fe2efc57SMark    Collective on ISLocalToGlobalMapping
320fe2efc57SMark 
321fe2efc57SMark    Input Parameters:
322fe2efc57SMark +  A - the local to global mapping object
323736c3998SJose E. Roman .  obj - Optional object
324736c3998SJose E. Roman -  name - command line option
325fe2efc57SMark 
326fe2efc57SMark    Level: intermediate
327fe2efc57SMark .seealso:  ISLocalToGlobalMapping, ISLocalToGlobalMappingView, PetscObjectViewFromOptions(), ISLocalToGlobalMappingCreate()
328fe2efc57SMark @*/
329fe2efc57SMark PetscErrorCode  ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A,PetscObject obj,const char name[])
330fe2efc57SMark {
331fe2efc57SMark   PetscErrorCode ierr;
332fe2efc57SMark 
333fe2efc57SMark   PetscFunctionBegin;
334fe2efc57SMark   PetscValidHeaderSpecific(A,IS_LTOGM_CLASSID,1);
335fe2efc57SMark   ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr);
336fe2efc57SMark   PetscFunctionReturn(0);
337fe2efc57SMark }
338fe2efc57SMark 
339fe2efc57SMark /*@C
3405a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
3415a5d4f66SBarry Smith 
342b9cd556bSLois Curfman McInnes     Not Collective
343b9cd556bSLois Curfman McInnes 
3445a5d4f66SBarry Smith     Input Parameters:
3453b9aefa3SBarry Smith +   ltog - local to global mapping
3463b9aefa3SBarry Smith -   viewer - viewer
3475a5d4f66SBarry Smith 
348a997ad1aSLois Curfman McInnes     Level: advanced
349a997ad1aSLois Curfman McInnes 
3505a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
3515a5d4f66SBarry Smith @*/
3527087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)
3535a5d4f66SBarry Smith {
35432dcc486SBarry Smith   PetscInt       i;
35532dcc486SBarry Smith   PetscMPIInt    rank;
356ace3abfcSBarry Smith   PetscBool      iascii;
3576849ba73SBarry Smith   PetscErrorCode ierr;
3585a5d4f66SBarry Smith 
3595a5d4f66SBarry Smith   PetscFunctionBegin;
3600700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
3613050cee2SBarry Smith   if (!viewer) {
362ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr);
3633050cee2SBarry Smith   }
3640700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3655a5d4f66SBarry Smith 
366ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRMPI(ierr);
367251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
36832077d6dSBarry Smith   if (iascii) {
36998c3331eSBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr);
3701575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
3715a5d4f66SBarry Smith     for (i=0; i<mapping->n; i++) {
3727904a332SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr);
3736831982aSBarry Smith     }
374b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3751575c14dSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
3761575c14dSBarry Smith   }
3775a5d4f66SBarry Smith   PetscFunctionReturn(0);
3785a5d4f66SBarry Smith }
3795a5d4f66SBarry Smith 
3801f428162SBarry Smith /*@
3812bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
3822bdab257SBarry Smith     ordering and a global parallel ordering.
3832bdab257SBarry Smith 
3840f5bd95cSBarry Smith     Not collective
385b9cd556bSLois Curfman McInnes 
386a997ad1aSLois Curfman McInnes     Input Parameter:
3878c03b21aSDmitry Karpeev .   is - index set containing the global numbers for each local number
3882bdab257SBarry Smith 
389a997ad1aSLois Curfman McInnes     Output Parameter:
3902bdab257SBarry Smith .   mapping - new mapping data structure
3912bdab257SBarry Smith 
39295452b02SPatrick Sanan     Notes:
39395452b02SPatrick Sanan     the block size of the IS determines the block size of the mapping
394a997ad1aSLois Curfman McInnes     Level: advanced
395a997ad1aSLois Curfman McInnes 
3967e99dc12SLawrence Mitchell .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetFromOptions()
3972bdab257SBarry Smith @*/
3987087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
3992bdab257SBarry Smith {
4006849ba73SBarry Smith   PetscErrorCode ierr;
4013bbf0e92SBarry Smith   PetscInt       n,bs;
4025d0c19d7SBarry Smith   const PetscInt *indices;
4032bdab257SBarry Smith   MPI_Comm       comm;
4043bbf0e92SBarry Smith   PetscBool      isblock;
4053a40ed3dSBarry Smith 
4063a40ed3dSBarry Smith   PetscFunctionBegin;
4070700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,1);
4084482741eSBarry Smith   PetscValidPointer(mapping,2);
4092bdab257SBarry Smith 
4102bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
4113b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
4123bbf0e92SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr);
4136006e8d2SBarry Smith   if (!isblock) {
414f0413b6fSBarry Smith     ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
415f0413b6fSBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
4162bdab257SBarry Smith     ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
4176006e8d2SBarry Smith   } else {
4186006e8d2SBarry Smith     ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr);
419f0413b6fSBarry Smith     ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr);
42028bc9809SBarry Smith     ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr);
421f0413b6fSBarry Smith     ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr);
4226006e8d2SBarry Smith   }
4233a40ed3dSBarry Smith   PetscFunctionReturn(0);
4242bdab257SBarry Smith }
4255a5d4f66SBarry Smith 
426a4d96a55SJed Brown /*@C
427a4d96a55SJed Brown     ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
428a4d96a55SJed Brown     ordering and a global parallel ordering.
429a4d96a55SJed Brown 
430a4d96a55SJed Brown     Collective
431a4d96a55SJed Brown 
432*d8d19677SJose E. Roman     Input Parameters:
433a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
434a4d96a55SJed Brown -   start - first global index on this process
435a4d96a55SJed Brown 
436a4d96a55SJed Brown     Output Parameter:
437a4d96a55SJed Brown .   mapping - new mapping data structure
438a4d96a55SJed Brown 
439a4d96a55SJed Brown     Level: advanced
440a4d96a55SJed Brown 
4417e99dc12SLawrence Mitchell .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingSetFromOptions()
442a4d96a55SJed Brown @*/
443a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
444a4d96a55SJed Brown {
445a4d96a55SJed Brown   PetscErrorCode ierr;
446a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
447a4d96a55SJed Brown   const PetscInt *ilocal;
448a4d96a55SJed Brown   MPI_Comm       comm;
449a4d96a55SJed Brown 
450a4d96a55SJed Brown   PetscFunctionBegin;
451a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
452a4d96a55SJed Brown   PetscValidPointer(mapping,3);
453a4d96a55SJed Brown 
454a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
4550298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
456f6e5521dSKarl Rupp   if (ilocal) {
457f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
458f6e5521dSKarl Rupp   }
459a4d96a55SJed Brown   else maxlocal = nleaves;
460785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
461785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
462a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
463a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
464ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog,MPI_REPLACE);CHKERRQ(ierr);
465ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog,MPI_REPLACE);CHKERRQ(ierr);
466f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
467a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
468a4d96a55SJed Brown   PetscFunctionReturn(0);
469a4d96a55SJed Brown }
470b46b645bSBarry Smith 
47163fa5c83Sstefano_zampini /*@
47263fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
47363fa5c83Sstefano_zampini 
47463fa5c83Sstefano_zampini     Not collective
47563fa5c83Sstefano_zampini 
47663fa5c83Sstefano_zampini     Input Parameters:
477a2b725a8SWilliam Gropp +   mapping - mapping data structure
478a2b725a8SWilliam Gropp -   bs - the blocksize
47963fa5c83Sstefano_zampini 
48063fa5c83Sstefano_zampini     Level: advanced
48163fa5c83Sstefano_zampini 
48263fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
48363fa5c83Sstefano_zampini @*/
48463fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
48563fa5c83Sstefano_zampini {
486a59f3c4dSstefano_zampini   PetscInt       *nid;
487a59f3c4dSstefano_zampini   const PetscInt *oid;
488a59f3c4dSstefano_zampini   PetscInt       i,cn,on,obs,nn;
48963fa5c83Sstefano_zampini   PetscErrorCode ierr;
49063fa5c83Sstefano_zampini 
49163fa5c83Sstefano_zampini   PetscFunctionBegin;
49263fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
49363fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
49463fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
49563fa5c83Sstefano_zampini   on  = mapping->n;
49663fa5c83Sstefano_zampini   obs = mapping->bs;
49763fa5c83Sstefano_zampini   oid = mapping->indices;
49863fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
49963fa5c83Sstefano_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);
500a59f3c4dSstefano_zampini 
50163fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
502a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingGetIndices(mapping,&oid);CHKERRQ(ierr);
503a59f3c4dSstefano_zampini   for (i=0;i<nn;i++) {
504a59f3c4dSstefano_zampini     PetscInt j;
505a59f3c4dSstefano_zampini     for (j=0,cn=0;j<bs-1;j++) {
506a59f3c4dSstefano_zampini       if (oid[i*bs+j] < 0) { cn++; continue; }
507a59f3c4dSstefano_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]);
508a59f3c4dSstefano_zampini     }
509a59f3c4dSstefano_zampini     if (oid[i*bs+j] < 0) cn++;
5108b7cb0e6Sstefano_zampini     if (cn) {
511a59f3c4dSstefano_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);
512a59f3c4dSstefano_zampini       nid[i] = -1;
5138b7cb0e6Sstefano_zampini     } else {
514a59f3c4dSstefano_zampini       nid[i] = oid[i*bs]/bs;
51563fa5c83Sstefano_zampini     }
51663fa5c83Sstefano_zampini   }
517a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(mapping,&oid);CHKERRQ(ierr);
518a59f3c4dSstefano_zampini 
51963fa5c83Sstefano_zampini   mapping->n           = nn;
52063fa5c83Sstefano_zampini   mapping->bs          = bs;
52163fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
52263fa5c83Sstefano_zampini   mapping->indices     = nid;
523c9345713Sstefano_zampini   mapping->globalstart = 0;
524c9345713Sstefano_zampini   mapping->globalend   = 0;
5251bd0b88eSStefano Zampini 
5261bd0b88eSStefano Zampini   /* reset the cached information */
5271bd0b88eSStefano Zampini   ierr = PetscFree(mapping->info_procs);CHKERRQ(ierr);
5281bd0b88eSStefano Zampini   ierr = PetscFree(mapping->info_numprocs);CHKERRQ(ierr);
5291bd0b88eSStefano Zampini   if (mapping->info_indices) {
5301bd0b88eSStefano Zampini     PetscInt i;
5311bd0b88eSStefano Zampini 
5321bd0b88eSStefano Zampini     ierr = PetscFree((mapping->info_indices)[0]);CHKERRQ(ierr);
5331bd0b88eSStefano Zampini     for (i=1; i<mapping->info_nproc; i++) {
5341bd0b88eSStefano Zampini       ierr = PetscFree(mapping->info_indices[i]);CHKERRQ(ierr);
5351bd0b88eSStefano Zampini     }
5361bd0b88eSStefano Zampini     ierr = PetscFree(mapping->info_indices);CHKERRQ(ierr);
5371bd0b88eSStefano Zampini   }
5381bd0b88eSStefano Zampini   mapping->info_cached = PETSC_FALSE;
5391bd0b88eSStefano Zampini 
540413f72f0SBarry Smith   if (mapping->ops->destroy) {
541413f72f0SBarry Smith     ierr = (*mapping->ops->destroy)(mapping);CHKERRQ(ierr);
542413f72f0SBarry Smith   }
54363fa5c83Sstefano_zampini   PetscFunctionReturn(0);
54463fa5c83Sstefano_zampini }
54563fa5c83Sstefano_zampini 
54645b6f7e9SBarry Smith /*@
54745b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
54845b6f7e9SBarry Smith     ordering and a global parallel ordering.
54945b6f7e9SBarry Smith 
55045b6f7e9SBarry Smith     Not Collective
55145b6f7e9SBarry Smith 
55245b6f7e9SBarry Smith     Input Parameters:
55345b6f7e9SBarry Smith .   mapping - mapping data structure
55445b6f7e9SBarry Smith 
55545b6f7e9SBarry Smith     Output Parameter:
55645b6f7e9SBarry Smith .   bs - the blocksize
55745b6f7e9SBarry Smith 
55845b6f7e9SBarry Smith     Level: advanced
55945b6f7e9SBarry Smith 
56045b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
56145b6f7e9SBarry Smith @*/
56245b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
56345b6f7e9SBarry Smith {
56445b6f7e9SBarry Smith   PetscFunctionBegin;
565cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
56645b6f7e9SBarry Smith   *bs = mapping->bs;
56745b6f7e9SBarry Smith   PetscFunctionReturn(0);
56845b6f7e9SBarry Smith }
56945b6f7e9SBarry Smith 
570ba5bb76aSSatish Balay /*@
57190f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
57290f02eecSBarry Smith     ordering and a global parallel ordering.
5732362add9SBarry Smith 
57489d82c54SBarry Smith     Not Collective, but communicator may have more than one process
575b9cd556bSLois Curfman McInnes 
5762362add9SBarry Smith     Input Parameters:
57789d82c54SBarry Smith +   comm - MPI communicator
578f0413b6fSBarry Smith .   bs - the block size
57928bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
58028bc9809SBarry 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
581d5ad8652SBarry Smith -   mode - see PetscCopyMode
5822362add9SBarry Smith 
583a997ad1aSLois Curfman McInnes     Output Parameter:
58490f02eecSBarry Smith .   mapping - new mapping data structure
5852362add9SBarry Smith 
58695452b02SPatrick Sanan     Notes:
58795452b02SPatrick Sanan     There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
588413f72f0SBarry Smith 
5899a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
590413f72f0SBarry 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.
591413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
592413f72f0SBarry Smith 
593a997ad1aSLois Curfman McInnes     Level: advanced
594a997ad1aSLois Curfman McInnes 
595413f72f0SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingSetFromOptions(), ISLOCALTOGLOBALMAPPINGBASIC, ISLOCALTOGLOBALMAPPINGHASH
596413f72f0SBarry Smith           ISLocalToGlobalMappingSetType(), ISLocalToGlobalMappingType
5972362add9SBarry Smith @*/
59860c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
5992362add9SBarry Smith {
6006849ba73SBarry Smith   PetscErrorCode ierr;
60132dcc486SBarry Smith   PetscInt       *in;
602b46b645bSBarry Smith 
603b46b645bSBarry Smith   PetscFunctionBegin;
604064a246eSJacob Faibussowitsch   if (n) PetscValidIntPointer(indices,4);
605064a246eSJacob Faibussowitsch   PetscValidPointer(mapping,6);
606b46b645bSBarry Smith 
6070298fd71SBarry Smith   *mapping = NULL;
608607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
6092362add9SBarry Smith 
61073107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
61160c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
612d4bb536fSBarry Smith   (*mapping)->n             = n;
613f0413b6fSBarry Smith   (*mapping)->bs            = bs;
614268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
615268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
616268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
617268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
618268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
6191bd0b88eSStefano Zampini   (*mapping)->info_nodec    = NULL;
6201bd0b88eSStefano Zampini   (*mapping)->info_nodei    = NULL;
621413f72f0SBarry Smith 
622413f72f0SBarry Smith   (*mapping)->ops->globaltolocalmappingapply      = NULL;
623413f72f0SBarry Smith   (*mapping)->ops->globaltolocalmappingapplyblock = NULL;
624413f72f0SBarry Smith   (*mapping)->ops->destroy                        = NULL;
625d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
626785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
627580bdb30SBarry Smith     ierr = PetscArraycpy(in,indices,n);CHKERRQ(ierr);
628d5ad8652SBarry Smith     (*mapping)->indices = in;
6296389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
6306389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
6316389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
6326389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
6336389a1a1SBarry Smith   }
63460c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
6353a40ed3dSBarry Smith   PetscFunctionReturn(0);
6362362add9SBarry Smith }
6372362add9SBarry Smith 
638413f72f0SBarry Smith PetscFunctionList ISLocalToGlobalMappingList = NULL;
639413f72f0SBarry Smith 
64090f02eecSBarry Smith /*@
6417e99dc12SLawrence Mitchell    ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database.
6427e99dc12SLawrence Mitchell 
6437e99dc12SLawrence Mitchell    Not collective
6447e99dc12SLawrence Mitchell 
6457e99dc12SLawrence Mitchell    Input Parameters:
6467e99dc12SLawrence Mitchell .  mapping - mapping data structure
6477e99dc12SLawrence Mitchell 
6487e99dc12SLawrence Mitchell    Level: advanced
6497e99dc12SLawrence Mitchell 
6507e99dc12SLawrence Mitchell @*/
6517e99dc12SLawrence Mitchell PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)
6527e99dc12SLawrence Mitchell {
6537e99dc12SLawrence Mitchell   PetscErrorCode             ierr;
654413f72f0SBarry Smith   char                       type[256];
655413f72f0SBarry Smith   ISLocalToGlobalMappingType defaulttype = "Not set";
6567e99dc12SLawrence Mitchell   PetscBool                  flg;
6577e99dc12SLawrence Mitchell 
6587e99dc12SLawrence Mitchell   PetscFunctionBegin;
6597e99dc12SLawrence Mitchell   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
660413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegisterAll();CHKERRQ(ierr);
6617e99dc12SLawrence Mitchell   ierr = PetscObjectOptionsBegin((PetscObject)mapping);CHKERRQ(ierr);
662413f72f0SBarry Smith   ierr = PetscOptionsFList("-islocaltoglobalmapping_type","ISLocalToGlobalMapping method","ISLocalToGlobalMappingSetType",ISLocalToGlobalMappingList,(char*)(((PetscObject)mapping)->type_name) ? ((PetscObject)mapping)->type_name : defaulttype,type,256,&flg);CHKERRQ(ierr);
663413f72f0SBarry Smith   if (flg) {
664413f72f0SBarry Smith     ierr = ISLocalToGlobalMappingSetType(mapping,type);CHKERRQ(ierr);
665413f72f0SBarry Smith   }
6667e99dc12SLawrence Mitchell   ierr = PetscOptionsEnd();CHKERRQ(ierr);
6677e99dc12SLawrence Mitchell   PetscFunctionReturn(0);
6687e99dc12SLawrence Mitchell }
6697e99dc12SLawrence Mitchell 
6707e99dc12SLawrence Mitchell /*@
67190f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
67290f02eecSBarry Smith    ordering and a global parallel ordering.
67390f02eecSBarry Smith 
6740f5bd95cSBarry Smith    Note Collective
675b9cd556bSLois Curfman McInnes 
67690f02eecSBarry Smith    Input Parameters:
67790f02eecSBarry Smith .  mapping - mapping data structure
67890f02eecSBarry Smith 
679a997ad1aSLois Curfman McInnes    Level: advanced
680a997ad1aSLois Curfman McInnes 
6813acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
68290f02eecSBarry Smith @*/
6836bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
68490f02eecSBarry Smith {
685dfbe8321SBarry Smith   PetscErrorCode ierr;
6865fd66863SKarl Rupp 
6873a40ed3dSBarry Smith   PetscFunctionBegin;
6886bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
6896bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
6904c8fdceaSLisandro Dalcin   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = NULL;PetscFunctionReturn(0);}
6916bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
692268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
693268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
694268a049cSStefano Zampini   if ((*mapping)->info_indices) {
695268a049cSStefano Zampini     PetscInt i;
696268a049cSStefano Zampini 
697268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
698268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
699268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
700268a049cSStefano Zampini     }
701268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
702268a049cSStefano Zampini   }
7031bd0b88eSStefano Zampini   if ((*mapping)->info_nodei) {
7041bd0b88eSStefano Zampini     ierr = PetscFree(((*mapping)->info_nodei)[0]);CHKERRQ(ierr);
7051bd0b88eSStefano Zampini   }
706071fcb05SBarry Smith   ierr = PetscFree2((*mapping)->info_nodec,(*mapping)->info_nodei);CHKERRQ(ierr);
707413f72f0SBarry Smith   if ((*mapping)->ops->destroy) {
708413f72f0SBarry Smith     ierr = (*(*mapping)->ops->destroy)(*mapping);CHKERRQ(ierr);
709413f72f0SBarry Smith   }
710d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
7114c8fdceaSLisandro Dalcin   *mapping = NULL;
7123a40ed3dSBarry Smith   PetscFunctionReturn(0);
71390f02eecSBarry Smith }
71490f02eecSBarry Smith 
71590f02eecSBarry Smith /*@
7163acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
7173acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
7183acfe500SLois Curfman McInnes     context.
71990f02eecSBarry Smith 
7204cb36875SStefano Zampini     Collective on is
721b9cd556bSLois Curfman McInnes 
72290f02eecSBarry Smith     Input Parameters:
723b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
724b9cd556bSLois Curfman McInnes -   is - index set in local numbering
72590f02eecSBarry Smith 
72690f02eecSBarry Smith     Output Parameters:
72790f02eecSBarry Smith .   newis - index set in global numbering
72890f02eecSBarry Smith 
7294cb36875SStefano Zampini     Notes:
7304cb36875SStefano Zampini     The output IS will have the same communicator of the input IS.
7314cb36875SStefano Zampini 
732a997ad1aSLois Curfman McInnes     Level: advanced
733a997ad1aSLois Curfman McInnes 
73490f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
735d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
73690f02eecSBarry Smith @*/
7377087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
73890f02eecSBarry Smith {
7396849ba73SBarry Smith   PetscErrorCode ierr;
740e24637baSBarry Smith   PetscInt       n,*idxout;
7415d0c19d7SBarry Smith   const PetscInt *idxin;
7423a40ed3dSBarry Smith 
7433a40ed3dSBarry Smith   PetscFunctionBegin;
7440700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
7450700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
7464482741eSBarry Smith   PetscValidPointer(newis,3);
74790f02eecSBarry Smith 
7483b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
74990f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
750785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
751e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
7523b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
753543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
7543a40ed3dSBarry Smith   PetscFunctionReturn(0);
75590f02eecSBarry Smith }
75690f02eecSBarry Smith 
757b89cb25eSSatish Balay /*@
7583acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
7593acfe500SLois Curfman McInnes    and converts them to the global numbering.
76090f02eecSBarry Smith 
761b9cd556bSLois Curfman McInnes    Not collective
762b9cd556bSLois Curfman McInnes 
763bb25748dSBarry Smith    Input Parameters:
764b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
765bb25748dSBarry Smith .  N - number of integers
766b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
767bb25748dSBarry Smith 
768bb25748dSBarry Smith    Output Parameter:
769bb25748dSBarry Smith .  out - indices in global numbering
770bb25748dSBarry Smith 
771b9cd556bSLois Curfman McInnes    Notes:
772b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
773d4bb536fSBarry Smith 
774a997ad1aSLois Curfman McInnes    Level: advanced
775a997ad1aSLois Curfman McInnes 
77645b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
7770752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
778d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
779bb25748dSBarry Smith 
780afcb2eb5SJed Brown @*/
781afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
782afcb2eb5SJed Brown {
783cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
78445b6f7e9SBarry Smith 
78545b6f7e9SBarry Smith   PetscFunctionBegin;
786cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
787cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
788cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
78945b6f7e9SBarry Smith   if (bs == 1) {
790cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
79145b6f7e9SBarry Smith     for (i=0; i<N; i++) {
79245b6f7e9SBarry Smith       if (in[i] < 0) {
79345b6f7e9SBarry Smith         out[i] = in[i];
79445b6f7e9SBarry Smith         continue;
79545b6f7e9SBarry Smith       }
796e24637baSBarry 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);
79745b6f7e9SBarry Smith       out[i] = idx[in[i]];
79845b6f7e9SBarry Smith     }
79945b6f7e9SBarry Smith   } else {
800cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
80145b6f7e9SBarry Smith     for (i=0; i<N; i++) {
80245b6f7e9SBarry Smith       if (in[i] < 0) {
80345b6f7e9SBarry Smith         out[i] = in[i];
80445b6f7e9SBarry Smith         continue;
80545b6f7e9SBarry Smith       }
806e24637baSBarry 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);
80745b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
80845b6f7e9SBarry Smith     }
80945b6f7e9SBarry Smith   }
81045b6f7e9SBarry Smith   PetscFunctionReturn(0);
81145b6f7e9SBarry Smith }
81245b6f7e9SBarry Smith 
81345b6f7e9SBarry Smith /*@
8146006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
81545b6f7e9SBarry Smith 
81645b6f7e9SBarry Smith    Not collective
81745b6f7e9SBarry Smith 
81845b6f7e9SBarry Smith    Input Parameters:
81945b6f7e9SBarry Smith +  mapping - the local to global mapping context
82045b6f7e9SBarry Smith .  N - number of integers
8216006e8d2SBarry Smith -  in - input indices in local block numbering
82245b6f7e9SBarry Smith 
82345b6f7e9SBarry Smith    Output Parameter:
8246006e8d2SBarry Smith .  out - indices in global block numbering
82545b6f7e9SBarry Smith 
82645b6f7e9SBarry Smith    Notes:
82745b6f7e9SBarry Smith    The in and out array parameters may be identical.
82845b6f7e9SBarry Smith 
8296006e8d2SBarry Smith    Example:
8306006e8d2SBarry 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
8316006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
8326006e8d2SBarry Smith 
83345b6f7e9SBarry Smith    Level: advanced
83445b6f7e9SBarry Smith 
83545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
83645b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
83745b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
83845b6f7e9SBarry Smith 
83945b6f7e9SBarry Smith @*/
84045b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
84145b6f7e9SBarry Smith {
842cbc1caf0SMatthew G. Knepley 
843cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
844cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
845cbc1caf0SMatthew G. Knepley   {
846afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
847afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
848d4bb536fSBarry Smith 
849afcb2eb5SJed Brown     for (i=0; i<N; i++) {
850afcb2eb5SJed Brown       if (in[i] < 0) {
851afcb2eb5SJed Brown         out[i] = in[i];
852afcb2eb5SJed Brown         continue;
853afcb2eb5SJed Brown       }
854e24637baSBarry 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);
855afcb2eb5SJed Brown       out[i] = idx[in[i]];
856afcb2eb5SJed Brown     }
857cbc1caf0SMatthew G. Knepley   }
858afcb2eb5SJed Brown   PetscFunctionReturn(0);
859afcb2eb5SJed Brown }
860d4bb536fSBarry Smith 
8617e99dc12SLawrence Mitchell /*@
862a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
863a997ad1aSLois Curfman McInnes     specified with a global numbering.
864d4bb536fSBarry Smith 
865b9cd556bSLois Curfman McInnes     Not collective
866b9cd556bSLois Curfman McInnes 
867d4bb536fSBarry Smith     Input Parameters:
868b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
8690040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
870d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
871d4bb536fSBarry Smith .   n - number of global indices to map
872b9cd556bSLois Curfman McInnes -   idx - global indices to map
873d4bb536fSBarry Smith 
874d4bb536fSBarry Smith     Output Parameters:
875b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
876b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
877e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
8780298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
879e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
880e182c471SBarry Smith              a second time to set the values.
881d4bb536fSBarry Smith 
882b9cd556bSLois Curfman McInnes     Notes:
8830298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
884d4bb536fSBarry Smith 
8859a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
886413f72f0SBarry 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.
887413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
8880f5bd95cSBarry Smith 
889a997ad1aSLois Curfman McInnes     Level: advanced
890a997ad1aSLois Curfman McInnes 
89132fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
89232fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
89332fd6b96SBarry Smith 
8949d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
895413f72f0SBarry Smith           ISLocalToGlobalMappingDestroy()
896d4bb536fSBarry Smith @*/
897413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
898d4bb536fSBarry Smith {
8999d90f715SBarry Smith   PetscErrorCode ierr;
9009d90f715SBarry Smith 
9019d90f715SBarry Smith   PetscFunctionBegin;
9029d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
903413f72f0SBarry Smith   if (!mapping->data) {
904413f72f0SBarry Smith     ierr = ISGlobalToLocalMappingSetUp(mapping);CHKERRQ(ierr);
9059d90f715SBarry Smith   }
906413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingapply)(mapping,type,n,idx,nout,idxout);CHKERRQ(ierr);
9079d90f715SBarry Smith   PetscFunctionReturn(0);
9089d90f715SBarry Smith }
9099d90f715SBarry Smith 
910d4fe737eSStefano Zampini /*@
911d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
912d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
913d4fe737eSStefano Zampini     context.
914d4fe737eSStefano Zampini 
915d4fe737eSStefano Zampini     Not collective
916d4fe737eSStefano Zampini 
917d4fe737eSStefano Zampini     Input Parameters:
918d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
9190040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
9202785b321SStefano Zampini            IS_GTOLM_DROP - drops the indices with no local value from the output list
921d4fe737eSStefano Zampini -   is - index set in global numbering
922d4fe737eSStefano Zampini 
923d4fe737eSStefano Zampini     Output Parameters:
924d4fe737eSStefano Zampini .   newis - index set in local numbering
925d4fe737eSStefano Zampini 
9264cb36875SStefano Zampini     Notes:
9274cb36875SStefano Zampini     The output IS will be sequential, as it encodes a purely local operation
9284cb36875SStefano Zampini 
929d4fe737eSStefano Zampini     Level: advanced
930d4fe737eSStefano Zampini 
931d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
932d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
933d4fe737eSStefano Zampini @*/
934413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,IS is,IS *newis)
935d4fe737eSStefano Zampini {
936d4fe737eSStefano Zampini   PetscErrorCode ierr;
937d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
938d4fe737eSStefano Zampini   const PetscInt *idxin;
939d4fe737eSStefano Zampini 
940d4fe737eSStefano Zampini   PetscFunctionBegin;
941d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
942d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
943d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
944d4fe737eSStefano Zampini 
945d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
946d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
947d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
948d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
949d4fe737eSStefano Zampini   } else {
950d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
951d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
952d4fe737eSStefano Zampini   }
953d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
954d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
9554cb36875SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
956d4fe737eSStefano Zampini   PetscFunctionReturn(0);
957d4fe737eSStefano Zampini }
958d4fe737eSStefano Zampini 
9599d90f715SBarry Smith /*@
9609d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
9619d90f715SBarry Smith     specified with a block global numbering.
9629d90f715SBarry Smith 
9639d90f715SBarry Smith     Not collective
9649d90f715SBarry Smith 
9659d90f715SBarry Smith     Input Parameters:
9669d90f715SBarry Smith +   mapping - mapping between local and global numbering
9670040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
9689d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
9699d90f715SBarry Smith .   n - number of global indices to map
9709d90f715SBarry Smith -   idx - global indices to map
9719d90f715SBarry Smith 
9729d90f715SBarry Smith     Output Parameters:
9739d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
9749d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
9759d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
9769d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
9779d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
9789d90f715SBarry Smith              a second time to set the values.
9799d90f715SBarry Smith 
9809d90f715SBarry Smith     Notes:
9819d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
9829d90f715SBarry Smith 
9839a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
984413f72f0SBarry 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.
985413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
9869d90f715SBarry Smith 
9879d90f715SBarry Smith     Level: advanced
9889d90f715SBarry Smith 
9899d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
9909d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
9919d90f715SBarry Smith 
9929d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
993413f72f0SBarry Smith           ISLocalToGlobalMappingDestroy()
9949d90f715SBarry Smith @*/
995413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,
9969d90f715SBarry Smith                                                  PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
9979d90f715SBarry Smith {
9986849ba73SBarry Smith   PetscErrorCode ierr;
999d4bb536fSBarry Smith 
10003a40ed3dSBarry Smith   PetscFunctionBegin;
10010700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1002413f72f0SBarry Smith   if (!mapping->data) {
1003413f72f0SBarry Smith     ierr = ISGlobalToLocalMappingSetUp(mapping);CHKERRQ(ierr);
1004d4bb536fSBarry Smith   }
1005413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingapplyblock)(mapping,type,n,idx,nout,idxout);CHKERRQ(ierr);
10063a40ed3dSBarry Smith   PetscFunctionReturn(0);
1007d4bb536fSBarry Smith }
100890f02eecSBarry Smith 
100989d82c54SBarry Smith /*@C
10106a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
101189d82c54SBarry Smith      each index shared by more than one processor
101289d82c54SBarry Smith 
101389d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
101489d82c54SBarry Smith 
101589d82c54SBarry Smith     Input Parameters:
101689d82c54SBarry Smith .   mapping - the mapping from local to global indexing
101789d82c54SBarry Smith 
1018*d8d19677SJose E. Roman     Output Parameters:
101989d82c54SBarry Smith +   nproc - number of processors that are connected to this one
102089d82c54SBarry Smith .   proc - neighboring processors
102107b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
10223463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
102389d82c54SBarry Smith 
102489d82c54SBarry Smith     Level: advanced
102589d82c54SBarry Smith 
10262cfcea29SBarry Smith     Fortran Usage:
10272cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
10282cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
10292cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
10302cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
10312cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
10322cfcea29SBarry Smith 
103307b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
103407b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
103589d82c54SBarry Smith @*/
10366a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
103789d82c54SBarry Smith {
10386849ba73SBarry Smith   PetscErrorCode ierr;
1039268a049cSStefano Zampini 
1040268a049cSStefano Zampini   PetscFunctionBegin;
1041268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1042268a049cSStefano Zampini   if (mapping->info_cached) {
1043268a049cSStefano Zampini     *nproc    = mapping->info_nproc;
1044268a049cSStefano Zampini     *procs    = mapping->info_procs;
1045268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
1046268a049cSStefano Zampini     *indices  = mapping->info_indices;
1047268a049cSStefano Zampini   } else {
1048268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
1049268a049cSStefano Zampini   }
1050268a049cSStefano Zampini   PetscFunctionReturn(0);
1051268a049cSStefano Zampini }
1052268a049cSStefano Zampini 
1053268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
1054268a049cSStefano Zampini {
1055268a049cSStefano Zampini   PetscErrorCode ierr;
105697f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
105732dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
105832dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
105997f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
106032dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
106132dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
106289d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
106330dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
1064ce94432eSBarry Smith   MPI_Comm       comm;
1065ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
106689d82c54SBarry Smith 
106789d82c54SBarry Smith   PetscFunctionBegin;
1068ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
1069ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
1070ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
107124cf384cSBarry Smith   if (size == 1) {
107224cf384cSBarry Smith     *nproc         = 0;
10730298fd71SBarry Smith     *procs         = NULL;
107495dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
10751e2105dcSBarry Smith     (*numprocs)[0] = 0;
107695dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
10770298fd71SBarry Smith     (*indices)[0]  = NULL;
1078268a049cSStefano Zampini     /* save info for reuse */
1079268a049cSStefano Zampini     mapping->info_nproc = *nproc;
1080268a049cSStefano Zampini     mapping->info_procs = *procs;
1081268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
1082268a049cSStefano Zampini     mapping->info_indices = *indices;
1083268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
108424cf384cSBarry Smith     PetscFunctionReturn(0);
108524cf384cSBarry Smith   }
108624cf384cSBarry Smith 
1087c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
108807b52d57SBarry Smith 
10893677ff5aSBarry Smith   /*
10906a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
10913677ff5aSBarry Smith 
10923677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
10933677ff5aSBarry Smith            numbering, just for this routine.
10943677ff5aSBarry Smith 
10953677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
10963677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
10973677ff5aSBarry Smith 
10983677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
10993677ff5aSBarry Smith 
11003677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
11013677ff5aSBarry Smith            local subdomain
11023677ff5aSBarry Smith   */
110324cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
110424cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
110524cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
110689d82c54SBarry Smith 
110789d82c54SBarry Smith   for (i=0; i<n; i++) {
110889d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
110989d82c54SBarry Smith   }
1110820f2d46SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRMPI(ierr);
111178058e43SBarry Smith   Ng++;
111255b25c41SPierre Jolivet   ierr   = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
111355b25c41SPierre Jolivet   ierr   = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1114bc8ff85bSBarry Smith   scale  = Ng/size + 1;
1115a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
1116caba0dd0SBarry Smith   rstart = scale*rank;
111789d82c54SBarry Smith 
111889d82c54SBarry Smith   /* determine ownership ranges of global indices */
1119785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
1120580bdb30SBarry Smith   ierr = PetscArrayzero(nprocs,2*size);CHKERRQ(ierr);
112189d82c54SBarry Smith 
112289d82c54SBarry Smith   /* determine owners of each local node  */
1123785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
112489d82c54SBarry Smith   for (i=0; i<n; i++) {
11253677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
112627c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
11273677ff5aSBarry Smith     owner[i]         = proc;
112827c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
112989d82c54SBarry Smith   }
113027c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
11317904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
113289d82c54SBarry Smith 
113389d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
113427c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
11357904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
113689d82c54SBarry Smith 
113789d82c54SBarry Smith   /* post receives for owned rows */
1138785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
1139854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
114089d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
1141ffc4695bSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRMPI(ierr);
114289d82c54SBarry Smith   }
114389d82c54SBarry Smith 
114489d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
1145854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
1146854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
114789d82c54SBarry Smith   starts[0] = 0;
1148f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
114989d82c54SBarry Smith   for (i=0; i<n; i++) {
115089d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
115130dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
115289d82c54SBarry Smith   }
115389d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
115489d82c54SBarry Smith   starts[0] = 0;
1155f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
115689d82c54SBarry Smith 
115789d82c54SBarry Smith   /* send the messages */
1158854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
1159854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
116089d82c54SBarry Smith   cnt = 0;
116189d82c54SBarry Smith   for (i=0; i<size; i++) {
116227c402fcSBarry Smith     if (nprocs[2*i]) {
116355b25c41SPierre Jolivet       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRMPI(ierr);
116430dcb7c9SBarry Smith       dest[cnt] = i;
116589d82c54SBarry Smith       cnt++;
116689d82c54SBarry Smith     }
116789d82c54SBarry Smith   }
116889d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
116989d82c54SBarry Smith 
117089d82c54SBarry Smith   /* wait on receives */
1171854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
1172854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
117389d82c54SBarry Smith   cnt  = nrecvs;
1174580bdb30SBarry Smith   ierr = PetscCalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
117589d82c54SBarry Smith   while (cnt) {
1176ffc4695bSBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRMPI(ierr);
117789d82c54SBarry Smith     /* unpack receives into our local space */
117855b25c41SPierre Jolivet     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRMPI(ierr);
117989d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
118030dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
1181caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
118230dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
118389d82c54SBarry Smith     cnt--;
118489d82c54SBarry Smith   }
118589d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
118689d82c54SBarry Smith 
118730dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1188bc8ff85bSBarry Smith   nowned  = 0;
1189bc8ff85bSBarry Smith   nownedm = 0;
1190bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
1191bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
1192bc8ff85bSBarry Smith   }
1193bc8ff85bSBarry Smith 
1194bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1195854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1196854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1197bc8ff85bSBarry Smith   starts[0] = 0;
1198bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1199bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1200bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1201bc8ff85bSBarry Smith   }
1202bc8ff85bSBarry Smith 
120330dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1204bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1205bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
120630dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1207f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1208bc8ff85bSBarry Smith     }
1209bc8ff85bSBarry Smith   }
1210bc8ff85bSBarry Smith 
121107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
121230dcb7c9SBarry Smith     starts[0] = 0;
121330dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
121430dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
121530dcb7c9SBarry Smith       else starts[i] = starts[i-1];
121630dcb7c9SBarry Smith     }
121730dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
121830dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
12197904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
122030dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
12217904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
122230dcb7c9SBarry Smith         }
122330dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
122430dcb7c9SBarry Smith       }
122530dcb7c9SBarry Smith     }
12260ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
122707b52d57SBarry Smith   } /* -----------------------------------  */
122830dcb7c9SBarry Smith 
12293677ff5aSBarry Smith   /* wait on original sends */
12303a96401aSBarry Smith   if (nsends) {
1231785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
1232ffc4695bSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRMPI(ierr);
12333a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
12343a96401aSBarry Smith   }
123589d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12363a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
12373677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
12383677ff5aSBarry Smith 
12393677ff5aSBarry Smith   /* pack messages to send back to local owners */
124030dcb7c9SBarry Smith   starts[0] = 0;
124130dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
124230dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
124330dcb7c9SBarry Smith     else starts[i] = starts[i-1];
124430dcb7c9SBarry Smith   }
124530dcb7c9SBarry Smith   nsends2 = nrecvs;
1246854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
124730dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
124830dcb7c9SBarry Smith     nprocs[i] = 1;
124930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
125030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1251f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
125230dcb7c9SBarry Smith     }
125330dcb7c9SBarry Smith   }
1254f6e5521dSKarl Rupp   nt = 0;
1255f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1256f6e5521dSKarl Rupp 
1257854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1258854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1259f6e5521dSKarl Rupp 
1260f6e5521dSKarl Rupp   starts2[0] = 0;
1261f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
126230dcb7c9SBarry Smith   /*
126330dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
126430dcb7c9SBarry Smith        (0) the number of nodes being sent back
126530dcb7c9SBarry Smith        (1) the local node number,
126630dcb7c9SBarry Smith        (2) the number of processors sharing it,
126730dcb7c9SBarry Smith        (3) the processors sharing it
126830dcb7c9SBarry Smith   */
126930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
127030dcb7c9SBarry Smith     cnt = 1;
127130dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
127230dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
127330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
127430dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
127530dcb7c9SBarry Smith         sends2[starts2[i]]++;
127630dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
127730dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
1278580bdb30SBarry Smith         ierr = PetscArraycpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]);CHKERRQ(ierr);
127930dcb7c9SBarry Smith         cnt += nownedsenders[node];
128030dcb7c9SBarry Smith       }
128130dcb7c9SBarry Smith     }
128230dcb7c9SBarry Smith   }
128330dcb7c9SBarry Smith 
128430dcb7c9SBarry Smith   /* receive the message lengths */
128530dcb7c9SBarry Smith   nrecvs2 = nsends;
1286854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1287854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1288854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
128930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1290ffc4695bSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRMPI(ierr);
129130dcb7c9SBarry Smith   }
1292d44834fbSBarry Smith 
12938a8e0b3aSBarry Smith   /* send the message lengths */
12948a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
1295ffc4695bSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRMPI(ierr);
12968a8e0b3aSBarry Smith   }
12978a8e0b3aSBarry Smith 
1298d44834fbSBarry Smith   /* wait on receives of lens */
12990c468ba9SBarry Smith   if (nrecvs2) {
1300785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1301ffc4695bSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRMPI(ierr);
1302d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
13030c468ba9SBarry Smith   }
1304a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1305d44834fbSBarry Smith 
130630dcb7c9SBarry Smith   starts3[0] = 0;
1307d44834fbSBarry Smith   nt         = 0;
130830dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
130930dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1310d44834fbSBarry Smith     nt          += lens2[i];
131130dcb7c9SBarry Smith   }
131276466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1313d44834fbSBarry Smith 
1314854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1315854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
131652b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
1317ffc4695bSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRMPI(ierr);
131830dcb7c9SBarry Smith   }
131930dcb7c9SBarry Smith 
132030dcb7c9SBarry Smith   /* send the messages */
1321854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
132230dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
1323ffc4695bSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRMPI(ierr);
132430dcb7c9SBarry Smith   }
132530dcb7c9SBarry Smith 
132630dcb7c9SBarry Smith   /* wait on receives */
13270c468ba9SBarry Smith   if (nrecvs2) {
1328785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1329ffc4695bSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRMPI(ierr);
133030dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
13310c468ba9SBarry Smith   }
133230dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
133330dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
133430dcb7c9SBarry Smith 
133507b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
133630dcb7c9SBarry Smith     cnt = 0;
133730dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
133830dcb7c9SBarry Smith       nt = recvs2[cnt++];
133930dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
13407904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
134130dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
13427904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
134330dcb7c9SBarry Smith         }
134430dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
134530dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
134630dcb7c9SBarry Smith       }
134730dcb7c9SBarry Smith     }
13480ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
134907b52d57SBarry Smith   } /* -----------------------------------  */
135030dcb7c9SBarry Smith 
135130dcb7c9SBarry Smith   /* count number subdomains for each local node */
1352580bdb30SBarry Smith   ierr = PetscCalloc1(size,&nprocs);CHKERRQ(ierr);
135330dcb7c9SBarry Smith   cnt  = 0;
135430dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
135530dcb7c9SBarry Smith     nt = recvs2[cnt++];
135630dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1357f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
135830dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
135930dcb7c9SBarry Smith     }
136030dcb7c9SBarry Smith   }
136130dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
136230dcb7c9SBarry Smith   *nproc    = nt;
1363854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1364854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1365854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
13660298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1367785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
136830dcb7c9SBarry Smith   cnt  = 0;
136930dcb7c9SBarry Smith   for (i=0; i<size; i++) {
137030dcb7c9SBarry Smith     if (nprocs[i] > 0) {
137130dcb7c9SBarry Smith       bprocs[i]        = cnt;
137230dcb7c9SBarry Smith       (*procs)[cnt]    = i;
137330dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1374785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
137530dcb7c9SBarry Smith       cnt++;
137630dcb7c9SBarry Smith     }
137730dcb7c9SBarry Smith   }
137830dcb7c9SBarry Smith 
137930dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
1380580bdb30SBarry Smith   ierr = PetscArrayzero(*numprocs,nt);CHKERRQ(ierr);
138130dcb7c9SBarry Smith   cnt  = 0;
138230dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
138330dcb7c9SBarry Smith     nt = recvs2[cnt++];
138430dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1385f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
138630dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
138730dcb7c9SBarry Smith     }
138830dcb7c9SBarry Smith   }
138930dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
139007b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
139130dcb7c9SBarry Smith 
139207b52d57SBarry Smith   /* sort the node indexing by their global numbers */
139307b52d57SBarry Smith   nt = *nproc;
139407b52d57SBarry Smith   for (i=0; i<nt; i++) {
1395854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1396f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
139707b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
139807b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
139907b52d57SBarry Smith   }
140007b52d57SBarry Smith 
140107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
140230dcb7c9SBarry Smith     nt = *nproc;
140330dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
14047904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
140530dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
14067904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
140730dcb7c9SBarry Smith       }
140830dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
140930dcb7c9SBarry Smith     }
14100ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
141107b52d57SBarry Smith   } /* -----------------------------------  */
141230dcb7c9SBarry Smith 
141330dcb7c9SBarry Smith   /* wait on sends */
141430dcb7c9SBarry Smith   if (nsends2) {
1415785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
1416ffc4695bSBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRMPI(ierr);
141730dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
141830dcb7c9SBarry Smith   }
141930dcb7c9SBarry Smith 
142030dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
142130dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
142230dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
14233677ff5aSBarry Smith 
1424bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1425bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1426bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
142730dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
142830dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
142989d82c54SBarry Smith 
143089d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
143197f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
143289d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
14333a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
143430dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
143524cf384cSBarry Smith 
143624cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
143724cf384cSBarry Smith   first_procs    = (*procs)[0];
143824cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
143924cf384cSBarry Smith   first_indices  = (*indices)[0];
144024cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
144124cf384cSBarry Smith     if ((*procs)[i] == rank) {
144224cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
144324cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
144424cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
144524cf384cSBarry Smith       (*procs)[i]    = first_procs;
144624cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
144724cf384cSBarry Smith       (*indices)[i]  = first_indices;
144824cf384cSBarry Smith       break;
144924cf384cSBarry Smith     }
145024cf384cSBarry Smith   }
1451268a049cSStefano Zampini 
1452268a049cSStefano Zampini   /* save info for reuse */
1453268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1454268a049cSStefano Zampini   mapping->info_procs = *procs;
1455268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1456268a049cSStefano Zampini   mapping->info_indices = *indices;
1457268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
145889d82c54SBarry Smith   PetscFunctionReturn(0);
145989d82c54SBarry Smith }
146089d82c54SBarry Smith 
14616a818285SBarry Smith /*@C
14626a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
14636a818285SBarry Smith 
14646a818285SBarry Smith     Collective on ISLocalToGlobalMapping
14656a818285SBarry Smith 
14666a818285SBarry Smith     Input Parameters:
14676a818285SBarry Smith .   mapping - the mapping from local to global indexing
14686a818285SBarry Smith 
1469*d8d19677SJose E. Roman     Output Parameters:
14706a818285SBarry Smith +   nproc - number of processors that are connected to this one
14716a818285SBarry Smith .   proc - neighboring processors
14726a818285SBarry Smith .   numproc - number of indices for each processor
14736a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
14746a818285SBarry Smith 
14756a818285SBarry Smith     Level: advanced
14766a818285SBarry Smith 
14776a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
14786a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
14796a818285SBarry Smith @*/
14806a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
14816a818285SBarry Smith {
14826a818285SBarry Smith   PetscErrorCode ierr;
14836a818285SBarry Smith 
14846a818285SBarry Smith   PetscFunctionBegin;
1485cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1486268a049cSStefano Zampini   if (mapping->info_free) {
14876a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
14886a818285SBarry Smith     if (*indices) {
1489268a049cSStefano Zampini       PetscInt i;
1490268a049cSStefano Zampini 
14916a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
14926a818285SBarry Smith       for (i=1; i<*nproc; i++) {
14936a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
14946a818285SBarry Smith       }
14956a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
14966a818285SBarry Smith     }
1497268a049cSStefano Zampini   }
1498268a049cSStefano Zampini   *nproc    = 0;
1499268a049cSStefano Zampini   *procs    = NULL;
1500268a049cSStefano Zampini   *numprocs = NULL;
1501268a049cSStefano Zampini   *indices  = NULL;
15026a818285SBarry Smith   PetscFunctionReturn(0);
15036a818285SBarry Smith }
15046a818285SBarry Smith 
15056a818285SBarry Smith /*@C
15066a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
15076a818285SBarry Smith      each index shared by more than one processor
15086a818285SBarry Smith 
15096a818285SBarry Smith     Collective on ISLocalToGlobalMapping
15106a818285SBarry Smith 
15116a818285SBarry Smith     Input Parameters:
15126a818285SBarry Smith .   mapping - the mapping from local to global indexing
15136a818285SBarry Smith 
1514*d8d19677SJose E. Roman     Output Parameters:
15156a818285SBarry Smith +   nproc - number of processors that are connected to this one
15166a818285SBarry Smith .   proc - neighboring processors
15176a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
15186a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
15196a818285SBarry Smith 
15206a818285SBarry Smith     Level: advanced
15216a818285SBarry Smith 
15221bd0b88eSStefano Zampini     Notes: The user needs to call ISLocalToGlobalMappingRestoreInfo when the data is no longer needed.
15231bd0b88eSStefano Zampini 
15246a818285SBarry Smith     Fortran Usage:
15256a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
15266a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
15276a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
15286a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
15296a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
15306a818285SBarry Smith 
15316a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
15326a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
15336a818285SBarry Smith @*/
15346a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
15356a818285SBarry Smith {
15366a818285SBarry Smith   PetscErrorCode ierr;
1537268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
15386a818285SBarry Smith 
15396a818285SBarry Smith   PetscFunctionBegin;
15406a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1541268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1542268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1543732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1544268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
15456a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1546268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1547268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
15486a818285SBarry Smith         for (k=0; k<bs; k++) {
15496a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
15506a818285SBarry Smith         }
15516a818285SBarry Smith       }
1552268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
15536a818285SBarry Smith     }
1554268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1555268a049cSStefano Zampini   } else {
1556268a049cSStefano Zampini     *numprocs = bnumprocs;
1557268a049cSStefano Zampini     *indices  = bindices;
15586a818285SBarry Smith   }
15596a818285SBarry Smith   PetscFunctionReturn(0);
15606a818285SBarry Smith }
15616a818285SBarry Smith 
156207b52d57SBarry Smith /*@C
156307b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
156489d82c54SBarry Smith 
156507b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
156607b52d57SBarry Smith 
156707b52d57SBarry Smith     Input Parameters:
156807b52d57SBarry Smith .   mapping - the mapping from local to global indexing
156907b52d57SBarry Smith 
1570*d8d19677SJose E. Roman     Output Parameters:
157107b52d57SBarry Smith +   nproc - number of processors that are connected to this one
157207b52d57SBarry Smith .   proc - neighboring processors
157307b52d57SBarry Smith .   numproc - number of indices for each processor
157407b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
157507b52d57SBarry Smith 
157607b52d57SBarry Smith     Level: advanced
157707b52d57SBarry Smith 
157807b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
157907b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
158007b52d57SBarry Smith @*/
15817087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
158207b52d57SBarry Smith {
15836849ba73SBarry Smith   PetscErrorCode ierr;
158407b52d57SBarry Smith 
158507b52d57SBarry Smith   PetscFunctionBegin;
15866a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
158707b52d57SBarry Smith   PetscFunctionReturn(0);
158807b52d57SBarry Smith }
158986994e45SJed Brown 
159086994e45SJed Brown /*@C
15911bd0b88eSStefano Zampini     ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information for each node
15921bd0b88eSStefano Zampini 
15931bd0b88eSStefano Zampini     Collective on ISLocalToGlobalMapping
15941bd0b88eSStefano Zampini 
15951bd0b88eSStefano Zampini     Input Parameters:
15961bd0b88eSStefano Zampini .   mapping - the mapping from local to global indexing
15971bd0b88eSStefano Zampini 
1598*d8d19677SJose E. Roman     Output Parameters:
15991bd0b88eSStefano Zampini +   nnodes - number of local nodes (same ISLocalToGlobalMappingGetSize())
16001bd0b88eSStefano Zampini .   count - number of neighboring processors per node
16011bd0b88eSStefano Zampini -   indices - indices of processes sharing the node (sorted)
16021bd0b88eSStefano Zampini 
16031bd0b88eSStefano Zampini     Level: advanced
16041bd0b88eSStefano Zampini 
16051bd0b88eSStefano Zampini     Notes: The user needs to call ISLocalToGlobalMappingRestoreInfo when the data is no longer needed.
16061bd0b88eSStefano Zampini 
16071bd0b88eSStefano Zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
16081bd0b88eSStefano Zampini           ISLocalToGlobalMappingGetInfo(), ISLocalToGlobalMappingRestoreNodeInfo()
16091bd0b88eSStefano Zampini @*/
16101bd0b88eSStefano Zampini PetscErrorCode  ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping,PetscInt *nnodes,PetscInt *count[],PetscInt **indices[])
16111bd0b88eSStefano Zampini {
16121bd0b88eSStefano Zampini   PetscInt       n;
16131bd0b88eSStefano Zampini   PetscErrorCode ierr;
16141bd0b88eSStefano Zampini 
16151bd0b88eSStefano Zampini   PetscFunctionBegin;
16161bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
16171bd0b88eSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mapping,&n);CHKERRQ(ierr);
16181bd0b88eSStefano Zampini   if (!mapping->info_nodec) {
16191bd0b88eSStefano Zampini     PetscInt i,m,n_neigh,*neigh,*n_shared,**shared;
16201bd0b88eSStefano Zampini 
1621071fcb05SBarry Smith     ierr = PetscMalloc2(n+1,&mapping->info_nodec,n,&mapping->info_nodei);CHKERRQ(ierr);
16221bd0b88eSStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1623071fcb05SBarry Smith     for (i=0;i<n;i++) { mapping->info_nodec[i] = 1;}
1624071fcb05SBarry Smith     m = n;
1625071fcb05SBarry Smith     mapping->info_nodec[n] = 0;
16261bd0b88eSStefano Zampini     for (i=1;i<n_neigh;i++) {
16271bd0b88eSStefano Zampini       PetscInt j;
16281bd0b88eSStefano Zampini 
16291bd0b88eSStefano Zampini       m += n_shared[i];
16301bd0b88eSStefano Zampini       for (j=0;j<n_shared[i];j++) mapping->info_nodec[shared[i][j]] += 1;
16311bd0b88eSStefano Zampini     }
16321bd0b88eSStefano Zampini     if (n) { ierr = PetscMalloc1(m,&mapping->info_nodei[0]);CHKERRQ(ierr); }
16331bd0b88eSStefano Zampini     for (i=1;i<n;i++) mapping->info_nodei[i] = mapping->info_nodei[i-1] + mapping->info_nodec[i-1];
1634580bdb30SBarry Smith     ierr = PetscArrayzero(mapping->info_nodec,n);CHKERRQ(ierr);
16351bd0b88eSStefano Zampini     for (i=0;i<n;i++) { mapping->info_nodec[i] = 1; mapping->info_nodei[i][0] = neigh[0]; }
16361bd0b88eSStefano Zampini     for (i=1;i<n_neigh;i++) {
16371bd0b88eSStefano Zampini       PetscInt j;
16381bd0b88eSStefano Zampini 
16391bd0b88eSStefano Zampini       for (j=0;j<n_shared[i];j++) {
16401bd0b88eSStefano Zampini         PetscInt k = shared[i][j];
16411bd0b88eSStefano Zampini 
16421bd0b88eSStefano Zampini         mapping->info_nodei[k][mapping->info_nodec[k]] = neigh[i];
16431bd0b88eSStefano Zampini         mapping->info_nodec[k] += 1;
16441bd0b88eSStefano Zampini       }
16451bd0b88eSStefano Zampini     }
16461bd0b88eSStefano Zampini     for (i=0;i<n;i++) { ierr = PetscSortRemoveDupsInt(&mapping->info_nodec[i],mapping->info_nodei[i]);CHKERRQ(ierr); }
16471bd0b88eSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
16481bd0b88eSStefano Zampini   }
16491bd0b88eSStefano Zampini   if (nnodes)  *nnodes  = n;
16501bd0b88eSStefano Zampini   if (count)   *count   = mapping->info_nodec;
16511bd0b88eSStefano Zampini   if (indices) *indices = mapping->info_nodei;
16521bd0b88eSStefano Zampini   PetscFunctionReturn(0);
16531bd0b88eSStefano Zampini }
16541bd0b88eSStefano Zampini 
16551bd0b88eSStefano Zampini /*@C
16561bd0b88eSStefano Zampini     ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by ISLocalToGlobalMappingGetNodeInfo()
16571bd0b88eSStefano Zampini 
16581bd0b88eSStefano Zampini     Collective on ISLocalToGlobalMapping
16591bd0b88eSStefano Zampini 
16601bd0b88eSStefano Zampini     Input Parameters:
16611bd0b88eSStefano Zampini .   mapping - the mapping from local to global indexing
16621bd0b88eSStefano Zampini 
1663*d8d19677SJose E. Roman     Output Parameters:
16641bd0b88eSStefano Zampini +   nnodes - number of local nodes
16651bd0b88eSStefano Zampini .   count - number of neighboring processors per node
16661bd0b88eSStefano Zampini -   indices - indices of processes sharing the node (sorted)
16671bd0b88eSStefano Zampini 
16681bd0b88eSStefano Zampini     Level: advanced
16691bd0b88eSStefano Zampini 
16701bd0b88eSStefano Zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
16711bd0b88eSStefano Zampini           ISLocalToGlobalMappingGetInfo()
16721bd0b88eSStefano Zampini @*/
16731bd0b88eSStefano Zampini PetscErrorCode  ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping,PetscInt *nnodes,PetscInt *count[],PetscInt **indices[])
16741bd0b88eSStefano Zampini {
16751bd0b88eSStefano Zampini   PetscFunctionBegin;
16761bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
16771bd0b88eSStefano Zampini   if (nnodes)  *nnodes  = 0;
16781bd0b88eSStefano Zampini   if (count)   *count   = NULL;
16791bd0b88eSStefano Zampini   if (indices) *indices = NULL;
16801bd0b88eSStefano Zampini   PetscFunctionReturn(0);
16811bd0b88eSStefano Zampini }
16821bd0b88eSStefano Zampini 
16831bd0b88eSStefano Zampini /*@C
1684107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
168586994e45SJed Brown 
168686994e45SJed Brown    Not Collective
168786994e45SJed Brown 
168886994e45SJed Brown    Input Arguments:
168986994e45SJed Brown . ltog - local to global mapping
169086994e45SJed Brown 
169186994e45SJed Brown    Output Arguments:
1692565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
169386994e45SJed Brown 
169486994e45SJed Brown    Level: advanced
169586994e45SJed Brown 
169695452b02SPatrick Sanan    Notes:
169795452b02SPatrick Sanan     ISLocalToGlobalMappingGetSize() returns the length the this array
1698107e9a97SBarry Smith 
1699107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
170086994e45SJed Brown @*/
17017087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
170286994e45SJed Brown {
170386994e45SJed Brown   PetscFunctionBegin;
170486994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
170586994e45SJed Brown   PetscValidPointer(array,2);
170645b6f7e9SBarry Smith   if (ltog->bs == 1) {
170786994e45SJed Brown     *array = ltog->indices;
170845b6f7e9SBarry Smith   } else {
170945b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
171045b6f7e9SBarry Smith     const PetscInt *ii;
171145b6f7e9SBarry Smith     PetscErrorCode ierr;
171245b6f7e9SBarry Smith 
171345b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
171445b6f7e9SBarry Smith     *array = jj;
171545b6f7e9SBarry Smith     k    = 0;
171645b6f7e9SBarry Smith     ii   = ltog->indices;
171745b6f7e9SBarry Smith     for (i=0; i<n; i++)
171845b6f7e9SBarry Smith       for (j=0; j<bs; j++)
171945b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
172045b6f7e9SBarry Smith   }
172186994e45SJed Brown   PetscFunctionReturn(0);
172286994e45SJed Brown }
172386994e45SJed Brown 
172486994e45SJed Brown /*@C
1725193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
172686994e45SJed Brown 
172786994e45SJed Brown    Not Collective
172886994e45SJed Brown 
172986994e45SJed Brown    Input Arguments:
173086994e45SJed Brown + ltog - local to global mapping
173186994e45SJed Brown - array - array of indices
173286994e45SJed Brown 
173386994e45SJed Brown    Level: advanced
173486994e45SJed Brown 
173586994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
173686994e45SJed Brown @*/
17377087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
173886994e45SJed Brown {
173986994e45SJed Brown   PetscFunctionBegin;
174086994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
174186994e45SJed Brown   PetscValidPointer(array,2);
174245b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
174345b6f7e9SBarry Smith 
174445b6f7e9SBarry Smith   if (ltog->bs > 1) {
174545b6f7e9SBarry Smith     PetscErrorCode ierr;
174645b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
174745b6f7e9SBarry Smith   }
174845b6f7e9SBarry Smith   PetscFunctionReturn(0);
174945b6f7e9SBarry Smith }
175045b6f7e9SBarry Smith 
175145b6f7e9SBarry Smith /*@C
175245b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
175345b6f7e9SBarry Smith 
175445b6f7e9SBarry Smith    Not Collective
175545b6f7e9SBarry Smith 
175645b6f7e9SBarry Smith    Input Arguments:
175745b6f7e9SBarry Smith . ltog - local to global mapping
175845b6f7e9SBarry Smith 
175945b6f7e9SBarry Smith    Output Arguments:
176045b6f7e9SBarry Smith . array - array of indices
176145b6f7e9SBarry Smith 
176245b6f7e9SBarry Smith    Level: advanced
176345b6f7e9SBarry Smith 
176445b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
176545b6f7e9SBarry Smith @*/
176645b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
176745b6f7e9SBarry Smith {
176845b6f7e9SBarry Smith   PetscFunctionBegin;
176945b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
177045b6f7e9SBarry Smith   PetscValidPointer(array,2);
177145b6f7e9SBarry Smith   *array = ltog->indices;
177245b6f7e9SBarry Smith   PetscFunctionReturn(0);
177345b6f7e9SBarry Smith }
177445b6f7e9SBarry Smith 
177545b6f7e9SBarry Smith /*@C
177645b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
177745b6f7e9SBarry Smith 
177845b6f7e9SBarry Smith    Not Collective
177945b6f7e9SBarry Smith 
178045b6f7e9SBarry Smith    Input Arguments:
178145b6f7e9SBarry Smith + ltog - local to global mapping
178245b6f7e9SBarry Smith - array - array of indices
178345b6f7e9SBarry Smith 
178445b6f7e9SBarry Smith    Level: advanced
178545b6f7e9SBarry Smith 
178645b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
178745b6f7e9SBarry Smith @*/
178845b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
178945b6f7e9SBarry Smith {
179045b6f7e9SBarry Smith   PetscFunctionBegin;
179145b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
179245b6f7e9SBarry Smith   PetscValidPointer(array,2);
179386994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
17940298fd71SBarry Smith   *array = NULL;
179586994e45SJed Brown   PetscFunctionReturn(0);
179686994e45SJed Brown }
1797f7efa3c7SJed Brown 
1798f7efa3c7SJed Brown /*@C
1799f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1800f7efa3c7SJed Brown 
1801f7efa3c7SJed Brown    Not Collective
1802f7efa3c7SJed Brown 
1803f7efa3c7SJed Brown    Input Arguments:
1804f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1805f7efa3c7SJed Brown . n - number of mappings to concatenate
1806f7efa3c7SJed Brown - ltogs - local to global mappings
1807f7efa3c7SJed Brown 
1808f7efa3c7SJed Brown    Output Arguments:
1809f7efa3c7SJed Brown . ltogcat - new mapping
1810f7efa3c7SJed Brown 
18119d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
18129d90f715SBarry Smith 
18139d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
18149d90f715SBarry Smith 
1815f7efa3c7SJed Brown    Level: advanced
1816f7efa3c7SJed Brown 
1817f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1818f7efa3c7SJed Brown @*/
1819f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1820f7efa3c7SJed Brown {
1821f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1822f7efa3c7SJed Brown   PetscErrorCode ierr;
1823f7efa3c7SJed Brown 
1824f7efa3c7SJed Brown   PetscFunctionBegin;
1825f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1826f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1827f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1828f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1829f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1830f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1831f7efa3c7SJed Brown     cnt += m;
1832f7efa3c7SJed Brown   }
1833785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1834f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1835f7efa3c7SJed Brown     const PetscInt *subidx;
1836f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1837f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1838580bdb30SBarry Smith     ierr = PetscArraycpy(&idx[cnt],subidx,m);CHKERRQ(ierr);
1839f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1840f7efa3c7SJed Brown     cnt += m;
1841f7efa3c7SJed Brown   }
1842f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1843f7efa3c7SJed Brown   PetscFunctionReturn(0);
1844f7efa3c7SJed Brown }
184504a59952SBarry Smith 
1846413f72f0SBarry Smith /*MC
1847413f72f0SBarry Smith       ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the ISLocalToGlobalMapping object. When ISGlobalToLocalMappingApply() is
1848413f72f0SBarry Smith                                     used this is good for only small and moderate size problems.
1849413f72f0SBarry Smith 
1850413f72f0SBarry Smith    Options Database Keys:
1851a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type basic - select this method
1852413f72f0SBarry Smith 
1853413f72f0SBarry Smith    Level: beginner
1854413f72f0SBarry Smith 
1855413f72f0SBarry Smith .seealso:  ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetType(), ISLOCALTOGLOBALMAPPINGHASH
1856413f72f0SBarry Smith M*/
1857413f72f0SBarry Smith PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)
1858413f72f0SBarry Smith {
1859413f72f0SBarry Smith   PetscFunctionBegin;
1860413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Basic;
1861413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Basic;
1862413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic;
1863413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Basic;
1864413f72f0SBarry Smith   PetscFunctionReturn(0);
1865413f72f0SBarry Smith }
1866413f72f0SBarry Smith 
1867413f72f0SBarry Smith /*MC
1868413f72f0SBarry Smith       ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the ISLocalToGlobalMapping object. When ISGlobalToLocalMappingApply() is
1869ed56e8eaSBarry Smith                                     used this is good for large memory problems.
1870413f72f0SBarry Smith 
1871413f72f0SBarry Smith    Options Database Keys:
1872a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type hash - select this method
1873413f72f0SBarry Smith 
187495452b02SPatrick Sanan    Notes:
187595452b02SPatrick Sanan     This is selected automatically for large problems if the user does not set the type.
1876ed56e8eaSBarry Smith 
1877413f72f0SBarry Smith    Level: beginner
1878413f72f0SBarry Smith 
1879413f72f0SBarry Smith .seealso:  ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetType(), ISLOCALTOGLOBALMAPPINGHASH
1880413f72f0SBarry Smith M*/
1881413f72f0SBarry Smith PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)
1882413f72f0SBarry Smith {
1883413f72f0SBarry Smith   PetscFunctionBegin;
1884413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Hash;
1885413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Hash;
1886413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash;
1887413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Hash;
1888413f72f0SBarry Smith   PetscFunctionReturn(0);
1889413f72f0SBarry Smith }
1890413f72f0SBarry Smith 
1891413f72f0SBarry Smith /*@C
1892413f72f0SBarry Smith     ISLocalToGlobalMappingRegister -  Adds a method for applying a global to local mapping with an ISLocalToGlobalMapping
1893413f72f0SBarry Smith 
1894413f72f0SBarry Smith    Not Collective
1895413f72f0SBarry Smith 
1896413f72f0SBarry Smith    Input Parameters:
1897413f72f0SBarry Smith +  sname - name of a new method
1898413f72f0SBarry Smith -  routine_create - routine to create method context
1899413f72f0SBarry Smith 
1900413f72f0SBarry Smith    Notes:
1901ed56e8eaSBarry Smith    ISLocalToGlobalMappingRegister() may be called multiple times to add several user-defined mappings.
1902413f72f0SBarry Smith 
1903413f72f0SBarry Smith    Sample usage:
1904413f72f0SBarry Smith .vb
1905413f72f0SBarry Smith    ISLocalToGlobalMappingRegister("my_mapper",MyCreate);
1906413f72f0SBarry Smith .ve
1907413f72f0SBarry Smith 
1908ed56e8eaSBarry Smith    Then, your mapping can be chosen with the procedural interface via
1909413f72f0SBarry Smith $     ISLocalToGlobalMappingSetType(ltog,"my_mapper")
1910413f72f0SBarry Smith    or at runtime via the option
1911ed56e8eaSBarry Smith $     -islocaltoglobalmapping_type my_mapper
1912413f72f0SBarry Smith 
1913413f72f0SBarry Smith    Level: advanced
1914413f72f0SBarry Smith 
1915413f72f0SBarry Smith .seealso: ISLocalToGlobalMappingRegisterAll(), ISLocalToGlobalMappingRegisterDestroy(), ISLOCALTOGLOBALMAPPINGBASIC, ISLOCALTOGLOBALMAPPINGHASH
1916413f72f0SBarry Smith 
1917413f72f0SBarry Smith @*/
1918413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRegister(const char sname[],PetscErrorCode (*function)(ISLocalToGlobalMapping))
1919413f72f0SBarry Smith {
1920413f72f0SBarry Smith   PetscErrorCode ierr;
1921413f72f0SBarry Smith 
1922413f72f0SBarry Smith   PetscFunctionBegin;
19231d36bdfdSBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
1924413f72f0SBarry Smith   ierr = PetscFunctionListAdd(&ISLocalToGlobalMappingList,sname,function);CHKERRQ(ierr);
1925413f72f0SBarry Smith   PetscFunctionReturn(0);
1926413f72f0SBarry Smith }
1927413f72f0SBarry Smith 
1928413f72f0SBarry Smith /*@C
1929ed56e8eaSBarry Smith    ISLocalToGlobalMappingSetType - Builds ISLocalToGlobalMapping for a particular global to local mapping approach.
1930413f72f0SBarry Smith 
1931413f72f0SBarry Smith    Logically Collective on ISLocalToGlobalMapping
1932413f72f0SBarry Smith 
1933413f72f0SBarry Smith    Input Parameters:
1934413f72f0SBarry Smith +  ltog - the ISLocalToGlobalMapping object
1935413f72f0SBarry Smith -  type - a known method
1936413f72f0SBarry Smith 
1937413f72f0SBarry Smith    Options Database Key:
1938ed56e8eaSBarry Smith .  -islocaltoglobalmapping_type  <method> - Sets the method; use -help for a list
1939413f72f0SBarry Smith     of available methods (for instance, basic or hash)
1940413f72f0SBarry Smith 
1941413f72f0SBarry Smith    Notes:
1942413f72f0SBarry Smith    See "petsc/include/petscis.h" for available methods
1943413f72f0SBarry Smith 
1944413f72f0SBarry Smith   Normally, it is best to use the ISLocalToGlobalMappingSetFromOptions() command and
1945413f72f0SBarry Smith   then set the ISLocalToGlobalMapping type from the options database rather than by using
1946413f72f0SBarry Smith   this routine.
1947413f72f0SBarry Smith 
1948413f72f0SBarry Smith   Level: intermediate
1949413f72f0SBarry Smith 
1950413f72f0SBarry Smith   Developer Note: ISLocalToGlobalMappingRegister() is used to add new types to ISLocalToGlobalMappingList from which they
1951413f72f0SBarry Smith   are accessed by ISLocalToGlobalMappingSetType().
1952413f72f0SBarry Smith 
1953413f72f0SBarry Smith .seealso: PCSetType(), ISLocalToGlobalMappingType, ISLocalToGlobalMappingRegister(), ISLocalToGlobalMappingCreate()
1954413f72f0SBarry Smith 
1955413f72f0SBarry Smith @*/
1956413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type)
1957413f72f0SBarry Smith {
1958413f72f0SBarry Smith   PetscErrorCode ierr,(*r)(ISLocalToGlobalMapping);
1959413f72f0SBarry Smith   PetscBool      match;
1960413f72f0SBarry Smith 
1961413f72f0SBarry Smith   PetscFunctionBegin;
1962413f72f0SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
1963413f72f0SBarry Smith   PetscValidCharPointer(type,2);
1964413f72f0SBarry Smith 
1965413f72f0SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)ltog,type,&match);CHKERRQ(ierr);
1966413f72f0SBarry Smith   if (match) PetscFunctionReturn(0);
1967413f72f0SBarry Smith 
1968413f72f0SBarry Smith   ierr =  PetscFunctionListFind(ISLocalToGlobalMappingList,type,&r);CHKERRQ(ierr);
1969413f72f0SBarry Smith   if (!r) SETERRQ1(PetscObjectComm((PetscObject)ltog),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested ISLocalToGlobalMapping type %s",type);
1970413f72f0SBarry Smith   /* Destroy the previous private LTOG context */
1971413f72f0SBarry Smith   if (ltog->ops->destroy) {
1972413f72f0SBarry Smith     ierr              = (*ltog->ops->destroy)(ltog);CHKERRQ(ierr);
1973413f72f0SBarry Smith     ltog->ops->destroy = NULL;
1974413f72f0SBarry Smith   }
1975413f72f0SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)ltog,type);CHKERRQ(ierr);
1976413f72f0SBarry Smith   ierr = (*r)(ltog);CHKERRQ(ierr);
1977413f72f0SBarry Smith   PetscFunctionReturn(0);
1978413f72f0SBarry Smith }
1979413f72f0SBarry Smith 
1980413f72f0SBarry Smith PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE;
1981413f72f0SBarry Smith 
1982413f72f0SBarry Smith /*@C
1983413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the IS package.
1984413f72f0SBarry Smith 
1985413f72f0SBarry Smith   Not Collective
1986413f72f0SBarry Smith 
1987413f72f0SBarry Smith   Level: advanced
1988413f72f0SBarry Smith 
1989413f72f0SBarry Smith .seealso:  ISRegister(),  ISLocalToGlobalRegister()
1990413f72f0SBarry Smith @*/
1991413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRegisterAll(void)
1992413f72f0SBarry Smith {
1993413f72f0SBarry Smith   PetscErrorCode ierr;
1994413f72f0SBarry Smith 
1995413f72f0SBarry Smith   PetscFunctionBegin;
1996413f72f0SBarry Smith   if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(0);
1997413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE;
1998413f72f0SBarry Smith 
1999413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic);CHKERRQ(ierr);
2000413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash);CHKERRQ(ierr);
2001413f72f0SBarry Smith   PetscFunctionReturn(0);
2002413f72f0SBarry Smith }
2003