xref: /petsc/src/vec/is/utils/isltog.c (revision 9a535baf3620b7b1d5229355c8a20d219c1a92fe)
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 
432d8d19677SJose E. Roman     Input Parameters:
433a4d96a55SJed Brown +   sf - star forest mapping contiguous local indices to (rank, offset)
434*9a535bafSVaclav Hapla -   start - first global index on this process, or PETSC_DECIDE to compute contiguous global numbering automatically
435a4d96a55SJed Brown 
436a4d96a55SJed Brown     Output Parameter:
437a4d96a55SJed Brown .   mapping - new mapping data structure
438a4d96a55SJed Brown 
439a4d96a55SJed Brown     Level: advanced
440a4d96a55SJed Brown 
441*9a535bafSVaclav Hapla     Notes:
442*9a535bafSVaclav Hapla     If any processor calls this with start = PETSC_DECIDE then all processors must, otherwise the program will hang.
443*9a535bafSVaclav Hapla 
4447e99dc12SLawrence Mitchell .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingSetFromOptions()
445a4d96a55SJed Brown @*/
446a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping)
447a4d96a55SJed Brown {
448a4d96a55SJed Brown   PetscErrorCode ierr;
449a4d96a55SJed Brown   PetscInt       i,maxlocal,nroots,nleaves,*globals,*ltog;
450a4d96a55SJed Brown   const PetscInt *ilocal;
451a4d96a55SJed Brown   MPI_Comm       comm;
452a4d96a55SJed Brown 
453a4d96a55SJed Brown   PetscFunctionBegin;
454a4d96a55SJed Brown   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
455a4d96a55SJed Brown   PetscValidPointer(mapping,3);
456a4d96a55SJed Brown 
457a4d96a55SJed Brown   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
4580298fd71SBarry Smith   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr);
459*9a535bafSVaclav Hapla   if (start == PETSC_DECIDE) {
460*9a535bafSVaclav Hapla     start = 0;
461*9a535bafSVaclav Hapla     ierr = MPI_Exscan(&nroots,&start,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
462*9a535bafSVaclav Hapla   } else if (start < 0) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "start must be nonnegative or PETSC_DECIDE");
463f6e5521dSKarl Rupp   if (ilocal) {
464f6e5521dSKarl Rupp     for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1);
465f6e5521dSKarl Rupp   }
466a4d96a55SJed Brown   else maxlocal = nleaves;
467785e854fSJed Brown   ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr);
468785e854fSJed Brown   ierr = PetscMalloc1(maxlocal,&ltog);CHKERRQ(ierr);
469a4d96a55SJed Brown   for (i=0; i<nroots; i++) globals[i] = start + i;
470a4d96a55SJed Brown   for (i=0; i<maxlocal; i++) ltog[i] = -1;
471ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog,MPI_REPLACE);CHKERRQ(ierr);
472ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog,MPI_REPLACE);CHKERRQ(ierr);
473f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
474a4d96a55SJed Brown   ierr = PetscFree(globals);CHKERRQ(ierr);
475a4d96a55SJed Brown   PetscFunctionReturn(0);
476a4d96a55SJed Brown }
477b46b645bSBarry Smith 
47863fa5c83Sstefano_zampini /*@
47963fa5c83Sstefano_zampini     ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
48063fa5c83Sstefano_zampini 
48163fa5c83Sstefano_zampini     Not collective
48263fa5c83Sstefano_zampini 
48363fa5c83Sstefano_zampini     Input Parameters:
484a2b725a8SWilliam Gropp +   mapping - mapping data structure
485a2b725a8SWilliam Gropp -   bs - the blocksize
48663fa5c83Sstefano_zampini 
48763fa5c83Sstefano_zampini     Level: advanced
48863fa5c83Sstefano_zampini 
48963fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
49063fa5c83Sstefano_zampini @*/
49163fa5c83Sstefano_zampini PetscErrorCode  ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)
49263fa5c83Sstefano_zampini {
493a59f3c4dSstefano_zampini   PetscInt       *nid;
494a59f3c4dSstefano_zampini   const PetscInt *oid;
495a59f3c4dSstefano_zampini   PetscInt       i,cn,on,obs,nn;
49663fa5c83Sstefano_zampini   PetscErrorCode ierr;
49763fa5c83Sstefano_zampini 
49863fa5c83Sstefano_zampini   PetscFunctionBegin;
49963fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
50063fa5c83Sstefano_zampini   if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs);
50163fa5c83Sstefano_zampini   if (bs == mapping->bs) PetscFunctionReturn(0);
50263fa5c83Sstefano_zampini   on  = mapping->n;
50363fa5c83Sstefano_zampini   obs = mapping->bs;
50463fa5c83Sstefano_zampini   oid = mapping->indices;
50563fa5c83Sstefano_zampini   nn  = (on*obs)/bs;
50663fa5c83Sstefano_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);
507a59f3c4dSstefano_zampini 
50863fa5c83Sstefano_zampini   ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr);
509a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingGetIndices(mapping,&oid);CHKERRQ(ierr);
510a59f3c4dSstefano_zampini   for (i=0;i<nn;i++) {
511a59f3c4dSstefano_zampini     PetscInt j;
512a59f3c4dSstefano_zampini     for (j=0,cn=0;j<bs-1;j++) {
513a59f3c4dSstefano_zampini       if (oid[i*bs+j] < 0) { cn++; continue; }
514a59f3c4dSstefano_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]);
515a59f3c4dSstefano_zampini     }
516a59f3c4dSstefano_zampini     if (oid[i*bs+j] < 0) cn++;
5178b7cb0e6Sstefano_zampini     if (cn) {
518a59f3c4dSstefano_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);
519a59f3c4dSstefano_zampini       nid[i] = -1;
5208b7cb0e6Sstefano_zampini     } else {
521a59f3c4dSstefano_zampini       nid[i] = oid[i*bs]/bs;
52263fa5c83Sstefano_zampini     }
52363fa5c83Sstefano_zampini   }
524a59f3c4dSstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(mapping,&oid);CHKERRQ(ierr);
525a59f3c4dSstefano_zampini 
52663fa5c83Sstefano_zampini   mapping->n           = nn;
52763fa5c83Sstefano_zampini   mapping->bs          = bs;
52863fa5c83Sstefano_zampini   ierr                 = PetscFree(mapping->indices);CHKERRQ(ierr);
52963fa5c83Sstefano_zampini   mapping->indices     = nid;
530c9345713Sstefano_zampini   mapping->globalstart = 0;
531c9345713Sstefano_zampini   mapping->globalend   = 0;
5321bd0b88eSStefano Zampini 
5331bd0b88eSStefano Zampini   /* reset the cached information */
5341bd0b88eSStefano Zampini   ierr = PetscFree(mapping->info_procs);CHKERRQ(ierr);
5351bd0b88eSStefano Zampini   ierr = PetscFree(mapping->info_numprocs);CHKERRQ(ierr);
5361bd0b88eSStefano Zampini   if (mapping->info_indices) {
5371bd0b88eSStefano Zampini     PetscInt i;
5381bd0b88eSStefano Zampini 
5391bd0b88eSStefano Zampini     ierr = PetscFree((mapping->info_indices)[0]);CHKERRQ(ierr);
5401bd0b88eSStefano Zampini     for (i=1; i<mapping->info_nproc; i++) {
5411bd0b88eSStefano Zampini       ierr = PetscFree(mapping->info_indices[i]);CHKERRQ(ierr);
5421bd0b88eSStefano Zampini     }
5431bd0b88eSStefano Zampini     ierr = PetscFree(mapping->info_indices);CHKERRQ(ierr);
5441bd0b88eSStefano Zampini   }
5451bd0b88eSStefano Zampini   mapping->info_cached = PETSC_FALSE;
5461bd0b88eSStefano Zampini 
547413f72f0SBarry Smith   if (mapping->ops->destroy) {
548413f72f0SBarry Smith     ierr = (*mapping->ops->destroy)(mapping);CHKERRQ(ierr);
549413f72f0SBarry Smith   }
55063fa5c83Sstefano_zampini   PetscFunctionReturn(0);
55163fa5c83Sstefano_zampini }
55263fa5c83Sstefano_zampini 
55345b6f7e9SBarry Smith /*@
55445b6f7e9SBarry Smith     ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
55545b6f7e9SBarry Smith     ordering and a global parallel ordering.
55645b6f7e9SBarry Smith 
55745b6f7e9SBarry Smith     Not Collective
55845b6f7e9SBarry Smith 
55945b6f7e9SBarry Smith     Input Parameters:
56045b6f7e9SBarry Smith .   mapping - mapping data structure
56145b6f7e9SBarry Smith 
56245b6f7e9SBarry Smith     Output Parameter:
56345b6f7e9SBarry Smith .   bs - the blocksize
56445b6f7e9SBarry Smith 
56545b6f7e9SBarry Smith     Level: advanced
56645b6f7e9SBarry Smith 
56745b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
56845b6f7e9SBarry Smith @*/
56945b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs)
57045b6f7e9SBarry Smith {
57145b6f7e9SBarry Smith   PetscFunctionBegin;
572cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
57345b6f7e9SBarry Smith   *bs = mapping->bs;
57445b6f7e9SBarry Smith   PetscFunctionReturn(0);
57545b6f7e9SBarry Smith }
57645b6f7e9SBarry Smith 
577ba5bb76aSSatish Balay /*@
57890f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
57990f02eecSBarry Smith     ordering and a global parallel ordering.
5802362add9SBarry Smith 
58189d82c54SBarry Smith     Not Collective, but communicator may have more than one process
582b9cd556bSLois Curfman McInnes 
5832362add9SBarry Smith     Input Parameters:
58489d82c54SBarry Smith +   comm - MPI communicator
585f0413b6fSBarry Smith .   bs - the block size
58628bc9809SBarry Smith .   n - the number of local elements divided by the block size, or equivalently the number of block indices
58728bc9809SBarry 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
588d5ad8652SBarry Smith -   mode - see PetscCopyMode
5892362add9SBarry Smith 
590a997ad1aSLois Curfman McInnes     Output Parameter:
59190f02eecSBarry Smith .   mapping - new mapping data structure
5922362add9SBarry Smith 
59395452b02SPatrick Sanan     Notes:
59495452b02SPatrick Sanan     There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
595413f72f0SBarry Smith 
5969a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
597413f72f0SBarry 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.
598413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
599413f72f0SBarry Smith 
600a997ad1aSLois Curfman McInnes     Level: advanced
601a997ad1aSLois Curfman McInnes 
602413f72f0SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingSetFromOptions(), ISLOCALTOGLOBALMAPPINGBASIC, ISLOCALTOGLOBALMAPPINGHASH
603413f72f0SBarry Smith           ISLocalToGlobalMappingSetType(), ISLocalToGlobalMappingType
6042362add9SBarry Smith @*/
60560c7cefcSBarry Smith PetscErrorCode  ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping)
6062362add9SBarry Smith {
6076849ba73SBarry Smith   PetscErrorCode ierr;
60832dcc486SBarry Smith   PetscInt       *in;
609b46b645bSBarry Smith 
610b46b645bSBarry Smith   PetscFunctionBegin;
611064a246eSJacob Faibussowitsch   if (n) PetscValidIntPointer(indices,4);
612064a246eSJacob Faibussowitsch   PetscValidPointer(mapping,6);
613b46b645bSBarry Smith 
6140298fd71SBarry Smith   *mapping = NULL;
615607a6623SBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
6162362add9SBarry Smith 
61773107ff1SLisandro Dalcin   ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS",
61860c7cefcSBarry Smith                            comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr);
619d4bb536fSBarry Smith   (*mapping)->n             = n;
620f0413b6fSBarry Smith   (*mapping)->bs            = bs;
621268a049cSStefano Zampini   (*mapping)->info_cached   = PETSC_FALSE;
622268a049cSStefano Zampini   (*mapping)->info_free     = PETSC_FALSE;
623268a049cSStefano Zampini   (*mapping)->info_procs    = NULL;
624268a049cSStefano Zampini   (*mapping)->info_numprocs = NULL;
625268a049cSStefano Zampini   (*mapping)->info_indices  = NULL;
6261bd0b88eSStefano Zampini   (*mapping)->info_nodec    = NULL;
6271bd0b88eSStefano Zampini   (*mapping)->info_nodei    = NULL;
628413f72f0SBarry Smith 
629413f72f0SBarry Smith   (*mapping)->ops->globaltolocalmappingapply      = NULL;
630413f72f0SBarry Smith   (*mapping)->ops->globaltolocalmappingapplyblock = NULL;
631413f72f0SBarry Smith   (*mapping)->ops->destroy                        = NULL;
632d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
633785e854fSJed Brown     ierr = PetscMalloc1(n,&in);CHKERRQ(ierr);
634580bdb30SBarry Smith     ierr = PetscArraycpy(in,indices,n);CHKERRQ(ierr);
635d5ad8652SBarry Smith     (*mapping)->indices = in;
6366389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
6376389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
6386389a1a1SBarry Smith     (*mapping)->indices = (PetscInt*)indices;
6396389a1a1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr);
6406389a1a1SBarry Smith   }
64160c7cefcSBarry Smith   else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER");
6423a40ed3dSBarry Smith   PetscFunctionReturn(0);
6432362add9SBarry Smith }
6442362add9SBarry Smith 
645413f72f0SBarry Smith PetscFunctionList ISLocalToGlobalMappingList = NULL;
646413f72f0SBarry Smith 
64790f02eecSBarry Smith /*@
6487e99dc12SLawrence Mitchell    ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database.
6497e99dc12SLawrence Mitchell 
6507e99dc12SLawrence Mitchell    Not collective
6517e99dc12SLawrence Mitchell 
6527e99dc12SLawrence Mitchell    Input Parameters:
6537e99dc12SLawrence Mitchell .  mapping - mapping data structure
6547e99dc12SLawrence Mitchell 
6557e99dc12SLawrence Mitchell    Level: advanced
6567e99dc12SLawrence Mitchell 
6577e99dc12SLawrence Mitchell @*/
6587e99dc12SLawrence Mitchell PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)
6597e99dc12SLawrence Mitchell {
6607e99dc12SLawrence Mitchell   PetscErrorCode             ierr;
661413f72f0SBarry Smith   char                       type[256];
662413f72f0SBarry Smith   ISLocalToGlobalMappingType defaulttype = "Not set";
6637e99dc12SLawrence Mitchell   PetscBool                  flg;
6647e99dc12SLawrence Mitchell 
6657e99dc12SLawrence Mitchell   PetscFunctionBegin;
6667e99dc12SLawrence Mitchell   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
667413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegisterAll();CHKERRQ(ierr);
6687e99dc12SLawrence Mitchell   ierr = PetscObjectOptionsBegin((PetscObject)mapping);CHKERRQ(ierr);
669413f72f0SBarry Smith   ierr = PetscOptionsFList("-islocaltoglobalmapping_type","ISLocalToGlobalMapping method","ISLocalToGlobalMappingSetType",ISLocalToGlobalMappingList,(char*)(((PetscObject)mapping)->type_name) ? ((PetscObject)mapping)->type_name : defaulttype,type,256,&flg);CHKERRQ(ierr);
670413f72f0SBarry Smith   if (flg) {
671413f72f0SBarry Smith     ierr = ISLocalToGlobalMappingSetType(mapping,type);CHKERRQ(ierr);
672413f72f0SBarry Smith   }
6737e99dc12SLawrence Mitchell   ierr = PetscOptionsEnd();CHKERRQ(ierr);
6747e99dc12SLawrence Mitchell   PetscFunctionReturn(0);
6757e99dc12SLawrence Mitchell }
6767e99dc12SLawrence Mitchell 
6777e99dc12SLawrence Mitchell /*@
67890f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
67990f02eecSBarry Smith    ordering and a global parallel ordering.
68090f02eecSBarry Smith 
6810f5bd95cSBarry Smith    Note Collective
682b9cd556bSLois Curfman McInnes 
68390f02eecSBarry Smith    Input Parameters:
68490f02eecSBarry Smith .  mapping - mapping data structure
68590f02eecSBarry Smith 
686a997ad1aSLois Curfman McInnes    Level: advanced
687a997ad1aSLois Curfman McInnes 
6883acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
68990f02eecSBarry Smith @*/
6906bf464f9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
69190f02eecSBarry Smith {
692dfbe8321SBarry Smith   PetscErrorCode ierr;
6935fd66863SKarl Rupp 
6943a40ed3dSBarry Smith   PetscFunctionBegin;
6956bf464f9SBarry Smith   if (!*mapping) PetscFunctionReturn(0);
6966bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1);
6974c8fdceaSLisandro Dalcin   if (--((PetscObject)(*mapping))->refct > 0) {*mapping = NULL;PetscFunctionReturn(0);}
6986bf464f9SBarry Smith   ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr);
699268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr);
700268a049cSStefano Zampini   ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr);
701268a049cSStefano Zampini   if ((*mapping)->info_indices) {
702268a049cSStefano Zampini     PetscInt i;
703268a049cSStefano Zampini 
704268a049cSStefano Zampini     ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr);
705268a049cSStefano Zampini     for (i=1; i<(*mapping)->info_nproc; i++) {
706268a049cSStefano Zampini       ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr);
707268a049cSStefano Zampini     }
708268a049cSStefano Zampini     ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr);
709268a049cSStefano Zampini   }
7101bd0b88eSStefano Zampini   if ((*mapping)->info_nodei) {
7111bd0b88eSStefano Zampini     ierr = PetscFree(((*mapping)->info_nodei)[0]);CHKERRQ(ierr);
7121bd0b88eSStefano Zampini   }
713071fcb05SBarry Smith   ierr = PetscFree2((*mapping)->info_nodec,(*mapping)->info_nodei);CHKERRQ(ierr);
714413f72f0SBarry Smith   if ((*mapping)->ops->destroy) {
715413f72f0SBarry Smith     ierr = (*(*mapping)->ops->destroy)(*mapping);CHKERRQ(ierr);
716413f72f0SBarry Smith   }
717d38fa0fbSBarry Smith   ierr     = PetscHeaderDestroy(mapping);CHKERRQ(ierr);
7184c8fdceaSLisandro Dalcin   *mapping = NULL;
7193a40ed3dSBarry Smith   PetscFunctionReturn(0);
72090f02eecSBarry Smith }
72190f02eecSBarry Smith 
72290f02eecSBarry Smith /*@
7233acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
7243acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
7253acfe500SLois Curfman McInnes     context.
72690f02eecSBarry Smith 
7274cb36875SStefano Zampini     Collective on is
728b9cd556bSLois Curfman McInnes 
72990f02eecSBarry Smith     Input Parameters:
730b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
731b9cd556bSLois Curfman McInnes -   is - index set in local numbering
73290f02eecSBarry Smith 
73390f02eecSBarry Smith     Output Parameters:
73490f02eecSBarry Smith .   newis - index set in global numbering
73590f02eecSBarry Smith 
7364cb36875SStefano Zampini     Notes:
7374cb36875SStefano Zampini     The output IS will have the same communicator of the input IS.
7384cb36875SStefano Zampini 
739a997ad1aSLois Curfman McInnes     Level: advanced
740a997ad1aSLois Curfman McInnes 
74190f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
742d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
74390f02eecSBarry Smith @*/
7447087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis)
74590f02eecSBarry Smith {
7466849ba73SBarry Smith   PetscErrorCode ierr;
747e24637baSBarry Smith   PetscInt       n,*idxout;
7485d0c19d7SBarry Smith   const PetscInt *idxin;
7493a40ed3dSBarry Smith 
7503a40ed3dSBarry Smith   PetscFunctionBegin;
7510700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
7520700a824SBarry Smith   PetscValidHeaderSpecific(is,IS_CLASSID,2);
7534482741eSBarry Smith   PetscValidPointer(newis,3);
75490f02eecSBarry Smith 
7553b9aefa3SBarry Smith   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
75690f02eecSBarry Smith   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
757785e854fSJed Brown   ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
758e24637baSBarry Smith   ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr);
7593b9aefa3SBarry Smith   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
760543f3098SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
7613a40ed3dSBarry Smith   PetscFunctionReturn(0);
76290f02eecSBarry Smith }
76390f02eecSBarry Smith 
764b89cb25eSSatish Balay /*@
7653acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
7663acfe500SLois Curfman McInnes    and converts them to the global numbering.
76790f02eecSBarry Smith 
768b9cd556bSLois Curfman McInnes    Not collective
769b9cd556bSLois Curfman McInnes 
770bb25748dSBarry Smith    Input Parameters:
771b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
772bb25748dSBarry Smith .  N - number of integers
773b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
774bb25748dSBarry Smith 
775bb25748dSBarry Smith    Output Parameter:
776bb25748dSBarry Smith .  out - indices in global numbering
777bb25748dSBarry Smith 
778b9cd556bSLois Curfman McInnes    Notes:
779b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
780d4bb536fSBarry Smith 
781a997ad1aSLois Curfman McInnes    Level: advanced
782a997ad1aSLois Curfman McInnes 
78345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
7840752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
785d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
786bb25748dSBarry Smith 
787afcb2eb5SJed Brown @*/
788afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
789afcb2eb5SJed Brown {
790cbc1caf0SMatthew G. Knepley   PetscInt i,bs,Nmax;
79145b6f7e9SBarry Smith 
79245b6f7e9SBarry Smith   PetscFunctionBegin;
793cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
794cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
795cbc1caf0SMatthew G. Knepley   Nmax = bs*mapping->n;
79645b6f7e9SBarry Smith   if (bs == 1) {
797cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
79845b6f7e9SBarry Smith     for (i=0; i<N; i++) {
79945b6f7e9SBarry Smith       if (in[i] < 0) {
80045b6f7e9SBarry Smith         out[i] = in[i];
80145b6f7e9SBarry Smith         continue;
80245b6f7e9SBarry Smith       }
803e24637baSBarry 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);
80445b6f7e9SBarry Smith       out[i] = idx[in[i]];
80545b6f7e9SBarry Smith     }
80645b6f7e9SBarry Smith   } else {
807cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
80845b6f7e9SBarry Smith     for (i=0; i<N; i++) {
80945b6f7e9SBarry Smith       if (in[i] < 0) {
81045b6f7e9SBarry Smith         out[i] = in[i];
81145b6f7e9SBarry Smith         continue;
81245b6f7e9SBarry Smith       }
813e24637baSBarry 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);
81445b6f7e9SBarry Smith       out[i] = idx[in[i]/bs]*bs + (in[i] % bs);
81545b6f7e9SBarry Smith     }
81645b6f7e9SBarry Smith   }
81745b6f7e9SBarry Smith   PetscFunctionReturn(0);
81845b6f7e9SBarry Smith }
81945b6f7e9SBarry Smith 
82045b6f7e9SBarry Smith /*@
8216006e8d2SBarry Smith    ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
82245b6f7e9SBarry Smith 
82345b6f7e9SBarry Smith    Not collective
82445b6f7e9SBarry Smith 
82545b6f7e9SBarry Smith    Input Parameters:
82645b6f7e9SBarry Smith +  mapping - the local to global mapping context
82745b6f7e9SBarry Smith .  N - number of integers
8286006e8d2SBarry Smith -  in - input indices in local block numbering
82945b6f7e9SBarry Smith 
83045b6f7e9SBarry Smith    Output Parameter:
8316006e8d2SBarry Smith .  out - indices in global block numbering
83245b6f7e9SBarry Smith 
83345b6f7e9SBarry Smith    Notes:
83445b6f7e9SBarry Smith    The in and out array parameters may be identical.
83545b6f7e9SBarry Smith 
8366006e8d2SBarry Smith    Example:
8376006e8d2SBarry 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
8386006e8d2SBarry Smith      (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
8396006e8d2SBarry Smith 
84045b6f7e9SBarry Smith    Level: advanced
84145b6f7e9SBarry Smith 
84245b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
84345b6f7e9SBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
84445b6f7e9SBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
84545b6f7e9SBarry Smith 
84645b6f7e9SBarry Smith @*/
84745b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])
84845b6f7e9SBarry Smith {
849cbc1caf0SMatthew G. Knepley 
850cbc1caf0SMatthew G. Knepley   PetscFunctionBegin;
851cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
852cbc1caf0SMatthew G. Knepley   {
853afcb2eb5SJed Brown     PetscInt i,Nmax = mapping->n;
854afcb2eb5SJed Brown     const PetscInt *idx = mapping->indices;
855d4bb536fSBarry Smith 
856afcb2eb5SJed Brown     for (i=0; i<N; i++) {
857afcb2eb5SJed Brown       if (in[i] < 0) {
858afcb2eb5SJed Brown         out[i] = in[i];
859afcb2eb5SJed Brown         continue;
860afcb2eb5SJed Brown       }
861e24637baSBarry 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);
862afcb2eb5SJed Brown       out[i] = idx[in[i]];
863afcb2eb5SJed Brown     }
864cbc1caf0SMatthew G. Knepley   }
865afcb2eb5SJed Brown   PetscFunctionReturn(0);
866afcb2eb5SJed Brown }
867d4bb536fSBarry Smith 
8687e99dc12SLawrence Mitchell /*@
869a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
870a997ad1aSLois Curfman McInnes     specified with a global numbering.
871d4bb536fSBarry Smith 
872b9cd556bSLois Curfman McInnes     Not collective
873b9cd556bSLois Curfman McInnes 
874d4bb536fSBarry Smith     Input Parameters:
875b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
8760040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
877d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
878d4bb536fSBarry Smith .   n - number of global indices to map
879b9cd556bSLois Curfman McInnes -   idx - global indices to map
880d4bb536fSBarry Smith 
881d4bb536fSBarry Smith     Output Parameters:
882b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
883b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
884e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
8850298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
886e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
887e182c471SBarry Smith              a second time to set the values.
888d4bb536fSBarry Smith 
889b9cd556bSLois Curfman McInnes     Notes:
8900298fd71SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
891d4bb536fSBarry Smith 
8929a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
893413f72f0SBarry 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.
894413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
8950f5bd95cSBarry Smith 
896a997ad1aSLois Curfman McInnes     Level: advanced
897a997ad1aSLois Curfman McInnes 
89832fd6b96SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
89932fd6b96SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
90032fd6b96SBarry Smith 
9019d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),
902413f72f0SBarry Smith           ISLocalToGlobalMappingDestroy()
903d4bb536fSBarry Smith @*/
904413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
905d4bb536fSBarry Smith {
9069d90f715SBarry Smith   PetscErrorCode ierr;
9079d90f715SBarry Smith 
9089d90f715SBarry Smith   PetscFunctionBegin;
9099d90f715SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
910413f72f0SBarry Smith   if (!mapping->data) {
911413f72f0SBarry Smith     ierr = ISGlobalToLocalMappingSetUp(mapping);CHKERRQ(ierr);
9129d90f715SBarry Smith   }
913413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingapply)(mapping,type,n,idx,nout,idxout);CHKERRQ(ierr);
9149d90f715SBarry Smith   PetscFunctionReturn(0);
9159d90f715SBarry Smith }
9169d90f715SBarry Smith 
917d4fe737eSStefano Zampini /*@
918d4fe737eSStefano Zampini     ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering
919d4fe737eSStefano Zampini     a new index set using the local numbering defined in an ISLocalToGlobalMapping
920d4fe737eSStefano Zampini     context.
921d4fe737eSStefano Zampini 
922d4fe737eSStefano Zampini     Not collective
923d4fe737eSStefano Zampini 
924d4fe737eSStefano Zampini     Input Parameters:
925d4fe737eSStefano Zampini +   mapping - mapping between local and global numbering
9260040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
9272785b321SStefano Zampini            IS_GTOLM_DROP - drops the indices with no local value from the output list
928d4fe737eSStefano Zampini -   is - index set in global numbering
929d4fe737eSStefano Zampini 
930d4fe737eSStefano Zampini     Output Parameters:
931d4fe737eSStefano Zampini .   newis - index set in local numbering
932d4fe737eSStefano Zampini 
9334cb36875SStefano Zampini     Notes:
9344cb36875SStefano Zampini     The output IS will be sequential, as it encodes a purely local operation
9354cb36875SStefano Zampini 
936d4fe737eSStefano Zampini     Level: advanced
937d4fe737eSStefano Zampini 
938d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
939d4fe737eSStefano Zampini           ISLocalToGlobalMappingDestroy()
940d4fe737eSStefano Zampini @*/
941413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,IS is,IS *newis)
942d4fe737eSStefano Zampini {
943d4fe737eSStefano Zampini   PetscErrorCode ierr;
944d4fe737eSStefano Zampini   PetscInt       n,nout,*idxout;
945d4fe737eSStefano Zampini   const PetscInt *idxin;
946d4fe737eSStefano Zampini 
947d4fe737eSStefano Zampini   PetscFunctionBegin;
948d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
949d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is,IS_CLASSID,3);
950d4fe737eSStefano Zampini   PetscValidPointer(newis,4);
951d4fe737eSStefano Zampini 
952d4fe737eSStefano Zampini   ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
953d4fe737eSStefano Zampini   ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr);
954d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
955d4fe737eSStefano Zampini     ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr);
956d4fe737eSStefano Zampini   } else {
957d4fe737eSStefano Zampini     ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr);
958d4fe737eSStefano Zampini     ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr);
959d4fe737eSStefano Zampini   }
960d4fe737eSStefano Zampini   ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr);
961d4fe737eSStefano Zampini   ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr);
9624cb36875SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr);
963d4fe737eSStefano Zampini   PetscFunctionReturn(0);
964d4fe737eSStefano Zampini }
965d4fe737eSStefano Zampini 
9669d90f715SBarry Smith /*@
9679d90f715SBarry Smith     ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
9689d90f715SBarry Smith     specified with a block global numbering.
9699d90f715SBarry Smith 
9709d90f715SBarry Smith     Not collective
9719d90f715SBarry Smith 
9729d90f715SBarry Smith     Input Parameters:
9739d90f715SBarry Smith +   mapping - mapping between local and global numbering
9740040bde1SJunchao Zhang .   type - IS_GTOLM_MASK - maps global indices with no local value to -1 in the output list (i.e., mask them)
9759d90f715SBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
9769d90f715SBarry Smith .   n - number of global indices to map
9779d90f715SBarry Smith -   idx - global indices to map
9789d90f715SBarry Smith 
9799d90f715SBarry Smith     Output Parameters:
9809d90f715SBarry Smith +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
9819d90f715SBarry Smith -   idxout - local index of each global index, one must pass in an array long enough
9829d90f715SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with
9839d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
9849d90f715SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApplyBlock()
9859d90f715SBarry Smith              a second time to set the values.
9869d90f715SBarry Smith 
9879d90f715SBarry Smith     Notes:
9889d90f715SBarry Smith     Either nout or idxout may be NULL. idx and idxout may be identical.
9899d90f715SBarry Smith 
9909a7b7924SJed Brown     For "small" problems when using ISGlobalToLocalMappingApply() and ISGlobalToLocalMappingApplyBlock(), the ISLocalToGlobalMappingType of ISLOCALTOGLOBALMAPPINGBASIC will be used;
991413f72f0SBarry 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.
992413f72f0SBarry Smith     Use ISLocalToGlobalMappingSetType() or call ISLocalToGlobalMappingSetFromOptions() with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
9939d90f715SBarry Smith 
9949d90f715SBarry Smith     Level: advanced
9959d90f715SBarry Smith 
9969d90f715SBarry Smith     Developer Note: The manual page states that idx and idxout may be identical but the calling
9979d90f715SBarry Smith        sequence declares idx as const so it cannot be the same as idxout.
9989d90f715SBarry Smith 
9999d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(),
1000413f72f0SBarry Smith           ISLocalToGlobalMappingDestroy()
10019d90f715SBarry Smith @*/
1002413f72f0SBarry Smith PetscErrorCode  ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,
10039d90f715SBarry Smith                                                  PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[])
10049d90f715SBarry Smith {
10056849ba73SBarry Smith   PetscErrorCode ierr;
1006d4bb536fSBarry Smith 
10073a40ed3dSBarry Smith   PetscFunctionBegin;
10080700a824SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1009413f72f0SBarry Smith   if (!mapping->data) {
1010413f72f0SBarry Smith     ierr = ISGlobalToLocalMappingSetUp(mapping);CHKERRQ(ierr);
1011d4bb536fSBarry Smith   }
1012413f72f0SBarry Smith   ierr = (*mapping->ops->globaltolocalmappingapplyblock)(mapping,type,n,idx,nout,idxout);CHKERRQ(ierr);
10133a40ed3dSBarry Smith   PetscFunctionReturn(0);
1014d4bb536fSBarry Smith }
101590f02eecSBarry Smith 
101689d82c54SBarry Smith /*@C
10176a818285SBarry Smith     ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
101889d82c54SBarry Smith      each index shared by more than one processor
101989d82c54SBarry Smith 
102089d82c54SBarry Smith     Collective on ISLocalToGlobalMapping
102189d82c54SBarry Smith 
1022f899ff85SJose E. Roman     Input Parameter:
102389d82c54SBarry Smith .   mapping - the mapping from local to global indexing
102489d82c54SBarry Smith 
1025d8d19677SJose E. Roman     Output Parameters:
102689d82c54SBarry Smith +   nproc - number of processors that are connected to this one
102789d82c54SBarry Smith .   proc - neighboring processors
102807b52d57SBarry Smith .   numproc - number of indices for each subdomain (processor)
10293463a7baSJed Brown -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
103089d82c54SBarry Smith 
103189d82c54SBarry Smith     Level: advanced
103289d82c54SBarry Smith 
10332cfcea29SBarry Smith     Fortran Usage:
10342cfcea29SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
10352cfcea29SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
10362cfcea29SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
10372cfcea29SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
10382cfcea29SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
10392cfcea29SBarry Smith 
104007b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
104107b52d57SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
104289d82c54SBarry Smith @*/
10436a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
104489d82c54SBarry Smith {
10456849ba73SBarry Smith   PetscErrorCode ierr;
1046268a049cSStefano Zampini 
1047268a049cSStefano Zampini   PetscFunctionBegin;
1048268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1049268a049cSStefano Zampini   if (mapping->info_cached) {
1050268a049cSStefano Zampini     *nproc    = mapping->info_nproc;
1051268a049cSStefano Zampini     *procs    = mapping->info_procs;
1052268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
1053268a049cSStefano Zampini     *indices  = mapping->info_indices;
1054268a049cSStefano Zampini   } else {
1055268a049cSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
1056268a049cSStefano Zampini   }
1057268a049cSStefano Zampini   PetscFunctionReturn(0);
1058268a049cSStefano Zampini }
1059268a049cSStefano Zampini 
1060268a049cSStefano Zampini static PetscErrorCode  ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
1061268a049cSStefano Zampini {
1062268a049cSStefano Zampini   PetscErrorCode ierr;
106397f1f81fSBarry Smith   PetscMPIInt    size,rank,tag1,tag2,tag3,*len,*source,imdex;
106432dcc486SBarry Smith   PetscInt       i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices;
106532dcc486SBarry Smith   PetscInt       *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc;
106697f1f81fSBarry Smith   PetscInt       cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned;
106732dcc486SBarry Smith   PetscInt       node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp;
106832dcc486SBarry Smith   PetscInt       first_procs,first_numprocs,*first_indices;
106989d82c54SBarry Smith   MPI_Request    *recv_waits,*send_waits;
107030dcb7c9SBarry Smith   MPI_Status     recv_status,*send_status,*recv_statuses;
1071ce94432eSBarry Smith   MPI_Comm       comm;
1072ace3abfcSBarry Smith   PetscBool      debug = PETSC_FALSE;
107389d82c54SBarry Smith 
107489d82c54SBarry Smith   PetscFunctionBegin;
1075ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr);
1076ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
1077ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
107824cf384cSBarry Smith   if (size == 1) {
107924cf384cSBarry Smith     *nproc         = 0;
10800298fd71SBarry Smith     *procs         = NULL;
108195dccacaSBarry Smith     ierr           = PetscNew(numprocs);CHKERRQ(ierr);
10821e2105dcSBarry Smith     (*numprocs)[0] = 0;
108395dccacaSBarry Smith     ierr           = PetscNew(indices);CHKERRQ(ierr);
10840298fd71SBarry Smith     (*indices)[0]  = NULL;
1085268a049cSStefano Zampini     /* save info for reuse */
1086268a049cSStefano Zampini     mapping->info_nproc = *nproc;
1087268a049cSStefano Zampini     mapping->info_procs = *procs;
1088268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
1089268a049cSStefano Zampini     mapping->info_indices = *indices;
1090268a049cSStefano Zampini     mapping->info_cached = PETSC_TRUE;
109124cf384cSBarry Smith     PetscFunctionReturn(0);
109224cf384cSBarry Smith   }
109324cf384cSBarry Smith 
1094c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr);
109507b52d57SBarry Smith 
10963677ff5aSBarry Smith   /*
10976a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
10983677ff5aSBarry Smith 
10993677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
11003677ff5aSBarry Smith            numbering, just for this routine.
11013677ff5aSBarry Smith 
11023677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
11033677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
11043677ff5aSBarry Smith 
11053677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
11063677ff5aSBarry Smith 
11073677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
11083677ff5aSBarry Smith            local subdomain
11093677ff5aSBarry Smith   */
111024cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr);
111124cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr);
111224cf384cSBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr);
111389d82c54SBarry Smith 
111489d82c54SBarry Smith   for (i=0; i<n; i++) {
111589d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
111689d82c54SBarry Smith   }
1117820f2d46SBarry Smith   ierr   = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRMPI(ierr);
111878058e43SBarry Smith   Ng++;
111955b25c41SPierre Jolivet   ierr   = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
112055b25c41SPierre Jolivet   ierr   = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1121bc8ff85bSBarry Smith   scale  = Ng/size + 1;
1122a2e34c3dSBarry Smith   ng     = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng);
1123caba0dd0SBarry Smith   rstart = scale*rank;
112489d82c54SBarry Smith 
112589d82c54SBarry Smith   /* determine ownership ranges of global indices */
1126785e854fSJed Brown   ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr);
1127580bdb30SBarry Smith   ierr = PetscArrayzero(nprocs,2*size);CHKERRQ(ierr);
112889d82c54SBarry Smith 
112989d82c54SBarry Smith   /* determine owners of each local node  */
1130785e854fSJed Brown   ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr);
113189d82c54SBarry Smith   for (i=0; i<n; i++) {
11323677ff5aSBarry Smith     proc             = lindices[i]/scale; /* processor that globally owns this index */
113327c402fcSBarry Smith     nprocs[2*proc+1] = 1;                 /* processor globally owns at least one of ours */
11343677ff5aSBarry Smith     owner[i]         = proc;
113527c402fcSBarry Smith     nprocs[2*proc]++;                     /* count of how many that processor globally owns of ours */
113689d82c54SBarry Smith   }
113727c402fcSBarry Smith   nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1];
11387904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr);
113989d82c54SBarry Smith 
114089d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
114127c402fcSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
11427904a332SBarry Smith   ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr);
114389d82c54SBarry Smith 
114489d82c54SBarry Smith   /* post receives for owned rows */
1145785e854fSJed Brown   ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr);
1146854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
114789d82c54SBarry Smith   for (i=0; i<nrecvs; i++) {
1148ffc4695bSBarry Smith     ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRMPI(ierr);
114989d82c54SBarry Smith   }
115089d82c54SBarry Smith 
115189d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
1152854ce69bSBarry Smith   ierr      = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr);
1153854ce69bSBarry Smith   ierr      = PetscMalloc1(size+1,&starts);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   for (i=0; i<n; i++) {
115789d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
115830dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
115989d82c54SBarry Smith   }
116089d82c54SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
116189d82c54SBarry Smith   starts[0] = 0;
1162f6e5521dSKarl Rupp   for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2];
116389d82c54SBarry Smith 
116489d82c54SBarry Smith   /* send the messages */
1165854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
1166854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr);
116789d82c54SBarry Smith   cnt = 0;
116889d82c54SBarry Smith   for (i=0; i<size; i++) {
116927c402fcSBarry Smith     if (nprocs[2*i]) {
117055b25c41SPierre Jolivet       ierr      = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRMPI(ierr);
117130dcb7c9SBarry Smith       dest[cnt] = i;
117289d82c54SBarry Smith       cnt++;
117389d82c54SBarry Smith     }
117489d82c54SBarry Smith   }
117589d82c54SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
117689d82c54SBarry Smith 
117789d82c54SBarry Smith   /* wait on receives */
1178854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr);
1179854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr);
118089d82c54SBarry Smith   cnt  = nrecvs;
1181580bdb30SBarry Smith   ierr = PetscCalloc1(ng+1,&nownedsenders);CHKERRQ(ierr);
118289d82c54SBarry Smith   while (cnt) {
1183ffc4695bSBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRMPI(ierr);
118489d82c54SBarry Smith     /* unpack receives into our local space */
118555b25c41SPierre Jolivet     ierr          = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRMPI(ierr);
118689d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
118730dcb7c9SBarry Smith     len[imdex]    = len[imdex]/2;
1188caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
118930dcb7c9SBarry Smith     for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++;
119089d82c54SBarry Smith     cnt--;
119189d82c54SBarry Smith   }
119289d82c54SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
119389d82c54SBarry Smith 
119430dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1195bc8ff85bSBarry Smith   nowned  = 0;
1196bc8ff85bSBarry Smith   nownedm = 0;
1197bc8ff85bSBarry Smith   for (i=0; i<ng; i++) {
1198bc8ff85bSBarry Smith     if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;}
1199bc8ff85bSBarry Smith   }
1200bc8ff85bSBarry Smith 
1201bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
1202854ce69bSBarry Smith   ierr      = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr);
1203854ce69bSBarry Smith   ierr      = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr);
1204bc8ff85bSBarry Smith   starts[0] = 0;
1205bc8ff85bSBarry Smith   for (i=1; i<ng; i++) {
1206bc8ff85bSBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
1207bc8ff85bSBarry Smith     else starts[i] = starts[i-1];
1208bc8ff85bSBarry Smith   }
1209bc8ff85bSBarry Smith 
121030dcb7c9SBarry Smith   /* for each nontrival globally owned node list all arriving processors */
1211bc8ff85bSBarry Smith   for (i=0; i<nrecvs; i++) {
1212bc8ff85bSBarry Smith     for (j=0; j<len[i]; j++) {
121330dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1214f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1215bc8ff85bSBarry Smith     }
1216bc8ff85bSBarry Smith   }
1217bc8ff85bSBarry Smith 
121807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
121930dcb7c9SBarry Smith     starts[0] = 0;
122030dcb7c9SBarry Smith     for (i=1; i<ng; i++) {
122130dcb7c9SBarry Smith       if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
122230dcb7c9SBarry Smith       else starts[i] = starts[i-1];
122330dcb7c9SBarry Smith     }
122430dcb7c9SBarry Smith     for (i=0; i<ng; i++) {
122530dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
12267904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr);
122730dcb7c9SBarry Smith         for (j=0; j<nownedsenders[i]; j++) {
12287904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr);
122930dcb7c9SBarry Smith         }
123030dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
123130dcb7c9SBarry Smith       }
123230dcb7c9SBarry Smith     }
12330ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
123407b52d57SBarry Smith   } /* -----------------------------------  */
123530dcb7c9SBarry Smith 
12363677ff5aSBarry Smith   /* wait on original sends */
12373a96401aSBarry Smith   if (nsends) {
1238785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
1239ffc4695bSBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRMPI(ierr);
12403a96401aSBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
12413a96401aSBarry Smith   }
124289d82c54SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
12433a96401aSBarry Smith   ierr = PetscFree(sends);CHKERRQ(ierr);
12443677ff5aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
12453677ff5aSBarry Smith 
12463677ff5aSBarry Smith   /* pack messages to send back to local owners */
124730dcb7c9SBarry Smith   starts[0] = 0;
124830dcb7c9SBarry Smith   for (i=1; i<ng; i++) {
124930dcb7c9SBarry Smith     if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1];
125030dcb7c9SBarry Smith     else starts[i] = starts[i-1];
125130dcb7c9SBarry Smith   }
125230dcb7c9SBarry Smith   nsends2 = nrecvs;
1253854ce69bSBarry Smith   ierr    = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */
125430dcb7c9SBarry Smith   for (i=0; i<nrecvs; i++) {
125530dcb7c9SBarry Smith     nprocs[i] = 1;
125630dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
125730dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
1258f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
125930dcb7c9SBarry Smith     }
126030dcb7c9SBarry Smith   }
1261f6e5521dSKarl Rupp   nt = 0;
1262f6e5521dSKarl Rupp   for (i=0; i<nsends2; i++) nt += nprocs[i];
1263f6e5521dSKarl Rupp 
1264854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr);
1265854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr);
1266f6e5521dSKarl Rupp 
1267f6e5521dSKarl Rupp   starts2[0] = 0;
1268f6e5521dSKarl Rupp   for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1];
126930dcb7c9SBarry Smith   /*
127030dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
127130dcb7c9SBarry Smith        (0) the number of nodes being sent back
127230dcb7c9SBarry Smith        (1) the local node number,
127330dcb7c9SBarry Smith        (2) the number of processors sharing it,
127430dcb7c9SBarry Smith        (3) the processors sharing it
127530dcb7c9SBarry Smith   */
127630dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
127730dcb7c9SBarry Smith     cnt = 1;
127830dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
127930dcb7c9SBarry Smith     for (j=0; j<len[i]; j++) {
128030dcb7c9SBarry Smith       node = recvs[2*i*nmax+2*j]-rstart;
128130dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
128230dcb7c9SBarry Smith         sends2[starts2[i]]++;
128330dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1];
128430dcb7c9SBarry Smith         sends2[starts2[i]+cnt++] = nownedsenders[node];
1285580bdb30SBarry Smith         ierr = PetscArraycpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]);CHKERRQ(ierr);
128630dcb7c9SBarry Smith         cnt += nownedsenders[node];
128730dcb7c9SBarry Smith       }
128830dcb7c9SBarry Smith     }
128930dcb7c9SBarry Smith   }
129030dcb7c9SBarry Smith 
129130dcb7c9SBarry Smith   /* receive the message lengths */
129230dcb7c9SBarry Smith   nrecvs2 = nsends;
1293854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr);
1294854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr);
1295854ce69bSBarry Smith   ierr    = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
129630dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
1297ffc4695bSBarry Smith     ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRMPI(ierr);
129830dcb7c9SBarry Smith   }
1299d44834fbSBarry Smith 
13008a8e0b3aSBarry Smith   /* send the message lengths */
13018a8e0b3aSBarry Smith   for (i=0; i<nsends2; i++) {
1302ffc4695bSBarry Smith     ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRMPI(ierr);
13038a8e0b3aSBarry Smith   }
13048a8e0b3aSBarry Smith 
1305d44834fbSBarry Smith   /* wait on receives of lens */
13060c468ba9SBarry Smith   if (nrecvs2) {
1307785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1308ffc4695bSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRMPI(ierr);
1309d44834fbSBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
13100c468ba9SBarry Smith   }
1311a2ea699eSBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
1312d44834fbSBarry Smith 
131330dcb7c9SBarry Smith   starts3[0] = 0;
1314d44834fbSBarry Smith   nt         = 0;
131530dcb7c9SBarry Smith   for (i=0; i<nrecvs2-1; i++) {
131630dcb7c9SBarry Smith     starts3[i+1] = starts3[i] + lens2[i];
1317d44834fbSBarry Smith     nt          += lens2[i];
131830dcb7c9SBarry Smith   }
131976466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2-1];
1320d44834fbSBarry Smith 
1321854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr);
1322854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr);
132352b72c4aSBarry Smith   for (i=0; i<nrecvs2; i++) {
1324ffc4695bSBarry Smith     ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRMPI(ierr);
132530dcb7c9SBarry Smith   }
132630dcb7c9SBarry Smith 
132730dcb7c9SBarry Smith   /* send the messages */
1328854ce69bSBarry Smith   ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr);
132930dcb7c9SBarry Smith   for (i=0; i<nsends2; i++) {
1330ffc4695bSBarry Smith     ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRMPI(ierr);
133130dcb7c9SBarry Smith   }
133230dcb7c9SBarry Smith 
133330dcb7c9SBarry Smith   /* wait on receives */
13340c468ba9SBarry Smith   if (nrecvs2) {
1335785e854fSJed Brown     ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr);
1336ffc4695bSBarry Smith     ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRMPI(ierr);
133730dcb7c9SBarry Smith     ierr = PetscFree(recv_statuses);CHKERRQ(ierr);
13380c468ba9SBarry Smith   }
133930dcb7c9SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
134030dcb7c9SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
134130dcb7c9SBarry Smith 
134207b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
134330dcb7c9SBarry Smith     cnt = 0;
134430dcb7c9SBarry Smith     for (i=0; i<nrecvs2; i++) {
134530dcb7c9SBarry Smith       nt = recvs2[cnt++];
134630dcb7c9SBarry Smith       for (j=0; j<nt; j++) {
13477904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr);
134830dcb7c9SBarry Smith         for (k=0; k<recvs2[cnt+1]; k++) {
13497904a332SBarry Smith           ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr);
135030dcb7c9SBarry Smith         }
135130dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt+1];
135230dcb7c9SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
135330dcb7c9SBarry Smith       }
135430dcb7c9SBarry Smith     }
13550ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
135607b52d57SBarry Smith   } /* -----------------------------------  */
135730dcb7c9SBarry Smith 
135830dcb7c9SBarry Smith   /* count number subdomains for each local node */
1359580bdb30SBarry Smith   ierr = PetscCalloc1(size,&nprocs);CHKERRQ(ierr);
136030dcb7c9SBarry Smith   cnt  = 0;
136130dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
136230dcb7c9SBarry Smith     nt = recvs2[cnt++];
136330dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1364f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++;
136530dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
136630dcb7c9SBarry Smith     }
136730dcb7c9SBarry Smith   }
136830dcb7c9SBarry Smith   nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0);
136930dcb7c9SBarry Smith   *nproc    = nt;
1370854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr);
1371854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr);
1372854ce69bSBarry Smith   ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr);
13730298fd71SBarry Smith   for (i=0;i<nt+1;i++) (*indices)[i]=NULL;
1374785e854fSJed Brown   ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr);
137530dcb7c9SBarry Smith   cnt  = 0;
137630dcb7c9SBarry Smith   for (i=0; i<size; i++) {
137730dcb7c9SBarry Smith     if (nprocs[i] > 0) {
137830dcb7c9SBarry Smith       bprocs[i]        = cnt;
137930dcb7c9SBarry Smith       (*procs)[cnt]    = i;
138030dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
1381785e854fSJed Brown       ierr             = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr);
138230dcb7c9SBarry Smith       cnt++;
138330dcb7c9SBarry Smith     }
138430dcb7c9SBarry Smith   }
138530dcb7c9SBarry Smith 
138630dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
1387580bdb30SBarry Smith   ierr = PetscArrayzero(*numprocs,nt);CHKERRQ(ierr);
138830dcb7c9SBarry Smith   cnt  = 0;
138930dcb7c9SBarry Smith   for (i=0; i<nrecvs2; i++) {
139030dcb7c9SBarry Smith     nt = recvs2[cnt++];
139130dcb7c9SBarry Smith     for (j=0; j<nt; j++) {
1392f6e5521dSKarl Rupp       for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt];
139330dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt+1];
139430dcb7c9SBarry Smith     }
139530dcb7c9SBarry Smith   }
139630dcb7c9SBarry Smith   ierr = PetscFree(bprocs);CHKERRQ(ierr);
139707b52d57SBarry Smith   ierr = PetscFree(recvs2);CHKERRQ(ierr);
139830dcb7c9SBarry Smith 
139907b52d57SBarry Smith   /* sort the node indexing by their global numbers */
140007b52d57SBarry Smith   nt = *nproc;
140107b52d57SBarry Smith   for (i=0; i<nt; i++) {
1402854ce69bSBarry Smith     ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr);
1403f6e5521dSKarl Rupp     for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
140407b52d57SBarry Smith     ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr);
140507b52d57SBarry Smith     ierr = PetscFree(tmp);CHKERRQ(ierr);
140607b52d57SBarry Smith   }
140707b52d57SBarry Smith 
140807b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
140930dcb7c9SBarry Smith     nt = *nproc;
141030dcb7c9SBarry Smith     for (i=0; i<nt; i++) {
14117904a332SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr);
141230dcb7c9SBarry Smith       for (j=0; j<(*numprocs)[i]; j++) {
14137904a332SBarry Smith         ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr);
141430dcb7c9SBarry Smith       }
141530dcb7c9SBarry Smith       ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr);
141630dcb7c9SBarry Smith     }
14170ec8b6e3SBarry Smith     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
141807b52d57SBarry Smith   } /* -----------------------------------  */
141930dcb7c9SBarry Smith 
142030dcb7c9SBarry Smith   /* wait on sends */
142130dcb7c9SBarry Smith   if (nsends2) {
1422785e854fSJed Brown     ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr);
1423ffc4695bSBarry Smith     ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRMPI(ierr);
142430dcb7c9SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
142530dcb7c9SBarry Smith   }
142630dcb7c9SBarry Smith 
142730dcb7c9SBarry Smith   ierr = PetscFree(starts3);CHKERRQ(ierr);
142830dcb7c9SBarry Smith   ierr = PetscFree(dest);CHKERRQ(ierr);
142930dcb7c9SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
14303677ff5aSBarry Smith 
1431bc8ff85bSBarry Smith   ierr = PetscFree(nownedsenders);CHKERRQ(ierr);
1432bc8ff85bSBarry Smith   ierr = PetscFree(ownedsenders);CHKERRQ(ierr);
1433bc8ff85bSBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
143430dcb7c9SBarry Smith   ierr = PetscFree(starts2);CHKERRQ(ierr);
143530dcb7c9SBarry Smith   ierr = PetscFree(lens2);CHKERRQ(ierr);
143689d82c54SBarry Smith 
143789d82c54SBarry Smith   ierr = PetscFree(source);CHKERRQ(ierr);
143897f1f81fSBarry Smith   ierr = PetscFree(len);CHKERRQ(ierr);
143989d82c54SBarry Smith   ierr = PetscFree(recvs);CHKERRQ(ierr);
14403a96401aSBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
144130dcb7c9SBarry Smith   ierr = PetscFree(sends2);CHKERRQ(ierr);
144224cf384cSBarry Smith 
144324cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
144424cf384cSBarry Smith   first_procs    = (*procs)[0];
144524cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
144624cf384cSBarry Smith   first_indices  = (*indices)[0];
144724cf384cSBarry Smith   for (i=0; i<*nproc; i++) {
144824cf384cSBarry Smith     if ((*procs)[i] == rank) {
144924cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
145024cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
145124cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
145224cf384cSBarry Smith       (*procs)[i]    = first_procs;
145324cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
145424cf384cSBarry Smith       (*indices)[i]  = first_indices;
145524cf384cSBarry Smith       break;
145624cf384cSBarry Smith     }
145724cf384cSBarry Smith   }
1458268a049cSStefano Zampini 
1459268a049cSStefano Zampini   /* save info for reuse */
1460268a049cSStefano Zampini   mapping->info_nproc = *nproc;
1461268a049cSStefano Zampini   mapping->info_procs = *procs;
1462268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1463268a049cSStefano Zampini   mapping->info_indices = *indices;
1464268a049cSStefano Zampini   mapping->info_cached = PETSC_TRUE;
146589d82c54SBarry Smith   PetscFunctionReturn(0);
146689d82c54SBarry Smith }
146789d82c54SBarry Smith 
14686a818285SBarry Smith /*@C
14696a818285SBarry Smith     ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo()
14706a818285SBarry Smith 
14716a818285SBarry Smith     Collective on ISLocalToGlobalMapping
14726a818285SBarry Smith 
1473f899ff85SJose E. Roman     Input Parameter:
14746a818285SBarry Smith .   mapping - the mapping from local to global indexing
14756a818285SBarry Smith 
1476d8d19677SJose E. Roman     Output Parameters:
14776a818285SBarry Smith +   nproc - number of processors that are connected to this one
14786a818285SBarry Smith .   proc - neighboring processors
14796a818285SBarry Smith .   numproc - number of indices for each processor
14806a818285SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
14816a818285SBarry Smith 
14826a818285SBarry Smith     Level: advanced
14836a818285SBarry Smith 
14846a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
14856a818285SBarry Smith           ISLocalToGlobalMappingGetInfo()
14866a818285SBarry Smith @*/
14876a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
14886a818285SBarry Smith {
14896a818285SBarry Smith   PetscErrorCode ierr;
14906a818285SBarry Smith 
14916a818285SBarry Smith   PetscFunctionBegin;
1492cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1493268a049cSStefano Zampini   if (mapping->info_free) {
14946a818285SBarry Smith     ierr = PetscFree(*numprocs);CHKERRQ(ierr);
14956a818285SBarry Smith     if (*indices) {
1496268a049cSStefano Zampini       PetscInt i;
1497268a049cSStefano Zampini 
14986a818285SBarry Smith       ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);
14996a818285SBarry Smith       for (i=1; i<*nproc; i++) {
15006a818285SBarry Smith         ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);
15016a818285SBarry Smith       }
15026a818285SBarry Smith       ierr = PetscFree(*indices);CHKERRQ(ierr);
15036a818285SBarry Smith     }
1504268a049cSStefano Zampini   }
1505268a049cSStefano Zampini   *nproc    = 0;
1506268a049cSStefano Zampini   *procs    = NULL;
1507268a049cSStefano Zampini   *numprocs = NULL;
1508268a049cSStefano Zampini   *indices  = NULL;
15096a818285SBarry Smith   PetscFunctionReturn(0);
15106a818285SBarry Smith }
15116a818285SBarry Smith 
15126a818285SBarry Smith /*@C
15136a818285SBarry Smith     ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
15146a818285SBarry Smith      each index shared by more than one processor
15156a818285SBarry Smith 
15166a818285SBarry Smith     Collective on ISLocalToGlobalMapping
15176a818285SBarry Smith 
1518f899ff85SJose E. Roman     Input Parameter:
15196a818285SBarry Smith .   mapping - the mapping from local to global indexing
15206a818285SBarry Smith 
1521d8d19677SJose E. Roman     Output Parameters:
15226a818285SBarry Smith +   nproc - number of processors that are connected to this one
15236a818285SBarry Smith .   proc - neighboring processors
15246a818285SBarry Smith .   numproc - number of indices for each subdomain (processor)
15256a818285SBarry Smith -   indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
15266a818285SBarry Smith 
15276a818285SBarry Smith     Level: advanced
15286a818285SBarry Smith 
15291bd0b88eSStefano Zampini     Notes: The user needs to call ISLocalToGlobalMappingRestoreInfo when the data is no longer needed.
15301bd0b88eSStefano Zampini 
15316a818285SBarry Smith     Fortran Usage:
15326a818285SBarry Smith $        ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
15336a818285SBarry Smith $        ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
15346a818285SBarry Smith           PetscInt indices[nproc][numprocmax],ierr)
15356a818285SBarry Smith         There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and
15366a818285SBarry Smith         indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough.
15376a818285SBarry Smith 
15386a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
15396a818285SBarry Smith           ISLocalToGlobalMappingRestoreInfo()
15406a818285SBarry Smith @*/
15416a818285SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
15426a818285SBarry Smith {
15436a818285SBarry Smith   PetscErrorCode ierr;
1544268a049cSStefano Zampini   PetscInt       **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k;
15456a818285SBarry Smith 
15466a818285SBarry Smith   PetscFunctionBegin;
15476a818285SBarry Smith   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
1548268a049cSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr);
1549268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
1550732f65e3SBarry Smith     ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr);
1551268a049cSStefano Zampini     ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr);
15526a818285SBarry Smith     for (i=0; i<*nproc; i++) {
1553268a049cSStefano Zampini       ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr);
1554268a049cSStefano Zampini       for (j=0; j<bnumprocs[i]; j++) {
15556a818285SBarry Smith         for (k=0; k<bs; k++) {
15566a818285SBarry Smith           (*indices)[i][j*bs+k] = bs*bindices[i][j] + k;
15576a818285SBarry Smith         }
15586a818285SBarry Smith       }
1559268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i]*bs;
15606a818285SBarry Smith     }
1561268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1562268a049cSStefano Zampini   } else {
1563268a049cSStefano Zampini     *numprocs = bnumprocs;
1564268a049cSStefano Zampini     *indices  = bindices;
15656a818285SBarry Smith   }
15666a818285SBarry Smith   PetscFunctionReturn(0);
15676a818285SBarry Smith }
15686a818285SBarry Smith 
156907b52d57SBarry Smith /*@C
157007b52d57SBarry Smith     ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo()
157189d82c54SBarry Smith 
157207b52d57SBarry Smith     Collective on ISLocalToGlobalMapping
157307b52d57SBarry Smith 
1574f899ff85SJose E. Roman     Input Parameter:
157507b52d57SBarry Smith .   mapping - the mapping from local to global indexing
157607b52d57SBarry Smith 
1577d8d19677SJose E. Roman     Output Parameters:
157807b52d57SBarry Smith +   nproc - number of processors that are connected to this one
157907b52d57SBarry Smith .   proc - neighboring processors
158007b52d57SBarry Smith .   numproc - number of indices for each processor
158107b52d57SBarry Smith -   indices - indices of local nodes shared with neighbor (sorted by global numbering)
158207b52d57SBarry Smith 
158307b52d57SBarry Smith     Level: advanced
158407b52d57SBarry Smith 
158507b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
158607b52d57SBarry Smith           ISLocalToGlobalMappingGetInfo()
158707b52d57SBarry Smith @*/
15887087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[])
158907b52d57SBarry Smith {
15906849ba73SBarry Smith   PetscErrorCode ierr;
159107b52d57SBarry Smith 
159207b52d57SBarry Smith   PetscFunctionBegin;
15936a818285SBarry Smith   ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr);
159407b52d57SBarry Smith   PetscFunctionReturn(0);
159507b52d57SBarry Smith }
159686994e45SJed Brown 
159786994e45SJed Brown /*@C
15981bd0b88eSStefano Zampini     ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information for each node
15991bd0b88eSStefano Zampini 
16001bd0b88eSStefano Zampini     Collective on ISLocalToGlobalMapping
16011bd0b88eSStefano Zampini 
1602f899ff85SJose E. Roman     Input Parameter:
16031bd0b88eSStefano Zampini .   mapping - the mapping from local to global indexing
16041bd0b88eSStefano Zampini 
1605d8d19677SJose E. Roman     Output Parameters:
16061bd0b88eSStefano Zampini +   nnodes - number of local nodes (same ISLocalToGlobalMappingGetSize())
16071bd0b88eSStefano Zampini .   count - number of neighboring processors per node
16081bd0b88eSStefano Zampini -   indices - indices of processes sharing the node (sorted)
16091bd0b88eSStefano Zampini 
16101bd0b88eSStefano Zampini     Level: advanced
16111bd0b88eSStefano Zampini 
16121bd0b88eSStefano Zampini     Notes: The user needs to call ISLocalToGlobalMappingRestoreInfo when the data is no longer needed.
16131bd0b88eSStefano Zampini 
16141bd0b88eSStefano Zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
16151bd0b88eSStefano Zampini           ISLocalToGlobalMappingGetInfo(), ISLocalToGlobalMappingRestoreNodeInfo()
16161bd0b88eSStefano Zampini @*/
16171bd0b88eSStefano Zampini PetscErrorCode  ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping,PetscInt *nnodes,PetscInt *count[],PetscInt **indices[])
16181bd0b88eSStefano Zampini {
16191bd0b88eSStefano Zampini   PetscInt       n;
16201bd0b88eSStefano Zampini   PetscErrorCode ierr;
16211bd0b88eSStefano Zampini 
16221bd0b88eSStefano Zampini   PetscFunctionBegin;
16231bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
16241bd0b88eSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mapping,&n);CHKERRQ(ierr);
16251bd0b88eSStefano Zampini   if (!mapping->info_nodec) {
16261bd0b88eSStefano Zampini     PetscInt i,m,n_neigh,*neigh,*n_shared,**shared;
16271bd0b88eSStefano Zampini 
1628071fcb05SBarry Smith     ierr = PetscMalloc2(n+1,&mapping->info_nodec,n,&mapping->info_nodei);CHKERRQ(ierr);
16291bd0b88eSStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
1630071fcb05SBarry Smith     for (i=0;i<n;i++) { mapping->info_nodec[i] = 1;}
1631071fcb05SBarry Smith     m = n;
1632071fcb05SBarry Smith     mapping->info_nodec[n] = 0;
16331bd0b88eSStefano Zampini     for (i=1;i<n_neigh;i++) {
16341bd0b88eSStefano Zampini       PetscInt j;
16351bd0b88eSStefano Zampini 
16361bd0b88eSStefano Zampini       m += n_shared[i];
16371bd0b88eSStefano Zampini       for (j=0;j<n_shared[i];j++) mapping->info_nodec[shared[i][j]] += 1;
16381bd0b88eSStefano Zampini     }
16391bd0b88eSStefano Zampini     if (n) { ierr = PetscMalloc1(m,&mapping->info_nodei[0]);CHKERRQ(ierr); }
16401bd0b88eSStefano Zampini     for (i=1;i<n;i++) mapping->info_nodei[i] = mapping->info_nodei[i-1] + mapping->info_nodec[i-1];
1641580bdb30SBarry Smith     ierr = PetscArrayzero(mapping->info_nodec,n);CHKERRQ(ierr);
16421bd0b88eSStefano Zampini     for (i=0;i<n;i++) { mapping->info_nodec[i] = 1; mapping->info_nodei[i][0] = neigh[0]; }
16431bd0b88eSStefano Zampini     for (i=1;i<n_neigh;i++) {
16441bd0b88eSStefano Zampini       PetscInt j;
16451bd0b88eSStefano Zampini 
16461bd0b88eSStefano Zampini       for (j=0;j<n_shared[i];j++) {
16471bd0b88eSStefano Zampini         PetscInt k = shared[i][j];
16481bd0b88eSStefano Zampini 
16491bd0b88eSStefano Zampini         mapping->info_nodei[k][mapping->info_nodec[k]] = neigh[i];
16501bd0b88eSStefano Zampini         mapping->info_nodec[k] += 1;
16511bd0b88eSStefano Zampini       }
16521bd0b88eSStefano Zampini     }
16531bd0b88eSStefano Zampini     for (i=0;i<n;i++) { ierr = PetscSortRemoveDupsInt(&mapping->info_nodec[i],mapping->info_nodei[i]);CHKERRQ(ierr); }
16541bd0b88eSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
16551bd0b88eSStefano Zampini   }
16561bd0b88eSStefano Zampini   if (nnodes)  *nnodes  = n;
16571bd0b88eSStefano Zampini   if (count)   *count   = mapping->info_nodec;
16581bd0b88eSStefano Zampini   if (indices) *indices = mapping->info_nodei;
16591bd0b88eSStefano Zampini   PetscFunctionReturn(0);
16601bd0b88eSStefano Zampini }
16611bd0b88eSStefano Zampini 
16621bd0b88eSStefano Zampini /*@C
16631bd0b88eSStefano Zampini     ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by ISLocalToGlobalMappingGetNodeInfo()
16641bd0b88eSStefano Zampini 
16651bd0b88eSStefano Zampini     Collective on ISLocalToGlobalMapping
16661bd0b88eSStefano Zampini 
1667f899ff85SJose E. Roman     Input Parameter:
16681bd0b88eSStefano Zampini .   mapping - the mapping from local to global indexing
16691bd0b88eSStefano Zampini 
1670d8d19677SJose E. Roman     Output Parameters:
16711bd0b88eSStefano Zampini +   nnodes - number of local nodes
16721bd0b88eSStefano Zampini .   count - number of neighboring processors per node
16731bd0b88eSStefano Zampini -   indices - indices of processes sharing the node (sorted)
16741bd0b88eSStefano Zampini 
16751bd0b88eSStefano Zampini     Level: advanced
16761bd0b88eSStefano Zampini 
16771bd0b88eSStefano Zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(),
16781bd0b88eSStefano Zampini           ISLocalToGlobalMappingGetInfo()
16791bd0b88eSStefano Zampini @*/
16801bd0b88eSStefano Zampini PetscErrorCode  ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping,PetscInt *nnodes,PetscInt *count[],PetscInt **indices[])
16811bd0b88eSStefano Zampini {
16821bd0b88eSStefano Zampini   PetscFunctionBegin;
16831bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1);
16841bd0b88eSStefano Zampini   if (nnodes)  *nnodes  = 0;
16851bd0b88eSStefano Zampini   if (count)   *count   = NULL;
16861bd0b88eSStefano Zampini   if (indices) *indices = NULL;
16871bd0b88eSStefano Zampini   PetscFunctionReturn(0);
16881bd0b88eSStefano Zampini }
16891bd0b88eSStefano Zampini 
16901bd0b88eSStefano Zampini /*@C
1691107e9a97SBarry Smith    ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
169286994e45SJed Brown 
169386994e45SJed Brown    Not Collective
169486994e45SJed Brown 
16954165533cSJose E. Roman    Input Parameter:
169686994e45SJed Brown . ltog - local to global mapping
169786994e45SJed Brown 
16984165533cSJose E. Roman    Output Parameter:
1699565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize()
170086994e45SJed Brown 
170186994e45SJed Brown    Level: advanced
170286994e45SJed Brown 
170395452b02SPatrick Sanan    Notes:
170495452b02SPatrick Sanan     ISLocalToGlobalMappingGetSize() returns the length the this array
1705107e9a97SBarry Smith 
1706107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices()
170786994e45SJed Brown @*/
17087087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
170986994e45SJed Brown {
171086994e45SJed Brown   PetscFunctionBegin;
171186994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
171286994e45SJed Brown   PetscValidPointer(array,2);
171345b6f7e9SBarry Smith   if (ltog->bs == 1) {
171486994e45SJed Brown     *array = ltog->indices;
171545b6f7e9SBarry Smith   } else {
171645b6f7e9SBarry Smith     PetscInt       *jj,k,i,j,n = ltog->n, bs = ltog->bs;
171745b6f7e9SBarry Smith     const PetscInt *ii;
171845b6f7e9SBarry Smith     PetscErrorCode ierr;
171945b6f7e9SBarry Smith 
172045b6f7e9SBarry Smith     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
172145b6f7e9SBarry Smith     *array = jj;
172245b6f7e9SBarry Smith     k    = 0;
172345b6f7e9SBarry Smith     ii   = ltog->indices;
172445b6f7e9SBarry Smith     for (i=0; i<n; i++)
172545b6f7e9SBarry Smith       for (j=0; j<bs; j++)
172645b6f7e9SBarry Smith         jj[k++] = bs*ii[i] + j;
172745b6f7e9SBarry Smith   }
172886994e45SJed Brown   PetscFunctionReturn(0);
172986994e45SJed Brown }
173086994e45SJed Brown 
173186994e45SJed Brown /*@C
1732193a2b41SJulian Andrej    ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices()
173386994e45SJed Brown 
173486994e45SJed Brown    Not Collective
173586994e45SJed Brown 
17364165533cSJose E. Roman    Input Parameters:
173786994e45SJed Brown + ltog - local to global mapping
173886994e45SJed Brown - array - array of indices
173986994e45SJed Brown 
174086994e45SJed Brown    Level: advanced
174186994e45SJed Brown 
174286994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
174386994e45SJed Brown @*/
17447087cfbeSBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
174586994e45SJed Brown {
174686994e45SJed Brown   PetscFunctionBegin;
174786994e45SJed Brown   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
174886994e45SJed Brown   PetscValidPointer(array,2);
174945b6f7e9SBarry Smith   if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
175045b6f7e9SBarry Smith 
175145b6f7e9SBarry Smith   if (ltog->bs > 1) {
175245b6f7e9SBarry Smith     PetscErrorCode ierr;
175345b6f7e9SBarry Smith     ierr = PetscFree(*(void**)array);CHKERRQ(ierr);
175445b6f7e9SBarry Smith   }
175545b6f7e9SBarry Smith   PetscFunctionReturn(0);
175645b6f7e9SBarry Smith }
175745b6f7e9SBarry Smith 
175845b6f7e9SBarry Smith /*@C
175945b6f7e9SBarry Smith    ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
176045b6f7e9SBarry Smith 
176145b6f7e9SBarry Smith    Not Collective
176245b6f7e9SBarry Smith 
17634165533cSJose E. Roman    Input Parameter:
176445b6f7e9SBarry Smith . ltog - local to global mapping
176545b6f7e9SBarry Smith 
17664165533cSJose E. Roman    Output Parameter:
176745b6f7e9SBarry Smith . array - array of indices
176845b6f7e9SBarry Smith 
176945b6f7e9SBarry Smith    Level: advanced
177045b6f7e9SBarry Smith 
177145b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices()
177245b6f7e9SBarry Smith @*/
177345b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
177445b6f7e9SBarry Smith {
177545b6f7e9SBarry Smith   PetscFunctionBegin;
177645b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
177745b6f7e9SBarry Smith   PetscValidPointer(array,2);
177845b6f7e9SBarry Smith   *array = ltog->indices;
177945b6f7e9SBarry Smith   PetscFunctionReturn(0);
178045b6f7e9SBarry Smith }
178145b6f7e9SBarry Smith 
178245b6f7e9SBarry Smith /*@C
178345b6f7e9SBarry Smith    ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices()
178445b6f7e9SBarry Smith 
178545b6f7e9SBarry Smith    Not Collective
178645b6f7e9SBarry Smith 
17874165533cSJose E. Roman    Input Parameters:
178845b6f7e9SBarry Smith + ltog - local to global mapping
178945b6f7e9SBarry Smith - array - array of indices
179045b6f7e9SBarry Smith 
179145b6f7e9SBarry Smith    Level: advanced
179245b6f7e9SBarry Smith 
179345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices()
179445b6f7e9SBarry Smith @*/
179545b6f7e9SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array)
179645b6f7e9SBarry Smith {
179745b6f7e9SBarry Smith   PetscFunctionBegin;
179845b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
179945b6f7e9SBarry Smith   PetscValidPointer(array,2);
180086994e45SJed Brown   if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer");
18010298fd71SBarry Smith   *array = NULL;
180286994e45SJed Brown   PetscFunctionReturn(0);
180386994e45SJed Brown }
1804f7efa3c7SJed Brown 
1805f7efa3c7SJed Brown /*@C
1806f7efa3c7SJed Brown    ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1807f7efa3c7SJed Brown 
1808f7efa3c7SJed Brown    Not Collective
1809f7efa3c7SJed Brown 
18104165533cSJose E. Roman    Input Parameters:
1811f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1812f7efa3c7SJed Brown . n - number of mappings to concatenate
1813f7efa3c7SJed Brown - ltogs - local to global mappings
1814f7efa3c7SJed Brown 
18154165533cSJose E. Roman    Output Parameter:
1816f7efa3c7SJed Brown . ltogcat - new mapping
1817f7efa3c7SJed Brown 
18189d90f715SBarry Smith    Note: this currently always returns a mapping with block size of 1
18199d90f715SBarry Smith 
18209d90f715SBarry Smith    Developer Note: If all the input mapping have the same block size we could easily handle that as a special case
18219d90f715SBarry Smith 
1822f7efa3c7SJed Brown    Level: advanced
1823f7efa3c7SJed Brown 
1824f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate()
1825f7efa3c7SJed Brown @*/
1826f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat)
1827f7efa3c7SJed Brown {
1828f7efa3c7SJed Brown   PetscInt       i,cnt,m,*idx;
1829f7efa3c7SJed Brown   PetscErrorCode ierr;
1830f7efa3c7SJed Brown 
1831f7efa3c7SJed Brown   PetscFunctionBegin;
1832f7efa3c7SJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n);
1833f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs,3);
1834f7efa3c7SJed Brown   for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3);
1835f7efa3c7SJed Brown   PetscValidPointer(ltogcat,4);
1836f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1837f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1838f7efa3c7SJed Brown     cnt += m;
1839f7efa3c7SJed Brown   }
1840785e854fSJed Brown   ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr);
1841f7efa3c7SJed Brown   for (cnt=0,i=0; i<n; i++) {
1842f7efa3c7SJed Brown     const PetscInt *subidx;
1843f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr);
1844f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1845580bdb30SBarry Smith     ierr = PetscArraycpy(&idx[cnt],subidx,m);CHKERRQ(ierr);
1846f7efa3c7SJed Brown     ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr);
1847f7efa3c7SJed Brown     cnt += m;
1848f7efa3c7SJed Brown   }
1849f0413b6fSBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr);
1850f7efa3c7SJed Brown   PetscFunctionReturn(0);
1851f7efa3c7SJed Brown }
185204a59952SBarry Smith 
1853413f72f0SBarry Smith /*MC
1854413f72f0SBarry Smith       ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the ISLocalToGlobalMapping object. When ISGlobalToLocalMappingApply() is
1855413f72f0SBarry Smith                                     used this is good for only small and moderate size problems.
1856413f72f0SBarry Smith 
1857413f72f0SBarry Smith    Options Database Keys:
1858a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type basic - select this method
1859413f72f0SBarry Smith 
1860413f72f0SBarry Smith    Level: beginner
1861413f72f0SBarry Smith 
1862413f72f0SBarry Smith .seealso:  ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetType(), ISLOCALTOGLOBALMAPPINGHASH
1863413f72f0SBarry Smith M*/
1864413f72f0SBarry Smith PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)
1865413f72f0SBarry Smith {
1866413f72f0SBarry Smith   PetscFunctionBegin;
1867413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Basic;
1868413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Basic;
1869413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic;
1870413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Basic;
1871413f72f0SBarry Smith   PetscFunctionReturn(0);
1872413f72f0SBarry Smith }
1873413f72f0SBarry Smith 
1874413f72f0SBarry Smith /*MC
1875413f72f0SBarry Smith       ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the ISLocalToGlobalMapping object. When ISGlobalToLocalMappingApply() is
1876ed56e8eaSBarry Smith                                     used this is good for large memory problems.
1877413f72f0SBarry Smith 
1878413f72f0SBarry Smith    Options Database Keys:
1879a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type hash - select this method
1880413f72f0SBarry Smith 
188195452b02SPatrick Sanan    Notes:
188295452b02SPatrick Sanan     This is selected automatically for large problems if the user does not set the type.
1883ed56e8eaSBarry Smith 
1884413f72f0SBarry Smith    Level: beginner
1885413f72f0SBarry Smith 
1886413f72f0SBarry Smith .seealso:  ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingSetType(), ISLOCALTOGLOBALMAPPINGHASH
1887413f72f0SBarry Smith M*/
1888413f72f0SBarry Smith PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)
1889413f72f0SBarry Smith {
1890413f72f0SBarry Smith   PetscFunctionBegin;
1891413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Hash;
1892413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Hash;
1893413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash;
1894413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Hash;
1895413f72f0SBarry Smith   PetscFunctionReturn(0);
1896413f72f0SBarry Smith }
1897413f72f0SBarry Smith 
1898413f72f0SBarry Smith /*@C
1899413f72f0SBarry Smith     ISLocalToGlobalMappingRegister -  Adds a method for applying a global to local mapping with an ISLocalToGlobalMapping
1900413f72f0SBarry Smith 
1901413f72f0SBarry Smith    Not Collective
1902413f72f0SBarry Smith 
1903413f72f0SBarry Smith    Input Parameters:
1904413f72f0SBarry Smith +  sname - name of a new method
1905413f72f0SBarry Smith -  routine_create - routine to create method context
1906413f72f0SBarry Smith 
1907413f72f0SBarry Smith    Notes:
1908ed56e8eaSBarry Smith    ISLocalToGlobalMappingRegister() may be called multiple times to add several user-defined mappings.
1909413f72f0SBarry Smith 
1910413f72f0SBarry Smith    Sample usage:
1911413f72f0SBarry Smith .vb
1912413f72f0SBarry Smith    ISLocalToGlobalMappingRegister("my_mapper",MyCreate);
1913413f72f0SBarry Smith .ve
1914413f72f0SBarry Smith 
1915ed56e8eaSBarry Smith    Then, your mapping can be chosen with the procedural interface via
1916413f72f0SBarry Smith $     ISLocalToGlobalMappingSetType(ltog,"my_mapper")
1917413f72f0SBarry Smith    or at runtime via the option
1918ed56e8eaSBarry Smith $     -islocaltoglobalmapping_type my_mapper
1919413f72f0SBarry Smith 
1920413f72f0SBarry Smith    Level: advanced
1921413f72f0SBarry Smith 
1922413f72f0SBarry Smith .seealso: ISLocalToGlobalMappingRegisterAll(), ISLocalToGlobalMappingRegisterDestroy(), ISLOCALTOGLOBALMAPPINGBASIC, ISLOCALTOGLOBALMAPPINGHASH
1923413f72f0SBarry Smith 
1924413f72f0SBarry Smith @*/
1925413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRegister(const char sname[],PetscErrorCode (*function)(ISLocalToGlobalMapping))
1926413f72f0SBarry Smith {
1927413f72f0SBarry Smith   PetscErrorCode ierr;
1928413f72f0SBarry Smith 
1929413f72f0SBarry Smith   PetscFunctionBegin;
19301d36bdfdSBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
1931413f72f0SBarry Smith   ierr = PetscFunctionListAdd(&ISLocalToGlobalMappingList,sname,function);CHKERRQ(ierr);
1932413f72f0SBarry Smith   PetscFunctionReturn(0);
1933413f72f0SBarry Smith }
1934413f72f0SBarry Smith 
1935413f72f0SBarry Smith /*@C
1936ed56e8eaSBarry Smith    ISLocalToGlobalMappingSetType - Builds ISLocalToGlobalMapping for a particular global to local mapping approach.
1937413f72f0SBarry Smith 
1938413f72f0SBarry Smith    Logically Collective on ISLocalToGlobalMapping
1939413f72f0SBarry Smith 
1940413f72f0SBarry Smith    Input Parameters:
1941413f72f0SBarry Smith +  ltog - the ISLocalToGlobalMapping object
1942413f72f0SBarry Smith -  type - a known method
1943413f72f0SBarry Smith 
1944413f72f0SBarry Smith    Options Database Key:
1945ed56e8eaSBarry Smith .  -islocaltoglobalmapping_type  <method> - Sets the method; use -help for a list
1946413f72f0SBarry Smith     of available methods (for instance, basic or hash)
1947413f72f0SBarry Smith 
1948413f72f0SBarry Smith    Notes:
1949413f72f0SBarry Smith    See "petsc/include/petscis.h" for available methods
1950413f72f0SBarry Smith 
1951413f72f0SBarry Smith   Normally, it is best to use the ISLocalToGlobalMappingSetFromOptions() command and
1952413f72f0SBarry Smith   then set the ISLocalToGlobalMapping type from the options database rather than by using
1953413f72f0SBarry Smith   this routine.
1954413f72f0SBarry Smith 
1955413f72f0SBarry Smith   Level: intermediate
1956413f72f0SBarry Smith 
1957413f72f0SBarry Smith   Developer Note: ISLocalToGlobalMappingRegister() is used to add new types to ISLocalToGlobalMappingList from which they
1958413f72f0SBarry Smith   are accessed by ISLocalToGlobalMappingSetType().
1959413f72f0SBarry Smith 
1960413f72f0SBarry Smith .seealso: PCSetType(), ISLocalToGlobalMappingType, ISLocalToGlobalMappingRegister(), ISLocalToGlobalMappingCreate()
1961413f72f0SBarry Smith 
1962413f72f0SBarry Smith @*/
1963413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type)
1964413f72f0SBarry Smith {
1965413f72f0SBarry Smith   PetscErrorCode ierr,(*r)(ISLocalToGlobalMapping);
1966413f72f0SBarry Smith   PetscBool      match;
1967413f72f0SBarry Smith 
1968413f72f0SBarry Smith   PetscFunctionBegin;
1969413f72f0SBarry Smith   PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1);
1970413f72f0SBarry Smith   PetscValidCharPointer(type,2);
1971413f72f0SBarry Smith 
1972413f72f0SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)ltog,type,&match);CHKERRQ(ierr);
1973413f72f0SBarry Smith   if (match) PetscFunctionReturn(0);
1974413f72f0SBarry Smith 
1975413f72f0SBarry Smith   ierr =  PetscFunctionListFind(ISLocalToGlobalMappingList,type,&r);CHKERRQ(ierr);
1976413f72f0SBarry Smith   if (!r) SETERRQ1(PetscObjectComm((PetscObject)ltog),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested ISLocalToGlobalMapping type %s",type);
1977413f72f0SBarry Smith   /* Destroy the previous private LTOG context */
1978413f72f0SBarry Smith   if (ltog->ops->destroy) {
1979413f72f0SBarry Smith     ierr              = (*ltog->ops->destroy)(ltog);CHKERRQ(ierr);
1980413f72f0SBarry Smith     ltog->ops->destroy = NULL;
1981413f72f0SBarry Smith   }
1982413f72f0SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)ltog,type);CHKERRQ(ierr);
1983413f72f0SBarry Smith   ierr = (*r)(ltog);CHKERRQ(ierr);
1984413f72f0SBarry Smith   PetscFunctionReturn(0);
1985413f72f0SBarry Smith }
1986413f72f0SBarry Smith 
1987413f72f0SBarry Smith PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE;
1988413f72f0SBarry Smith 
1989413f72f0SBarry Smith /*@C
1990413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the IS package.
1991413f72f0SBarry Smith 
1992413f72f0SBarry Smith   Not Collective
1993413f72f0SBarry Smith 
1994413f72f0SBarry Smith   Level: advanced
1995413f72f0SBarry Smith 
1996413f72f0SBarry Smith .seealso:  ISRegister(),  ISLocalToGlobalRegister()
1997413f72f0SBarry Smith @*/
1998413f72f0SBarry Smith PetscErrorCode  ISLocalToGlobalMappingRegisterAll(void)
1999413f72f0SBarry Smith {
2000413f72f0SBarry Smith   PetscErrorCode ierr;
2001413f72f0SBarry Smith 
2002413f72f0SBarry Smith   PetscFunctionBegin;
2003413f72f0SBarry Smith   if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(0);
2004413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE;
2005413f72f0SBarry Smith 
2006413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic);CHKERRQ(ierr);
2007413f72f0SBarry Smith   ierr = ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash);CHKERRQ(ierr);
2008413f72f0SBarry Smith   PetscFunctionReturn(0);
2009413f72f0SBarry Smith }
2010