xref: /petsc/src/vec/is/utils/isltog.c (revision e33f79d88bab5f9023ea6be42dc5dbb69a57d50a)
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
19cab54364SBarry Smith   ISGetPointRange - Returns a description of the points in an `IS` suitable for traversal
20413f72f0SBarry Smith 
2120662ed9SBarry Smith   Not Collective
226528b96dSMatthew G. Knepley 
236528b96dSMatthew G. Knepley   Input Parameter:
24cab54364SBarry Smith . 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   Level: intermediate
326528b96dSMatthew G. Knepley 
33cab54364SBarry Smith   Notes:
3420662ed9SBarry Smith   If the `IS` contains contiguous indices in an `ISSTRIDE`, then the indices are contained in [pStart, pEnd) and points = `NULL`.
3520662ed9SBarry Smith   Otherwise, `pStart = 0`, `pEnd = numIndices`, and points is an array of the indices. This supports the following pattern
36cab54364SBarry Smith .vb
37cab54364SBarry Smith   ISGetPointRange(is, &pStart, &pEnd, &points);
38cab54364SBarry Smith   for (p = pStart; p < pEnd; ++p) {
39cab54364SBarry Smith     const PetscInt point = points ? points[p] : p;
4020662ed9SBarry Smith     // use point
41cab54364SBarry Smith   }
42cab54364SBarry Smith   ISRestorePointRange(is, &pstart, &pEnd, &points);
43cab54364SBarry Smith .ve
4420662ed9SBarry Smith   Hence the same code can be written for `pointIS` being a `ISSTRIDE` or `ISGENERAL`
45cab54364SBarry Smith 
46cab54364SBarry Smith .seealso: [](sec_scatter), `IS`, `ISRestorePointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()`
476528b96dSMatthew G. Knepley @*/
48d71ae5a4SJacob Faibussowitsch PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
49d71ae5a4SJacob Faibussowitsch {
509305a4c7SMatthew G. Knepley   PetscInt  numCells, step = 1;
519305a4c7SMatthew G. Knepley   PetscBool isStride;
529305a4c7SMatthew G. Knepley 
539305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
549305a4c7SMatthew G. Knepley   *pStart = 0;
559305a4c7SMatthew G. Knepley   *points = NULL;
569566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointIS, &numCells));
579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pointIS, ISSTRIDE, &isStride));
589566063dSJacob Faibussowitsch   if (isStride) PetscCall(ISStrideGetInfo(pointIS, pStart, &step));
599305a4c7SMatthew G. Knepley   *pEnd = *pStart + numCells;
609566063dSJacob Faibussowitsch   if (!isStride || step != 1) PetscCall(ISGetIndices(pointIS, points));
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629305a4c7SMatthew G. Knepley }
639305a4c7SMatthew G. Knepley 
646528b96dSMatthew G. Knepley /*@C
65cab54364SBarry Smith   ISRestorePointRange - Destroys the traversal description created with `ISGetPointRange()`
666528b96dSMatthew G. Knepley 
6720662ed9SBarry Smith   Not Collective
686528b96dSMatthew G. Knepley 
696528b96dSMatthew G. Knepley   Input Parameters:
70cab54364SBarry Smith + pointIS - The `IS` object
71cab54364SBarry Smith . pStart  - The first index, from `ISGetPointRange()`
72cab54364SBarry Smith . pEnd    - One past the last index, from `ISGetPointRange()`
73cab54364SBarry Smith - points  - The indices, from `ISGetPointRange()`
746528b96dSMatthew G. Knepley 
756528b96dSMatthew G. Knepley   Level: intermediate
766528b96dSMatthew G. Knepley 
77cab54364SBarry Smith .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()`
786528b96dSMatthew G. Knepley @*/
79d71ae5a4SJacob Faibussowitsch PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
80d71ae5a4SJacob Faibussowitsch {
819305a4c7SMatthew G. Knepley   PetscInt  step = 1;
829305a4c7SMatthew G. Knepley   PetscBool isStride;
839305a4c7SMatthew G. Knepley 
849305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pointIS, ISSTRIDE, &isStride));
869566063dSJacob Faibussowitsch   if (isStride) PetscCall(ISStrideGetInfo(pointIS, pStart, &step));
879566063dSJacob Faibussowitsch   if (!isStride || step != 1) PetscCall(ISGetIndices(pointIS, points));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
899305a4c7SMatthew G. Knepley }
909305a4c7SMatthew G. Knepley 
916528b96dSMatthew G. Knepley /*@C
92cab54364SBarry Smith   ISGetPointSubrange - Configures the input `IS` to be a subrange for the traversal information given
936528b96dSMatthew G. Knepley 
9420662ed9SBarry Smith   Not Collective
956528b96dSMatthew G. Knepley 
966528b96dSMatthew G. Knepley   Input Parameters:
97cab54364SBarry Smith + subpointIS - The `IS` object to be configured
986528b96dSMatthew G. Knepley . pStart     - The first index of the subrange
996528b96dSMatthew G. Knepley . pEnd       - One past the last index for the subrange
100cab54364SBarry Smith - points     - The indices for the entire range, from `ISGetPointRange()`
1016528b96dSMatthew G. Knepley 
1026528b96dSMatthew G. Knepley   Output Parameters:
103cab54364SBarry Smith . subpointIS - The `IS` object now configured to be a subrange
1046528b96dSMatthew G. Knepley 
1056528b96dSMatthew G. Knepley   Level: intermediate
1066528b96dSMatthew G. Knepley 
107cab54364SBarry Smith   Note:
108cab54364SBarry Smith   The input `IS` will now respond properly to calls to `ISGetPointRange()` and return the subrange.
109cab54364SBarry Smith 
110cab54364SBarry Smith .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISRestorePointRange()`, `ISGetIndices()`, `ISCreateStride()`
1116528b96dSMatthew G. Knepley @*/
112d71ae5a4SJacob Faibussowitsch PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points)
113d71ae5a4SJacob Faibussowitsch {
1149305a4c7SMatthew G. Knepley   PetscFunctionBeginHot;
1159305a4c7SMatthew G. Knepley   if (points) {
1169566063dSJacob Faibussowitsch     PetscCall(ISSetType(subpointIS, ISGENERAL));
1179566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(subpointIS, pEnd - pStart, &points[pStart], PETSC_USE_POINTER));
1189305a4c7SMatthew G. Knepley   } else {
1199566063dSJacob Faibussowitsch     PetscCall(ISSetType(subpointIS, ISSTRIDE));
1209566063dSJacob Faibussowitsch     PetscCall(ISStrideSetStride(subpointIS, pEnd - pStart, pStart, 1));
1219305a4c7SMatthew G. Knepley   }
1223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1239305a4c7SMatthew G. Knepley }
1249305a4c7SMatthew G. Knepley 
125413f72f0SBarry Smith /* -----------------------------------------------------------------------------------------*/
126413f72f0SBarry Smith 
127413f72f0SBarry Smith /*
128413f72f0SBarry Smith     Creates the global mapping information in the ISLocalToGlobalMapping structure
129413f72f0SBarry Smith 
130413f72f0SBarry Smith     If the user has not selected how to handle the global to local mapping then use HASH for "large" problems
131413f72f0SBarry Smith */
132d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping)
133d71ae5a4SJacob Faibussowitsch {
134413f72f0SBarry Smith   PetscInt i, *idx = mapping->indices, n = mapping->n, end, start;
135413f72f0SBarry Smith 
136413f72f0SBarry Smith   PetscFunctionBegin;
1373ba16761SJacob Faibussowitsch   if (mapping->data) PetscFunctionReturn(PETSC_SUCCESS);
138413f72f0SBarry Smith   end   = 0;
139413f72f0SBarry Smith   start = PETSC_MAX_INT;
140413f72f0SBarry Smith 
141413f72f0SBarry Smith   for (i = 0; i < n; i++) {
142413f72f0SBarry Smith     if (idx[i] < 0) continue;
143413f72f0SBarry Smith     if (idx[i] < start) start = idx[i];
144413f72f0SBarry Smith     if (idx[i] > end) end = idx[i];
145413f72f0SBarry Smith   }
1469371c9d4SSatish Balay   if (start > end) {
1479371c9d4SSatish Balay     start = 0;
1489371c9d4SSatish Balay     end   = -1;
1499371c9d4SSatish Balay   }
150413f72f0SBarry Smith   mapping->globalstart = start;
151413f72f0SBarry Smith   mapping->globalend   = end;
152413f72f0SBarry Smith   if (!((PetscObject)mapping)->type_name) {
153413f72f0SBarry Smith     if ((end - start) > PetscMax(4 * n, 1000000)) {
1549566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGHASH));
155413f72f0SBarry Smith     } else {
1569566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGBASIC));
157413f72f0SBarry Smith     }
158413f72f0SBarry Smith   }
159dbbe0bcdSBarry Smith   PetscTryTypeMethod(mapping, globaltolocalmappingsetup);
1603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
161413f72f0SBarry Smith }
162413f72f0SBarry Smith 
163d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping)
164d71ae5a4SJacob Faibussowitsch {
165413f72f0SBarry Smith   PetscInt                      i, *idx = mapping->indices, n = mapping->n, end, start, *globals;
166413f72f0SBarry Smith   ISLocalToGlobalMapping_Basic *map;
167413f72f0SBarry Smith 
168413f72f0SBarry Smith   PetscFunctionBegin;
169413f72f0SBarry Smith   start = mapping->globalstart;
170413f72f0SBarry Smith   end   = mapping->globalend;
1719566063dSJacob Faibussowitsch   PetscCall(PetscNew(&map));
1729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(end - start + 2, &globals));
173413f72f0SBarry Smith   map->globals = globals;
174413f72f0SBarry Smith   for (i = 0; i < end - start + 1; i++) globals[i] = -1;
175413f72f0SBarry Smith   for (i = 0; i < n; i++) {
176413f72f0SBarry Smith     if (idx[i] < 0) continue;
177413f72f0SBarry Smith     globals[idx[i] - start] = i;
178413f72f0SBarry Smith   }
179413f72f0SBarry Smith   mapping->data = (void *)map;
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
181413f72f0SBarry Smith }
182413f72f0SBarry Smith 
183d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping)
184d71ae5a4SJacob Faibussowitsch {
185413f72f0SBarry Smith   PetscInt                     i, *idx = mapping->indices, n = mapping->n;
186413f72f0SBarry Smith   ISLocalToGlobalMapping_Hash *map;
187413f72f0SBarry Smith 
188413f72f0SBarry Smith   PetscFunctionBegin;
1899566063dSJacob Faibussowitsch   PetscCall(PetscNew(&map));
1909566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&map->globalht));
191413f72f0SBarry Smith   for (i = 0; i < n; i++) {
192413f72f0SBarry Smith     if (idx[i] < 0) continue;
1939566063dSJacob Faibussowitsch     PetscCall(PetscHMapISet(map->globalht, idx[i], i));
194413f72f0SBarry Smith   }
195413f72f0SBarry Smith   mapping->data = (void *)map;
1963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197413f72f0SBarry Smith }
198413f72f0SBarry Smith 
199d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping)
200d71ae5a4SJacob Faibussowitsch {
201413f72f0SBarry Smith   ISLocalToGlobalMapping_Basic *map = (ISLocalToGlobalMapping_Basic *)mapping->data;
202413f72f0SBarry Smith 
203413f72f0SBarry Smith   PetscFunctionBegin;
2043ba16761SJacob Faibussowitsch   if (!map) PetscFunctionReturn(PETSC_SUCCESS);
2059566063dSJacob Faibussowitsch   PetscCall(PetscFree(map->globals));
2069566063dSJacob Faibussowitsch   PetscCall(PetscFree(mapping->data));
2073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208413f72f0SBarry Smith }
209413f72f0SBarry Smith 
210d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping)
211d71ae5a4SJacob Faibussowitsch {
212413f72f0SBarry Smith   ISLocalToGlobalMapping_Hash *map = (ISLocalToGlobalMapping_Hash *)mapping->data;
213413f72f0SBarry Smith 
214413f72f0SBarry Smith   PetscFunctionBegin;
2153ba16761SJacob Faibussowitsch   if (!map) PetscFunctionReturn(PETSC_SUCCESS);
2169566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&map->globalht));
2179566063dSJacob Faibussowitsch   PetscCall(PetscFree(mapping->data));
2183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219413f72f0SBarry Smith }
220413f72f0SBarry Smith 
221413f72f0SBarry Smith #define GTOLTYPE _Basic
222413f72f0SBarry Smith #define GTOLNAME _Basic
223541bf97eSAdrian Croucher #define GTOLBS   mapping->bs
2249371c9d4SSatish Balay #define GTOL(g, local) \
2259371c9d4SSatish Balay   do { \
226413f72f0SBarry Smith     local = map->globals[g / bs - start]; \
2270040bde1SJunchao Zhang     if (local >= 0) local = bs * local + (g % bs); \
228413f72f0SBarry Smith   } while (0)
229541bf97eSAdrian Croucher 
230413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
231413f72f0SBarry Smith 
232413f72f0SBarry Smith #define GTOLTYPE _Basic
233413f72f0SBarry Smith #define GTOLNAME Block_Basic
234541bf97eSAdrian Croucher #define GTOLBS   1
2359371c9d4SSatish Balay #define GTOL(g, local) \
236d71ae5a4SJacob Faibussowitsch   do { \
237d71ae5a4SJacob Faibussowitsch     local = map->globals[g - start]; \
238d71ae5a4SJacob Faibussowitsch   } while (0)
239413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
240413f72f0SBarry Smith 
241413f72f0SBarry Smith #define GTOLTYPE _Hash
242413f72f0SBarry Smith #define GTOLNAME _Hash
243541bf97eSAdrian Croucher #define GTOLBS   mapping->bs
2449371c9d4SSatish Balay #define GTOL(g, local) \
2459371c9d4SSatish Balay   do { \
246e8f14785SLisandro Dalcin     (void)PetscHMapIGet(map->globalht, g / bs, &local); \
2470040bde1SJunchao Zhang     if (local >= 0) local = bs * local + (g % bs); \
248413f72f0SBarry Smith   } while (0)
249413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
250413f72f0SBarry Smith 
251413f72f0SBarry Smith #define GTOLTYPE _Hash
252413f72f0SBarry Smith #define GTOLNAME Block_Hash
253541bf97eSAdrian Croucher #define GTOLBS   1
2549371c9d4SSatish Balay #define GTOL(g, local) \
255d71ae5a4SJacob Faibussowitsch   do { \
256d71ae5a4SJacob Faibussowitsch     (void)PetscHMapIGet(map->globalht, g, &local); \
257d71ae5a4SJacob Faibussowitsch   } while (0)
258413f72f0SBarry Smith #include <../src/vec/is/utils/isltog.h>
259413f72f0SBarry Smith 
2606658fb44Sstefano_zampini /*@
2616658fb44Sstefano_zampini   ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
2626658fb44Sstefano_zampini 
2636658fb44Sstefano_zampini   Not Collective
2646658fb44Sstefano_zampini 
2656658fb44Sstefano_zampini   Input Parameter:
2666658fb44Sstefano_zampini . ltog - local to global mapping
2676658fb44Sstefano_zampini 
2686658fb44Sstefano_zampini   Output Parameter:
2696658fb44Sstefano_zampini . nltog - the duplicated local to global mapping
2706658fb44Sstefano_zampini 
2716658fb44Sstefano_zampini   Level: advanced
2726658fb44Sstefano_zampini 
273cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
2746658fb44Sstefano_zampini @*/
275d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog, ISLocalToGlobalMapping *nltog)
276d71ae5a4SJacob Faibussowitsch {
277a0d79125SStefano Zampini   ISLocalToGlobalMappingType l2gtype;
2786658fb44Sstefano_zampini 
2796658fb44Sstefano_zampini   PetscFunctionBegin;
2806658fb44Sstefano_zampini   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
2819566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog), ltog->bs, ltog->n, ltog->indices, PETSC_COPY_VALUES, nltog));
2829566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetType(ltog, &l2gtype));
2839566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*nltog, l2gtype));
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2856658fb44Sstefano_zampini }
2866658fb44Sstefano_zampini 
287565245c5SBarry Smith /*@
288107e9a97SBarry Smith   ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
2893b9aefa3SBarry Smith 
2903b9aefa3SBarry Smith   Not Collective
2913b9aefa3SBarry Smith 
2923b9aefa3SBarry Smith   Input Parameter:
29338b5cf2dSJacob Faibussowitsch . mapping - local to global mapping
2943b9aefa3SBarry Smith 
2953b9aefa3SBarry Smith   Output Parameter:
296cab54364SBarry Smith . n - the number of entries in the local mapping, `ISLocalToGlobalMappingGetIndices()` returns an array of this length
2973b9aefa3SBarry Smith 
2983b9aefa3SBarry Smith   Level: advanced
2993b9aefa3SBarry Smith 
300cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
3013b9aefa3SBarry Smith @*/
302d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping, PetscInt *n)
303d71ae5a4SJacob Faibussowitsch {
3043b9aefa3SBarry Smith   PetscFunctionBegin;
3050700a824SBarry Smith   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
3064482741eSBarry Smith   PetscValidIntPointer(n, 2);
307107e9a97SBarry Smith   *n = mapping->bs * mapping->n;
3083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3093b9aefa3SBarry Smith }
3103b9aefa3SBarry Smith 
3115a5d4f66SBarry Smith /*@C
312cab54364SBarry Smith   ISLocalToGlobalMappingViewFromOptions - View an `ISLocalToGlobalMapping` based on values in the options database
313fe2efc57SMark 
314c3339decSBarry Smith   Collective
315fe2efc57SMark 
316fe2efc57SMark   Input Parameters:
317fe2efc57SMark + A    - the local to global mapping object
31820662ed9SBarry Smith . obj  - Optional object that provides the options prefix used for the options database query
319736c3998SJose E. Roman - name - command line option
320fe2efc57SMark 
321fe2efc57SMark   Level: intermediate
322cab54364SBarry Smith 
32320662ed9SBarry Smith   Note:
32420662ed9SBarry Smith   See `PetscObjectViewFromOptions()` for the available `PetscViewer` and `PetscViewerFormat`
32520662ed9SBarry Smith 
32620662ed9SBarry Smith .seealso: [](sec_scatter), `PetscViewer`, ``ISLocalToGlobalMapping`, `ISLocalToGlobalMappingView`, `PetscObjectViewFromOptions()`, `ISLocalToGlobalMappingCreate()`
327fe2efc57SMark @*/
328d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A, PetscObject obj, const char name[])
329d71ae5a4SJacob Faibussowitsch {
330fe2efc57SMark   PetscFunctionBegin;
331fe2efc57SMark   PetscValidHeaderSpecific(A, IS_LTOGM_CLASSID, 1);
3329566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
334fe2efc57SMark }
335fe2efc57SMark 
336fe2efc57SMark /*@C
3375a5d4f66SBarry Smith   ISLocalToGlobalMappingView - View a local to global mapping
3385a5d4f66SBarry Smith 
339b9cd556bSLois Curfman McInnes   Not Collective
340b9cd556bSLois Curfman McInnes 
3415a5d4f66SBarry Smith   Input Parameters:
34238b5cf2dSJacob Faibussowitsch + mapping - local to global mapping
3433b9aefa3SBarry Smith - viewer  - viewer
3445a5d4f66SBarry Smith 
345a997ad1aSLois Curfman McInnes   Level: advanced
346a997ad1aSLois Curfman McInnes 
34720662ed9SBarry Smith .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
3485a5d4f66SBarry Smith @*/
349d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping, PetscViewer viewer)
350d71ae5a4SJacob Faibussowitsch {
35132dcc486SBarry Smith   PetscInt    i;
35232dcc486SBarry Smith   PetscMPIInt rank;
353ace3abfcSBarry Smith   PetscBool   iascii;
3545a5d4f66SBarry Smith 
3555a5d4f66SBarry Smith   PetscFunctionBegin;
3560700a824SBarry Smith   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
35748a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping), &viewer));
3580700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3595a5d4f66SBarry Smith 
3609566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mapping), &rank));
3619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
36232077d6dSBarry Smith   if (iascii) {
3639566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mapping, viewer));
3649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
365f2c6b1a2SJed Brown     for (i = 0; i < mapping->n; i++) {
366f2c6b1a2SJed Brown       PetscInt bs = mapping->bs, g = mapping->indices[i];
367f2c6b1a2SJed Brown       if (bs == 1) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT " %" PetscInt_FMT "\n", rank, i, g));
368f2c6b1a2SJed Brown       else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":%" PetscInt_FMT " %" PetscInt_FMT ":%" PetscInt_FMT "\n", rank, i * bs, (i + 1) * bs, g * bs, (g + 1) * bs));
369f2c6b1a2SJed Brown     }
3709566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
3719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
3721575c14dSBarry Smith   }
3733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3745a5d4f66SBarry Smith }
3755a5d4f66SBarry Smith 
3761f428162SBarry Smith /*@
3772bdab257SBarry Smith   ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
3782bdab257SBarry Smith   ordering and a global parallel ordering.
3792bdab257SBarry Smith 
38020662ed9SBarry Smith   Not Collective
381b9cd556bSLois Curfman McInnes 
382a997ad1aSLois Curfman McInnes   Input Parameter:
3838c03b21aSDmitry Karpeev . is - index set containing the global numbers for each local number
3842bdab257SBarry Smith 
385a997ad1aSLois Curfman McInnes   Output Parameter:
3862bdab257SBarry Smith . mapping - new mapping data structure
3872bdab257SBarry Smith 
388a997ad1aSLois Curfman McInnes   Level: advanced
389a997ad1aSLois Curfman McInnes 
390cab54364SBarry Smith   Note:
391cab54364SBarry Smith   the block size of the `IS` determines the block size of the mapping
392cab54364SBarry Smith 
393cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetFromOptions()`
3942bdab257SBarry Smith @*/
395d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is, ISLocalToGlobalMapping *mapping)
396d71ae5a4SJacob Faibussowitsch {
3973bbf0e92SBarry Smith   PetscInt        n, bs;
3985d0c19d7SBarry Smith   const PetscInt *indices;
3992bdab257SBarry Smith   MPI_Comm        comm;
4003bbf0e92SBarry Smith   PetscBool       isblock;
4013a40ed3dSBarry Smith 
4023a40ed3dSBarry Smith   PetscFunctionBegin;
4030700a824SBarry Smith   PetscValidHeaderSpecific(is, IS_CLASSID, 1);
4044482741eSBarry Smith   PetscValidPointer(mapping, 2);
4052bdab257SBarry Smith 
4069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)is, &comm));
4079566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
4089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)is, ISBLOCK, &isblock));
4096006e8d2SBarry Smith   if (!isblock) {
4109566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &indices));
4119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm, 1, n, indices, PETSC_COPY_VALUES, mapping));
4129566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &indices));
4136006e8d2SBarry Smith   } else {
4149566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(is, &bs));
4159566063dSJacob Faibussowitsch     PetscCall(ISBlockGetIndices(is, &indices));
4169566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm, bs, n / bs, indices, PETSC_COPY_VALUES, mapping));
4179566063dSJacob Faibussowitsch     PetscCall(ISBlockRestoreIndices(is, &indices));
4186006e8d2SBarry Smith   }
4193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4202bdab257SBarry Smith }
4215a5d4f66SBarry Smith 
422a4d96a55SJed Brown /*@C
423a4d96a55SJed Brown   ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n)
424a4d96a55SJed Brown   ordering and a global parallel ordering.
425a4d96a55SJed Brown 
426a4d96a55SJed Brown   Collective
427a4d96a55SJed Brown 
428d8d19677SJose E. Roman   Input Parameters:
429a4d96a55SJed Brown + sf    - star forest mapping contiguous local indices to (rank, offset)
430cab54364SBarry Smith - start - first global index on this process, or `PETSC_DECIDE` to compute contiguous global numbering automatically
431a4d96a55SJed Brown 
432a4d96a55SJed Brown   Output Parameter:
433a4d96a55SJed Brown . mapping - new mapping data structure
434a4d96a55SJed Brown 
435a4d96a55SJed Brown   Level: advanced
436a4d96a55SJed Brown 
43720662ed9SBarry Smith   Note:
43820662ed9SBarry Smith   If any processor calls this with `start` = `PETSC_DECIDE` then all processors must, otherwise the program will hang.
4399a535bafSVaclav Hapla 
440cab54364SBarry Smith .seealso: [](sec_scatter), `PetscSF`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`
441a4d96a55SJed Brown @*/
442d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf, PetscInt start, ISLocalToGlobalMapping *mapping)
443d71ae5a4SJacob Faibussowitsch {
444a4d96a55SJed Brown   PetscInt i, maxlocal, nroots, nleaves, *globals, *ltog;
445a4d96a55SJed Brown   MPI_Comm comm;
446a4d96a55SJed Brown 
447a4d96a55SJed Brown   PetscFunctionBegin;
448a4d96a55SJed Brown   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
449a4d96a55SJed Brown   PetscValidPointer(mapping, 3);
4509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
45141f4c31fSVaclav Hapla   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
4529a535bafSVaclav Hapla   if (start == PETSC_DECIDE) {
4539a535bafSVaclav Hapla     start = 0;
4549566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Exscan(&nroots, &start, 1, MPIU_INT, MPI_SUM, comm));
45541f4c31fSVaclav Hapla   } else PetscCheck(start >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "start must be nonnegative or PETSC_DECIDE");
45641f4c31fSVaclav Hapla   PetscCall(PetscSFGetLeafRange(sf, NULL, &maxlocal));
45741f4c31fSVaclav Hapla   ++maxlocal;
4589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &globals));
4599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxlocal, &ltog));
460a4d96a55SJed Brown   for (i = 0; i < nroots; i++) globals[i] = start + i;
461a4d96a55SJed Brown   for (i = 0; i < maxlocal; i++) ltog[i] = -1;
4629566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globals, ltog, MPI_REPLACE));
4639566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globals, ltog, MPI_REPLACE));
4649566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm, 1, maxlocal, ltog, PETSC_OWN_POINTER, mapping));
4659566063dSJacob Faibussowitsch   PetscCall(PetscFree(globals));
4663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
467a4d96a55SJed Brown }
468b46b645bSBarry Smith 
46963fa5c83Sstefano_zampini /*@
47063fa5c83Sstefano_zampini   ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
47163fa5c83Sstefano_zampini 
47220662ed9SBarry Smith   Not Collective
47363fa5c83Sstefano_zampini 
47463fa5c83Sstefano_zampini   Input Parameters:
475a2b725a8SWilliam Gropp + mapping - mapping data structure
476a2b725a8SWilliam Gropp - bs      - the blocksize
47763fa5c83Sstefano_zampini 
47863fa5c83Sstefano_zampini   Level: advanced
47963fa5c83Sstefano_zampini 
480cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`
48163fa5c83Sstefano_zampini @*/
482d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping, PetscInt bs)
483d71ae5a4SJacob Faibussowitsch {
484a59f3c4dSstefano_zampini   PetscInt       *nid;
485a59f3c4dSstefano_zampini   const PetscInt *oid;
486a59f3c4dSstefano_zampini   PetscInt        i, cn, on, obs, nn;
48763fa5c83Sstefano_zampini 
48863fa5c83Sstefano_zampini   PetscFunctionBegin;
48963fa5c83Sstefano_zampini   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
49008401ef6SPierre Jolivet   PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid block size %" PetscInt_FMT, bs);
4913ba16761SJacob Faibussowitsch   if (bs == mapping->bs) PetscFunctionReturn(PETSC_SUCCESS);
49263fa5c83Sstefano_zampini   on  = mapping->n;
49363fa5c83Sstefano_zampini   obs = mapping->bs;
49463fa5c83Sstefano_zampini   oid = mapping->indices;
49563fa5c83Sstefano_zampini   nn  = (on * obs) / bs;
49608401ef6SPierre Jolivet   PetscCheck((on * obs) % bs == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Block size %" PetscInt_FMT " is inconsistent with block size %" PetscInt_FMT " and number of block indices %" PetscInt_FMT, bs, obs, on);
497a59f3c4dSstefano_zampini 
4989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nn, &nid));
4999566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &oid));
500a59f3c4dSstefano_zampini   for (i = 0; i < nn; i++) {
501a59f3c4dSstefano_zampini     PetscInt j;
502a59f3c4dSstefano_zampini     for (j = 0, cn = 0; j < bs - 1; j++) {
5039371c9d4SSatish Balay       if (oid[i * bs + j] < 0) {
5049371c9d4SSatish Balay         cn++;
5059371c9d4SSatish Balay         continue;
5069371c9d4SSatish Balay       }
50708401ef6SPierre Jolivet       PetscCheck(oid[i * bs + j] == oid[i * bs + j + 1] - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Block sizes %" PetscInt_FMT " and %" PetscInt_FMT " are incompatible with the block indices: non consecutive indices %" PetscInt_FMT " %" PetscInt_FMT, bs, obs, oid[i * bs + j], oid[i * bs + j + 1]);
508a59f3c4dSstefano_zampini     }
509a59f3c4dSstefano_zampini     if (oid[i * bs + j] < 0) cn++;
5108b7cb0e6Sstefano_zampini     if (cn) {
51108401ef6SPierre Jolivet       PetscCheck(cn == bs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Block sizes %" PetscInt_FMT " and %" PetscInt_FMT " are incompatible with the block indices: invalid number of negative entries in block %" PetscInt_FMT, bs, obs, cn);
512a59f3c4dSstefano_zampini       nid[i] = -1;
5138b7cb0e6Sstefano_zampini     } else {
514a59f3c4dSstefano_zampini       nid[i] = oid[i * bs] / bs;
51563fa5c83Sstefano_zampini     }
51663fa5c83Sstefano_zampini   }
5179566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &oid));
518a59f3c4dSstefano_zampini 
51963fa5c83Sstefano_zampini   mapping->n  = nn;
52063fa5c83Sstefano_zampini   mapping->bs = bs;
5219566063dSJacob Faibussowitsch   PetscCall(PetscFree(mapping->indices));
52263fa5c83Sstefano_zampini   mapping->indices     = nid;
523c9345713Sstefano_zampini   mapping->globalstart = 0;
524c9345713Sstefano_zampini   mapping->globalend   = 0;
5251bd0b88eSStefano Zampini 
5261bd0b88eSStefano Zampini   /* reset the cached information */
5279566063dSJacob Faibussowitsch   PetscCall(PetscFree(mapping->info_procs));
5289566063dSJacob Faibussowitsch   PetscCall(PetscFree(mapping->info_numprocs));
5291bd0b88eSStefano Zampini   if (mapping->info_indices) {
5301bd0b88eSStefano Zampini     PetscInt i;
5311bd0b88eSStefano Zampini 
5329566063dSJacob Faibussowitsch     PetscCall(PetscFree((mapping->info_indices)[0]));
53348a46eb9SPierre Jolivet     for (i = 1; i < mapping->info_nproc; i++) PetscCall(PetscFree(mapping->info_indices[i]));
5349566063dSJacob Faibussowitsch     PetscCall(PetscFree(mapping->info_indices));
5351bd0b88eSStefano Zampini   }
5361bd0b88eSStefano Zampini   mapping->info_cached = PETSC_FALSE;
5371bd0b88eSStefano Zampini 
538dbbe0bcdSBarry Smith   PetscTryTypeMethod(mapping, destroy);
5393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54063fa5c83Sstefano_zampini }
54163fa5c83Sstefano_zampini 
54245b6f7e9SBarry Smith /*@
54345b6f7e9SBarry Smith   ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
54445b6f7e9SBarry Smith   ordering and a global parallel ordering.
54545b6f7e9SBarry Smith 
54645b6f7e9SBarry Smith   Not Collective
54745b6f7e9SBarry Smith 
5482fe279fdSBarry Smith   Input Parameter:
54945b6f7e9SBarry Smith . mapping - mapping data structure
55045b6f7e9SBarry Smith 
55145b6f7e9SBarry Smith   Output Parameter:
55245b6f7e9SBarry Smith . bs - the blocksize
55345b6f7e9SBarry Smith 
55445b6f7e9SBarry Smith   Level: advanced
55545b6f7e9SBarry Smith 
556cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`
55745b6f7e9SBarry Smith @*/
558d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping, PetscInt *bs)
559d71ae5a4SJacob Faibussowitsch {
56045b6f7e9SBarry Smith   PetscFunctionBegin;
561cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
56245b6f7e9SBarry Smith   *bs = mapping->bs;
5633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56445b6f7e9SBarry Smith }
56545b6f7e9SBarry Smith 
566ba5bb76aSSatish Balay /*@
56790f02eecSBarry Smith   ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
56890f02eecSBarry Smith   ordering and a global parallel ordering.
5692362add9SBarry Smith 
57089d82c54SBarry Smith   Not Collective, but communicator may have more than one process
571b9cd556bSLois Curfman McInnes 
5722362add9SBarry Smith   Input Parameters:
57389d82c54SBarry Smith + comm    - MPI communicator
574f0413b6fSBarry Smith . bs      - the block size
57528bc9809SBarry Smith . n       - the number of local elements divided by the block size, or equivalently the number of block indices
57628bc9809SBarry 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
577d5ad8652SBarry Smith - mode    - see PetscCopyMode
5782362add9SBarry Smith 
579a997ad1aSLois Curfman McInnes   Output Parameter:
58090f02eecSBarry Smith . mapping - new mapping data structure
5812362add9SBarry Smith 
582cab54364SBarry Smith   Level: advanced
583cab54364SBarry Smith 
58495452b02SPatrick Sanan   Notes:
58595452b02SPatrick Sanan   There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
586413f72f0SBarry Smith 
587cab54364SBarry Smith   For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType`
588cab54364SBarry Smith   of `ISLOCALTOGLOBALMAPPINGBASIC` will be used; this uses more memory but is faster; this approach is not scalable for extremely large mappings.
589413f72f0SBarry Smith 
590cab54364SBarry Smith   For large problems `ISLOCALTOGLOBALMAPPINGHASH` is used, this is scalable.
59120662ed9SBarry Smith   Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option
59220662ed9SBarry Smith   `-islocaltoglobalmapping_type` <`basic`,`hash`> to control which is used.
593a997ad1aSLois Curfman McInnes 
59420662ed9SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`,
59520662ed9SBarry Smith           `ISLOCALTOGLOBALMAPPINGBASIC`, `ISLOCALTOGLOBALMAPPINGHASH`
596db781477SPatrick Sanan           `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType`
5972362add9SBarry Smith @*/
598d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm comm, PetscInt bs, PetscInt n, const PetscInt indices[], PetscCopyMode mode, ISLocalToGlobalMapping *mapping)
599d71ae5a4SJacob Faibussowitsch {
60032dcc486SBarry Smith   PetscInt *in;
601b46b645bSBarry Smith 
602b46b645bSBarry Smith   PetscFunctionBegin;
603064a246eSJacob Faibussowitsch   if (n) PetscValidIntPointer(indices, 4);
604064a246eSJacob Faibussowitsch   PetscValidPointer(mapping, 6);
605b46b645bSBarry Smith 
6060298fd71SBarry Smith   *mapping = NULL;
6079566063dSJacob Faibussowitsch   PetscCall(ISInitializePackage());
6082362add9SBarry Smith 
6099566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*mapping, IS_LTOGM_CLASSID, "ISLocalToGlobalMapping", "Local to global mapping", "IS", comm, ISLocalToGlobalMappingDestroy, ISLocalToGlobalMappingView));
610d4bb536fSBarry Smith   (*mapping)->n  = n;
611f0413b6fSBarry Smith   (*mapping)->bs = bs;
612d5ad8652SBarry Smith   if (mode == PETSC_COPY_VALUES) {
6139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &in));
6149566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(in, indices, n));
615d5ad8652SBarry Smith     (*mapping)->indices         = in;
61671910c26SVaclav Hapla     (*mapping)->dealloc_indices = PETSC_TRUE;
6176389a1a1SBarry Smith   } else if (mode == PETSC_OWN_POINTER) {
6186389a1a1SBarry Smith     (*mapping)->indices         = (PetscInt *)indices;
61971910c26SVaclav Hapla     (*mapping)->dealloc_indices = PETSC_TRUE;
62071910c26SVaclav Hapla   } else if (mode == PETSC_USE_POINTER) {
62171910c26SVaclav Hapla     (*mapping)->indices = (PetscInt *)indices;
6229371c9d4SSatish Balay   } else SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid mode %d", mode);
6233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6242362add9SBarry Smith }
6252362add9SBarry Smith 
626413f72f0SBarry Smith PetscFunctionList ISLocalToGlobalMappingList = NULL;
627413f72f0SBarry Smith 
62890f02eecSBarry Smith /*@
6297e99dc12SLawrence Mitchell   ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database.
6307e99dc12SLawrence Mitchell 
63120662ed9SBarry Smith   Not Collective
6327e99dc12SLawrence Mitchell 
6332fe279fdSBarry Smith   Input Parameter:
6347e99dc12SLawrence Mitchell . mapping - mapping data structure
6357e99dc12SLawrence Mitchell 
63620662ed9SBarry Smith   Options Database Key:
63720662ed9SBarry Smith . -islocaltoglobalmapping_type - <basic,hash> nonscalable and scalable versions
63820662ed9SBarry Smith 
6397e99dc12SLawrence Mitchell   Level: advanced
6407e99dc12SLawrence Mitchell 
64120662ed9SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`,
64220662ed9SBarry Smith           `ISLOCALTOGLOBALMAPPINGBASIC`, `ISLOCALTOGLOBALMAPPINGHASH`
643cab54364SBarry Smith           `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType`
6447e99dc12SLawrence Mitchell @*/
645d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)
646d71ae5a4SJacob Faibussowitsch {
647413f72f0SBarry Smith   char                       type[256];
648413f72f0SBarry Smith   ISLocalToGlobalMappingType defaulttype = "Not set";
6497e99dc12SLawrence Mitchell   PetscBool                  flg;
6507e99dc12SLawrence Mitchell 
6517e99dc12SLawrence Mitchell   PetscFunctionBegin;
6527e99dc12SLawrence Mitchell   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
6539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRegisterAll());
654d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)mapping);
6559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-islocaltoglobalmapping_type", "ISLocalToGlobalMapping method", "ISLocalToGlobalMappingSetType", ISLocalToGlobalMappingList, (char *)(((PetscObject)mapping)->type_name) ? ((PetscObject)mapping)->type_name : defaulttype, type, 256, &flg));
6561baa6e33SBarry Smith   if (flg) PetscCall(ISLocalToGlobalMappingSetType(mapping, type));
657d0609cedSBarry Smith   PetscOptionsEnd();
6583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6597e99dc12SLawrence Mitchell }
6607e99dc12SLawrence Mitchell 
6617e99dc12SLawrence Mitchell /*@
66290f02eecSBarry Smith   ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
66390f02eecSBarry Smith   ordering and a global parallel ordering.
66490f02eecSBarry Smith 
66520662ed9SBarry Smith   Not Collective
666b9cd556bSLois Curfman McInnes 
6672fe279fdSBarry Smith   Input Parameter:
66890f02eecSBarry Smith . mapping - mapping data structure
66990f02eecSBarry Smith 
670a997ad1aSLois Curfman McInnes   Level: advanced
671a997ad1aSLois Curfman McInnes 
672cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`
67390f02eecSBarry Smith @*/
674d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
675d71ae5a4SJacob Faibussowitsch {
6763a40ed3dSBarry Smith   PetscFunctionBegin;
6773ba16761SJacob Faibussowitsch   if (!*mapping) PetscFunctionReturn(PETSC_SUCCESS);
6786bf464f9SBarry Smith   PetscValidHeaderSpecific((*mapping), IS_LTOGM_CLASSID, 1);
6799371c9d4SSatish Balay   if (--((PetscObject)(*mapping))->refct > 0) {
6809371c9d4SSatish Balay     *mapping = NULL;
6813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
68271910c26SVaclav Hapla   }
68348a46eb9SPierre Jolivet   if ((*mapping)->dealloc_indices) PetscCall(PetscFree((*mapping)->indices));
6849566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mapping)->info_procs));
6859566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mapping)->info_numprocs));
686268a049cSStefano Zampini   if ((*mapping)->info_indices) {
687268a049cSStefano Zampini     PetscInt i;
688268a049cSStefano Zampini 
6899566063dSJacob Faibussowitsch     PetscCall(PetscFree(((*mapping)->info_indices)[0]));
69048a46eb9SPierre Jolivet     for (i = 1; i < (*mapping)->info_nproc; i++) PetscCall(PetscFree(((*mapping)->info_indices)[i]));
6919566063dSJacob Faibussowitsch     PetscCall(PetscFree((*mapping)->info_indices));
692268a049cSStefano Zampini   }
69348a46eb9SPierre Jolivet   if ((*mapping)->info_nodei) PetscCall(PetscFree(((*mapping)->info_nodei)[0]));
6949566063dSJacob Faibussowitsch   PetscCall(PetscFree2((*mapping)->info_nodec, (*mapping)->info_nodei));
69548a46eb9SPierre Jolivet   if ((*mapping)->ops->destroy) PetscCall((*(*mapping)->ops->destroy)(*mapping));
6969566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(mapping));
6974c8fdceaSLisandro Dalcin   *mapping = NULL;
6983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69990f02eecSBarry Smith }
70090f02eecSBarry Smith 
70190f02eecSBarry Smith /*@
702cab54364SBarry Smith   ISLocalToGlobalMappingApplyIS - Creates from an `IS` in the local numbering
703cab54364SBarry Smith   a new index set using the global numbering defined in an `ISLocalToGlobalMapping`
7043acfe500SLois Curfman McInnes   context.
70590f02eecSBarry Smith 
706c3339decSBarry Smith   Collective
707b9cd556bSLois Curfman McInnes 
70890f02eecSBarry Smith   Input Parameters:
709b9cd556bSLois Curfman McInnes + mapping - mapping between local and global numbering
710b9cd556bSLois Curfman McInnes - is      - index set in local numbering
71190f02eecSBarry Smith 
712cab54364SBarry Smith   Output Parameter:
71390f02eecSBarry Smith . newis - index set in global numbering
71490f02eecSBarry Smith 
715a997ad1aSLois Curfman McInnes   Level: advanced
716a997ad1aSLois Curfman McInnes 
717cab54364SBarry Smith   Note:
71820662ed9SBarry Smith   The output `IS` will have the same communicator as the input `IS`.
719cab54364SBarry Smith 
720cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
721db781477SPatrick Sanan           `ISLocalToGlobalMappingDestroy()`, `ISGlobalToLocalMappingApply()`
72290f02eecSBarry Smith @*/
723d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping, IS is, IS *newis)
724d71ae5a4SJacob Faibussowitsch {
725e24637baSBarry Smith   PetscInt        n, *idxout;
7265d0c19d7SBarry Smith   const PetscInt *idxin;
7273a40ed3dSBarry Smith 
7283a40ed3dSBarry Smith   PetscFunctionBegin;
7290700a824SBarry Smith   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
7300700a824SBarry Smith   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
7314482741eSBarry Smith   PetscValidPointer(newis, 3);
73290f02eecSBarry Smith 
7339566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
7349566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &idxin));
7359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &idxout));
7369566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(mapping, n, idxin, idxout));
7379566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &idxin));
7389566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), n, idxout, PETSC_OWN_POINTER, newis));
7393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74090f02eecSBarry Smith }
74190f02eecSBarry Smith 
742b89cb25eSSatish Balay /*@
7433acfe500SLois Curfman McInnes   ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
7443acfe500SLois Curfman McInnes   and converts them to the global numbering.
74590f02eecSBarry Smith 
74620662ed9SBarry Smith   Not Collective
747b9cd556bSLois Curfman McInnes 
748bb25748dSBarry Smith   Input Parameters:
749b9cd556bSLois Curfman McInnes + mapping - the local to global mapping context
750bb25748dSBarry Smith . N       - number of integers
751b9cd556bSLois Curfman McInnes - in      - input indices in local numbering
752bb25748dSBarry Smith 
753bb25748dSBarry Smith   Output Parameter:
754bb25748dSBarry Smith . out - indices in global numbering
755bb25748dSBarry Smith 
756a997ad1aSLois Curfman McInnes   Level: advanced
757a997ad1aSLois Curfman McInnes 
758cab54364SBarry Smith   Note:
75920662ed9SBarry Smith   The `in` and `out` array parameters may be identical.
760cab54364SBarry Smith 
761cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`,
762c2e3fba1SPatrick Sanan           `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`,
763db781477SPatrick Sanan           `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()`
764afcb2eb5SJed Brown @*/
765d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[])
766d71ae5a4SJacob Faibussowitsch {
767cbc1caf0SMatthew G. Knepley   PetscInt i, bs, Nmax;
76845b6f7e9SBarry Smith 
76945b6f7e9SBarry Smith   PetscFunctionBegin;
770cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
771cbc1caf0SMatthew G. Knepley   bs   = mapping->bs;
772cbc1caf0SMatthew G. Knepley   Nmax = bs * mapping->n;
77345b6f7e9SBarry Smith   if (bs == 1) {
774cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
77545b6f7e9SBarry Smith     for (i = 0; i < N; i++) {
77645b6f7e9SBarry Smith       if (in[i] < 0) {
77745b6f7e9SBarry Smith         out[i] = in[i];
77845b6f7e9SBarry Smith         continue;
77945b6f7e9SBarry Smith       }
78008401ef6SPierre Jolivet       PetscCheck(in[i] < Nmax, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local index %" PetscInt_FMT " too large %" PetscInt_FMT " (max) at %" PetscInt_FMT, in[i], Nmax - 1, i);
78145b6f7e9SBarry Smith       out[i] = idx[in[i]];
78245b6f7e9SBarry Smith     }
78345b6f7e9SBarry Smith   } else {
784cbc1caf0SMatthew G. Knepley     const PetscInt *idx = mapping->indices;
78545b6f7e9SBarry Smith     for (i = 0; i < N; i++) {
78645b6f7e9SBarry Smith       if (in[i] < 0) {
78745b6f7e9SBarry Smith         out[i] = in[i];
78845b6f7e9SBarry Smith         continue;
78945b6f7e9SBarry Smith       }
79008401ef6SPierre Jolivet       PetscCheck(in[i] < Nmax, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local index %" PetscInt_FMT " too large %" PetscInt_FMT " (max) at %" PetscInt_FMT, in[i], Nmax - 1, i);
79145b6f7e9SBarry Smith       out[i] = idx[in[i] / bs] * bs + (in[i] % bs);
79245b6f7e9SBarry Smith     }
79345b6f7e9SBarry Smith   }
7943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79545b6f7e9SBarry Smith }
79645b6f7e9SBarry Smith 
79745b6f7e9SBarry Smith /*@
7986006e8d2SBarry Smith   ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
79945b6f7e9SBarry Smith 
80020662ed9SBarry Smith   Not Collective
80145b6f7e9SBarry Smith 
80245b6f7e9SBarry Smith   Input Parameters:
80345b6f7e9SBarry Smith + mapping - the local to global mapping context
80445b6f7e9SBarry Smith . N       - number of integers
8056006e8d2SBarry Smith - in      - input indices in local block numbering
80645b6f7e9SBarry Smith 
80745b6f7e9SBarry Smith   Output Parameter:
8086006e8d2SBarry Smith . out - indices in global block numbering
80945b6f7e9SBarry Smith 
8106006e8d2SBarry Smith   Example:
811cab54364SBarry 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
8126006e8d2SBarry Smith   (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
8136006e8d2SBarry Smith 
81420662ed9SBarry Smith   Level: advanced
81520662ed9SBarry Smith 
81620662ed9SBarry Smith   Note:
81720662ed9SBarry Smith   The `in` and `out` array parameters may be identical.
81820662ed9SBarry Smith 
819cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`,
820c2e3fba1SPatrick Sanan           `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`,
821db781477SPatrick Sanan           `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()`
82245b6f7e9SBarry Smith @*/
823d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[])
824d71ae5a4SJacob Faibussowitsch {
8258a1f772fSStefano Zampini   PetscInt        i, Nmax;
8268a1f772fSStefano Zampini   const PetscInt *idx;
827d4bb536fSBarry Smith 
828a0d79125SStefano Zampini   PetscFunctionBegin;
829a0d79125SStefano Zampini   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
8308a1f772fSStefano Zampini   Nmax = mapping->n;
8318a1f772fSStefano Zampini   idx  = mapping->indices;
832afcb2eb5SJed Brown   for (i = 0; i < N; i++) {
833afcb2eb5SJed Brown     if (in[i] < 0) {
834afcb2eb5SJed Brown       out[i] = in[i];
835afcb2eb5SJed Brown       continue;
836afcb2eb5SJed Brown     }
83708401ef6SPierre Jolivet     PetscCheck(in[i] < Nmax, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local block index %" PetscInt_FMT " too large %" PetscInt_FMT " (max) at %" PetscInt_FMT, in[i], Nmax - 1, i);
838afcb2eb5SJed Brown     out[i] = idx[in[i]];
839afcb2eb5SJed Brown   }
8403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
841afcb2eb5SJed Brown }
842d4bb536fSBarry Smith 
8437e99dc12SLawrence Mitchell /*@
844a997ad1aSLois Curfman McInnes   ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
845a997ad1aSLois Curfman McInnes   specified with a global numbering.
846d4bb536fSBarry Smith 
84720662ed9SBarry Smith   Not Collective
848b9cd556bSLois Curfman McInnes 
849d4bb536fSBarry Smith   Input Parameters:
850b9cd556bSLois Curfman McInnes + mapping - mapping between local and global numbering
851cab54364SBarry Smith . type    - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
852cab54364SBarry Smith            `IS_GTOLM_DROP` - drops the indices with no local value from the output list
853d4bb536fSBarry Smith . n       - number of global indices to map
854b9cd556bSLois Curfman McInnes - idx     - global indices to map
855d4bb536fSBarry Smith 
856d4bb536fSBarry Smith   Output Parameters:
857cab54364SBarry Smith + nout   - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n)
858b9cd556bSLois Curfman McInnes - idxout - local index of each global index, one must pass in an array long enough
859cab54364SBarry Smith              to hold all the indices. You can call `ISGlobalToLocalMappingApply()` with
8600298fd71SBarry Smith              idxout == NULL to determine the required length (returned in nout)
861cab54364SBarry Smith              and then allocate the required space and call `ISGlobalToLocalMappingApply()`
862e182c471SBarry Smith              a second time to set the values.
863d4bb536fSBarry Smith 
864cab54364SBarry Smith   Level: advanced
865cab54364SBarry Smith 
866b9cd556bSLois Curfman McInnes   Notes:
86720662ed9SBarry Smith   Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical.
868d4bb536fSBarry Smith 
86920662ed9SBarry Smith   For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of
87020662ed9SBarry Smith   `ISLOCALTOGLOBALMAPPINGBASIC` will be used;
871cab54364SBarry 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.
872cab54364SBarry Smith   Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
8730f5bd95cSBarry Smith 
87438b5cf2dSJacob Faibussowitsch   Developer Notes:
87520662ed9SBarry Smith   The manual page states that `idx` and `idxout` may be identical but the calling
87620662ed9SBarry Smith   sequence declares `idx` as const so it cannot be the same as `idxout`.
87732fd6b96SBarry Smith 
878cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`,
879db781477SPatrick Sanan           `ISLocalToGlobalMappingDestroy()`
880d4bb536fSBarry Smith @*/
881d71ae5a4SJacob Faibussowitsch PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[])
882d71ae5a4SJacob Faibussowitsch {
8839d90f715SBarry Smith   PetscFunctionBegin;
8849d90f715SBarry Smith   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
88548a46eb9SPierre Jolivet   if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping));
886dbbe0bcdSBarry Smith   PetscUseTypeMethod(mapping, globaltolocalmappingapply, type, n, idx, nout, idxout);
8873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8889d90f715SBarry Smith }
8899d90f715SBarry Smith 
890d4fe737eSStefano Zampini /*@
891cab54364SBarry Smith   ISGlobalToLocalMappingApplyIS - Creates from an `IS` in the global numbering
892cab54364SBarry Smith   a new index set using the local numbering defined in an `ISLocalToGlobalMapping`
893d4fe737eSStefano Zampini   context.
894d4fe737eSStefano Zampini 
89520662ed9SBarry Smith   Not Collective
896d4fe737eSStefano Zampini 
897d4fe737eSStefano Zampini   Input Parameters:
898d4fe737eSStefano Zampini + mapping - mapping between local and global numbering
899cab54364SBarry Smith . type    - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
900cab54364SBarry Smith            `IS_GTOLM_DROP` - drops the indices with no local value from the output list
901d4fe737eSStefano Zampini - is      - index set in global numbering
902d4fe737eSStefano Zampini 
9032fe279fdSBarry Smith   Output Parameter:
904d4fe737eSStefano Zampini . newis - index set in local numbering
905d4fe737eSStefano Zampini 
906d4fe737eSStefano Zampini   Level: advanced
907d4fe737eSStefano Zampini 
908cab54364SBarry Smith   Note:
909cab54364SBarry Smith   The output `IS` will be sequential, as it encodes a purely local operation
910cab54364SBarry Smith 
911cab54364SBarry Smith .seealso: [](sec_scatter), `ISGlobalToLocalMapping`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
912db781477SPatrick Sanan           `ISLocalToGlobalMappingDestroy()`
913d4fe737eSStefano Zampini @*/
914d71ae5a4SJacob Faibussowitsch PetscErrorCode ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, IS is, IS *newis)
915d71ae5a4SJacob Faibussowitsch {
916d4fe737eSStefano Zampini   PetscInt        n, nout, *idxout;
917d4fe737eSStefano Zampini   const PetscInt *idxin;
918d4fe737eSStefano Zampini 
919d4fe737eSStefano Zampini   PetscFunctionBegin;
920d4fe737eSStefano Zampini   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
921d4fe737eSStefano Zampini   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
922d4fe737eSStefano Zampini   PetscValidPointer(newis, 4);
923d4fe737eSStefano Zampini 
9249566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
9259566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &idxin));
926d4fe737eSStefano Zampini   if (type == IS_GTOLM_MASK) {
9279566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &idxout));
928d4fe737eSStefano Zampini   } else {
9299566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, NULL));
9309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nout, &idxout));
931d4fe737eSStefano Zampini   }
9329566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, idxout));
9339566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &idxin));
9349566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nout, idxout, PETSC_OWN_POINTER, newis));
9353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
936d4fe737eSStefano Zampini }
937d4fe737eSStefano Zampini 
9389d90f715SBarry Smith /*@
9399d90f715SBarry Smith   ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
9409d90f715SBarry Smith   specified with a block global numbering.
9419d90f715SBarry Smith 
94220662ed9SBarry Smith   Not Collective
9439d90f715SBarry Smith 
9449d90f715SBarry Smith   Input Parameters:
9459d90f715SBarry Smith + mapping - mapping between local and global numbering
946cab54364SBarry Smith . type    - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
947cab54364SBarry Smith            `IS_GTOLM_DROP` - drops the indices with no local value from the output list
9489d90f715SBarry Smith . n       - number of global indices to map
9499d90f715SBarry Smith - idx     - global indices to map
9509d90f715SBarry Smith 
9519d90f715SBarry Smith   Output Parameters:
952cab54364SBarry Smith + nout   - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n)
9539d90f715SBarry Smith - idxout - local index of each global index, one must pass in an array long enough
954cab54364SBarry Smith              to hold all the indices. You can call `ISGlobalToLocalMappingApplyBlock()` with
9559d90f715SBarry Smith              idxout == NULL to determine the required length (returned in nout)
956cab54364SBarry Smith              and then allocate the required space and call `ISGlobalToLocalMappingApplyBlock()`
9579d90f715SBarry Smith              a second time to set the values.
9589d90f715SBarry Smith 
959cab54364SBarry Smith   Level: advanced
960cab54364SBarry Smith 
9619d90f715SBarry Smith   Notes:
96220662ed9SBarry Smith   Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical.
9639d90f715SBarry Smith 
96420662ed9SBarry Smith   For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of
96520662ed9SBarry Smith   `ISLOCALTOGLOBALMAPPINGBASIC` will be used;
966cab54364SBarry 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.
967cab54364SBarry Smith   Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
9689d90f715SBarry Smith 
96938b5cf2dSJacob Faibussowitsch   Developer Notes:
97020662ed9SBarry Smith   The manual page states that `idx` and `idxout` may be identical but the calling
97120662ed9SBarry Smith   sequence declares `idx` as const so it cannot be the same as `idxout`.
9729d90f715SBarry Smith 
973cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
974db781477SPatrick Sanan           `ISLocalToGlobalMappingDestroy()`
9759d90f715SBarry Smith @*/
976d71ae5a4SJacob Faibussowitsch PetscErrorCode ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[])
977d71ae5a4SJacob Faibussowitsch {
9783a40ed3dSBarry Smith   PetscFunctionBegin;
9790700a824SBarry Smith   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
98048a46eb9SPierre Jolivet   if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping));
981dbbe0bcdSBarry Smith   PetscUseTypeMethod(mapping, globaltolocalmappingapplyblock, type, n, idx, nout, idxout);
9823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
983d4bb536fSBarry Smith }
98490f02eecSBarry Smith 
98589d82c54SBarry Smith /*@C
9866a818285SBarry Smith   ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and
98789d82c54SBarry Smith   each index shared by more than one processor
98889d82c54SBarry Smith 
989c3339decSBarry Smith   Collective
99089d82c54SBarry Smith 
991f899ff85SJose E. Roman   Input Parameter:
99289d82c54SBarry Smith . mapping - the mapping from local to global indexing
99389d82c54SBarry Smith 
994d8d19677SJose E. Roman   Output Parameters:
99589d82c54SBarry Smith + nproc    - number of processors that are connected to this one
99638b5cf2dSJacob Faibussowitsch . procs    - neighboring processors
99738b5cf2dSJacob Faibussowitsch . numprocs - number of indices for each subdomain (processor)
9983463a7baSJed Brown - indices  - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
99989d82c54SBarry Smith 
100089d82c54SBarry Smith   Level: advanced
100189d82c54SBarry Smith 
100238b5cf2dSJacob Faibussowitsch   Fortran Notes:
1003*e33f79d8SJacob Faibussowitsch   There is no `ISLocalToGlobalMappingRestoreInfo()` in Fortran. You must make sure that
1004*e33f79d8SJacob Faibussowitsch   `procs`[], `numprocs`[] and `indices`[][] are large enough arrays, either by allocating them
1005*e33f79d8SJacob Faibussowitsch   dynamically or defining static ones large enough.
1006cab54364SBarry Smith .vb
10072cfcea29SBarry Smith   PetscInt indices[nproc][numprocmax],ierr)
1008cab54364SBarry Smith   ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
1009cab54364SBarry Smith   ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
1010cab54364SBarry Smith .ve
1011cab54364SBarry Smith 
1012cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1013db781477SPatrick Sanan           `ISLocalToGlobalMappingRestoreInfo()`
101489d82c54SBarry Smith @*/
1015d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1016d71ae5a4SJacob Faibussowitsch {
1017268a049cSStefano Zampini   PetscFunctionBegin;
1018268a049cSStefano Zampini   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1019268a049cSStefano Zampini   if (mapping->info_cached) {
1020268a049cSStefano Zampini     *nproc    = mapping->info_nproc;
1021268a049cSStefano Zampini     *procs    = mapping->info_procs;
1022268a049cSStefano Zampini     *numprocs = mapping->info_numprocs;
1023268a049cSStefano Zampini     *indices  = mapping->info_indices;
1024268a049cSStefano Zampini   } else {
10259566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockInfo_Private(mapping, nproc, procs, numprocs, indices));
1026268a049cSStefano Zampini   }
10273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1028268a049cSStefano Zampini }
1029268a049cSStefano Zampini 
1030d71ae5a4SJacob Faibussowitsch static PetscErrorCode ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1031d71ae5a4SJacob Faibussowitsch {
103297f1f81fSBarry Smith   PetscMPIInt  size, rank, tag1, tag2, tag3, *len, *source, imdex;
103332dcc486SBarry Smith   PetscInt     i, n = mapping->n, Ng, ng, max = 0, *lindices = mapping->indices;
103432dcc486SBarry Smith   PetscInt    *nprocs, *owner, nsends, *sends, j, *starts, nmax, nrecvs, *recvs, proc;
1035c599c493SJunchao Zhang   PetscInt     cnt, scale, *ownedsenders, *nownedsenders, rstart;
103632dcc486SBarry Smith   PetscInt     node, nownedm, nt, *sends2, nsends2, *starts2, *lens2, *dest, nrecvs2, *starts3, *recvs2, k, *bprocs, *tmp;
103732dcc486SBarry Smith   PetscInt     first_procs, first_numprocs, *first_indices;
103889d82c54SBarry Smith   MPI_Request *recv_waits, *send_waits;
103930dcb7c9SBarry Smith   MPI_Status   recv_status, *send_status, *recv_statuses;
1040ce94432eSBarry Smith   MPI_Comm     comm;
1041ace3abfcSBarry Smith   PetscBool    debug = PETSC_FALSE;
104289d82c54SBarry Smith 
104389d82c54SBarry Smith   PetscFunctionBegin;
10449566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mapping, &comm));
10459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
10469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
104724cf384cSBarry Smith   if (size == 1) {
104824cf384cSBarry Smith     *nproc = 0;
10490298fd71SBarry Smith     *procs = NULL;
10509566063dSJacob Faibussowitsch     PetscCall(PetscNew(numprocs));
10511e2105dcSBarry Smith     (*numprocs)[0] = 0;
10529566063dSJacob Faibussowitsch     PetscCall(PetscNew(indices));
10530298fd71SBarry Smith     (*indices)[0] = NULL;
1054268a049cSStefano Zampini     /* save info for reuse */
1055268a049cSStefano Zampini     mapping->info_nproc    = *nproc;
1056268a049cSStefano Zampini     mapping->info_procs    = *procs;
1057268a049cSStefano Zampini     mapping->info_numprocs = *numprocs;
1058268a049cSStefano Zampini     mapping->info_indices  = *indices;
1059268a049cSStefano Zampini     mapping->info_cached   = PETSC_TRUE;
10603ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
106124cf384cSBarry Smith   }
106224cf384cSBarry Smith 
10639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)mapping)->options, NULL, "-islocaltoglobalmappinggetinfo_debug", &debug, NULL));
106407b52d57SBarry Smith 
10653677ff5aSBarry Smith   /*
10666a818285SBarry Smith     Notes on ISLocalToGlobalMappingGetBlockInfo
10673677ff5aSBarry Smith 
10683677ff5aSBarry Smith     globally owned node - the nodes that have been assigned to this processor in global
10693677ff5aSBarry Smith            numbering, just for this routine.
10703677ff5aSBarry Smith 
10713677ff5aSBarry Smith     nontrivial globally owned node - node assigned to this processor that is on a subdomain
10723677ff5aSBarry Smith            boundary (i.e. is has more than one local owner)
10733677ff5aSBarry Smith 
10743677ff5aSBarry Smith     locally owned node - node that exists on this processors subdomain
10753677ff5aSBarry Smith 
10763677ff5aSBarry Smith     nontrivial locally owned node - node that is not in the interior (i.e. has more than one
10773677ff5aSBarry Smith            local subdomain
10783677ff5aSBarry Smith   */
10799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mapping, &tag1));
10809566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mapping, &tag2));
10819566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetNewTag((PetscObject)mapping, &tag3));
108289d82c54SBarry Smith 
108389d82c54SBarry Smith   for (i = 0; i < n; i++) {
108489d82c54SBarry Smith     if (lindices[i] > max) max = lindices[i];
108589d82c54SBarry Smith   }
10861c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&max, &Ng, 1, MPIU_INT, MPI_MAX, comm));
108778058e43SBarry Smith   Ng++;
10889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
10899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1090bc8ff85bSBarry Smith   scale = Ng / size + 1;
10919371c9d4SSatish Balay   ng    = scale;
10929371c9d4SSatish Balay   if (rank == size - 1) ng = Ng - scale * (size - 1);
10939371c9d4SSatish Balay   ng     = PetscMax(1, ng);
1094caba0dd0SBarry Smith   rstart = scale * rank;
109589d82c54SBarry Smith 
109689d82c54SBarry Smith   /* determine ownership ranges of global indices */
10979566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2 * size, &nprocs));
10989566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(nprocs, 2 * size));
109989d82c54SBarry Smith 
110089d82c54SBarry Smith   /* determine owners of each local node  */
11019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &owner));
110289d82c54SBarry Smith   for (i = 0; i < n; i++) {
11033677ff5aSBarry Smith     proc                 = lindices[i] / scale; /* processor that globally owns this index */
110427c402fcSBarry Smith     nprocs[2 * proc + 1] = 1;                   /* processor globally owns at least one of ours */
11053677ff5aSBarry Smith     owner[i]             = proc;
110627c402fcSBarry Smith     nprocs[2 * proc]++; /* count of how many that processor globally owns of ours */
110789d82c54SBarry Smith   }
11089371c9d4SSatish Balay   nsends = 0;
11099371c9d4SSatish Balay   for (i = 0; i < size; i++) nsends += nprocs[2 * i + 1];
11109566063dSJacob Faibussowitsch   PetscCall(PetscInfo(mapping, "Number of global owners for my local data %" PetscInt_FMT "\n", nsends));
111189d82c54SBarry Smith 
111289d82c54SBarry Smith   /* inform other processors of number of messages and max length*/
11139566063dSJacob Faibussowitsch   PetscCall(PetscMaxSum(comm, nprocs, &nmax, &nrecvs));
11149566063dSJacob Faibussowitsch   PetscCall(PetscInfo(mapping, "Number of local owners for my global data %" PetscInt_FMT "\n", nrecvs));
111589d82c54SBarry Smith 
111689d82c54SBarry Smith   /* post receives for owned rows */
11179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((2 * nrecvs + 1) * (nmax + 1), &recvs));
11189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &recv_waits));
111948a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv(recvs + 2 * nmax * i, 2 * nmax, MPIU_INT, MPI_ANY_SOURCE, tag1, comm, recv_waits + i));
112089d82c54SBarry Smith 
112189d82c54SBarry Smith   /* pack messages containing lists of local nodes to owners */
11229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2 * n + 1, &sends));
11239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size + 1, &starts));
112489d82c54SBarry Smith   starts[0] = 0;
1125f6e5521dSKarl Rupp   for (i = 1; i < size; i++) starts[i] = starts[i - 1] + 2 * nprocs[2 * i - 2];
112689d82c54SBarry Smith   for (i = 0; i < n; i++) {
112789d82c54SBarry Smith     sends[starts[owner[i]]++] = lindices[i];
112830dcb7c9SBarry Smith     sends[starts[owner[i]]++] = i;
112989d82c54SBarry Smith   }
11309566063dSJacob Faibussowitsch   PetscCall(PetscFree(owner));
113189d82c54SBarry Smith   starts[0] = 0;
1132f6e5521dSKarl Rupp   for (i = 1; i < size; i++) starts[i] = starts[i - 1] + 2 * nprocs[2 * i - 2];
113389d82c54SBarry Smith 
113489d82c54SBarry Smith   /* send the messages */
11359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nsends + 1, &send_waits));
11369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nsends + 1, &dest));
113789d82c54SBarry Smith   cnt = 0;
113889d82c54SBarry Smith   for (i = 0; i < size; i++) {
113927c402fcSBarry Smith     if (nprocs[2 * i]) {
11409566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(sends + starts[i], 2 * nprocs[2 * i], MPIU_INT, i, tag1, comm, send_waits + cnt));
114130dcb7c9SBarry Smith       dest[cnt] = i;
114289d82c54SBarry Smith       cnt++;
114389d82c54SBarry Smith     }
114489d82c54SBarry Smith   }
11459566063dSJacob Faibussowitsch   PetscCall(PetscFree(starts));
114689d82c54SBarry Smith 
114789d82c54SBarry Smith   /* wait on receives */
11489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &source));
11499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &len));
115089d82c54SBarry Smith   cnt = nrecvs;
11519566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(ng + 1, &nownedsenders));
115289d82c54SBarry Smith   while (cnt) {
11539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitany(nrecvs, recv_waits, &imdex, &recv_status));
115489d82c54SBarry Smith     /* unpack receives into our local space */
11559566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get_count(&recv_status, MPIU_INT, &len[imdex]));
115689d82c54SBarry Smith     source[imdex] = recv_status.MPI_SOURCE;
115730dcb7c9SBarry Smith     len[imdex]    = len[imdex] / 2;
1158caba0dd0SBarry Smith     /* count how many local owners for each of my global owned indices */
115930dcb7c9SBarry Smith     for (i = 0; i < len[imdex]; i++) nownedsenders[recvs[2 * imdex * nmax + 2 * i] - rstart]++;
116089d82c54SBarry Smith     cnt--;
116189d82c54SBarry Smith   }
11629566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_waits));
116389d82c54SBarry Smith 
116430dcb7c9SBarry Smith   /* count how many globally owned indices are on an edge multiplied by how many processors own them. */
1165bc8ff85bSBarry Smith   nownedm = 0;
1166bc8ff85bSBarry Smith   for (i = 0; i < ng; i++) {
1167c599c493SJunchao Zhang     if (nownedsenders[i] > 1) nownedm += nownedsenders[i];
1168bc8ff85bSBarry Smith   }
1169bc8ff85bSBarry Smith 
1170bc8ff85bSBarry Smith   /* create single array to contain rank of all local owners of each globally owned index */
11719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nownedm + 1, &ownedsenders));
11729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ng + 1, &starts));
1173bc8ff85bSBarry Smith   starts[0] = 0;
1174bc8ff85bSBarry Smith   for (i = 1; i < ng; i++) {
1175bc8ff85bSBarry Smith     if (nownedsenders[i - 1] > 1) starts[i] = starts[i - 1] + nownedsenders[i - 1];
1176bc8ff85bSBarry Smith     else starts[i] = starts[i - 1];
1177bc8ff85bSBarry Smith   }
1178bc8ff85bSBarry Smith 
11796aad120cSJose E. Roman   /* for each nontrivial globally owned node list all arriving processors */
1180bc8ff85bSBarry Smith   for (i = 0; i < nrecvs; i++) {
1181bc8ff85bSBarry Smith     for (j = 0; j < len[i]; j++) {
118230dcb7c9SBarry Smith       node = recvs[2 * i * nmax + 2 * j] - rstart;
1183f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i];
1184bc8ff85bSBarry Smith     }
1185bc8ff85bSBarry Smith   }
1186bc8ff85bSBarry Smith 
118707b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
118830dcb7c9SBarry Smith     starts[0] = 0;
118930dcb7c9SBarry Smith     for (i = 1; i < ng; i++) {
119030dcb7c9SBarry Smith       if (nownedsenders[i - 1] > 1) starts[i] = starts[i - 1] + nownedsenders[i - 1];
119130dcb7c9SBarry Smith       else starts[i] = starts[i - 1];
119230dcb7c9SBarry Smith     }
119330dcb7c9SBarry Smith     for (i = 0; i < ng; i++) {
119430dcb7c9SBarry Smith       if (nownedsenders[i] > 1) {
11959566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "[%d] global node %" PetscInt_FMT " local owner processors: ", rank, i + rstart));
119648a46eb9SPierre Jolivet         for (j = 0; j < nownedsenders[i]; j++) PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", ownedsenders[starts[i] + j]));
11979566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
119830dcb7c9SBarry Smith       }
119930dcb7c9SBarry Smith     }
12009566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
120107b52d57SBarry Smith   } /* -----------------------------------  */
120230dcb7c9SBarry Smith 
12033677ff5aSBarry Smith   /* wait on original sends */
12043a96401aSBarry Smith   if (nsends) {
12059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nsends, &send_status));
12069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(nsends, send_waits, send_status));
12079566063dSJacob Faibussowitsch     PetscCall(PetscFree(send_status));
12083a96401aSBarry Smith   }
12099566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_waits));
12109566063dSJacob Faibussowitsch   PetscCall(PetscFree(sends));
12119566063dSJacob Faibussowitsch   PetscCall(PetscFree(nprocs));
12123677ff5aSBarry Smith 
12133677ff5aSBarry Smith   /* pack messages to send back to local owners */
121430dcb7c9SBarry Smith   starts[0] = 0;
121530dcb7c9SBarry Smith   for (i = 1; i < ng; i++) {
121630dcb7c9SBarry Smith     if (nownedsenders[i - 1] > 1) starts[i] = starts[i - 1] + nownedsenders[i - 1];
121730dcb7c9SBarry Smith     else starts[i] = starts[i - 1];
121830dcb7c9SBarry Smith   }
121930dcb7c9SBarry Smith   nsends2 = nrecvs;
12209566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nsends2 + 1, &nprocs)); /* length of each message */
122130dcb7c9SBarry Smith   for (i = 0; i < nrecvs; i++) {
122230dcb7c9SBarry Smith     nprocs[i] = 1;
122330dcb7c9SBarry Smith     for (j = 0; j < len[i]; j++) {
122430dcb7c9SBarry Smith       node = recvs[2 * i * nmax + 2 * j] - rstart;
1225f6e5521dSKarl Rupp       if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node];
122630dcb7c9SBarry Smith     }
122730dcb7c9SBarry Smith   }
1228f6e5521dSKarl Rupp   nt = 0;
1229f6e5521dSKarl Rupp   for (i = 0; i < nsends2; i++) nt += nprocs[i];
1230f6e5521dSKarl Rupp 
12319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nt + 1, &sends2));
12329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nsends2 + 1, &starts2));
1233f6e5521dSKarl Rupp 
1234f6e5521dSKarl Rupp   starts2[0] = 0;
1235f6e5521dSKarl Rupp   for (i = 1; i < nsends2; i++) starts2[i] = starts2[i - 1] + nprocs[i - 1];
123630dcb7c9SBarry Smith   /*
123730dcb7c9SBarry Smith      Each message is 1 + nprocs[i] long, and consists of
123830dcb7c9SBarry Smith        (0) the number of nodes being sent back
123930dcb7c9SBarry Smith        (1) the local node number,
124030dcb7c9SBarry Smith        (2) the number of processors sharing it,
124130dcb7c9SBarry Smith        (3) the processors sharing it
124230dcb7c9SBarry Smith   */
124330dcb7c9SBarry Smith   for (i = 0; i < nsends2; i++) {
124430dcb7c9SBarry Smith     cnt                = 1;
124530dcb7c9SBarry Smith     sends2[starts2[i]] = 0;
124630dcb7c9SBarry Smith     for (j = 0; j < len[i]; j++) {
124730dcb7c9SBarry Smith       node = recvs[2 * i * nmax + 2 * j] - rstart;
124830dcb7c9SBarry Smith       if (nownedsenders[node] > 1) {
124930dcb7c9SBarry Smith         sends2[starts2[i]]++;
125030dcb7c9SBarry Smith         sends2[starts2[i] + cnt++] = recvs[2 * i * nmax + 2 * j + 1];
125130dcb7c9SBarry Smith         sends2[starts2[i] + cnt++] = nownedsenders[node];
12529566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(&sends2[starts2[i] + cnt], &ownedsenders[starts[node]], nownedsenders[node]));
125330dcb7c9SBarry Smith         cnt += nownedsenders[node];
125430dcb7c9SBarry Smith       }
125530dcb7c9SBarry Smith     }
125630dcb7c9SBarry Smith   }
125730dcb7c9SBarry Smith 
125830dcb7c9SBarry Smith   /* receive the message lengths */
125930dcb7c9SBarry Smith   nrecvs2 = nsends;
12609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs2 + 1, &lens2));
12619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs2 + 1, &starts3));
12629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs2 + 1, &recv_waits));
126348a46eb9SPierre Jolivet   for (i = 0; i < nrecvs2; i++) PetscCallMPI(MPI_Irecv(&lens2[i], 1, MPIU_INT, dest[i], tag2, comm, recv_waits + i));
1264d44834fbSBarry Smith 
12658a8e0b3aSBarry Smith   /* send the message lengths */
126648a46eb9SPierre Jolivet   for (i = 0; i < nsends2; i++) PetscCallMPI(MPI_Send(&nprocs[i], 1, MPIU_INT, source[i], tag2, comm));
12678a8e0b3aSBarry Smith 
1268d44834fbSBarry Smith   /* wait on receives of lens */
12690c468ba9SBarry Smith   if (nrecvs2) {
12709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrecvs2, &recv_statuses));
12719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(nrecvs2, recv_waits, recv_statuses));
12729566063dSJacob Faibussowitsch     PetscCall(PetscFree(recv_statuses));
12730c468ba9SBarry Smith   }
12749566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_waits));
1275d44834fbSBarry Smith 
127630dcb7c9SBarry Smith   starts3[0] = 0;
1277d44834fbSBarry Smith   nt         = 0;
127830dcb7c9SBarry Smith   for (i = 0; i < nrecvs2 - 1; i++) {
127930dcb7c9SBarry Smith     starts3[i + 1] = starts3[i] + lens2[i];
1280d44834fbSBarry Smith     nt += lens2[i];
128130dcb7c9SBarry Smith   }
128276466f69SStefano Zampini   if (nrecvs2) nt += lens2[nrecvs2 - 1];
1283d44834fbSBarry Smith 
12849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nt + 1, &recvs2));
12859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs2 + 1, &recv_waits));
128648a46eb9SPierre Jolivet   for (i = 0; i < nrecvs2; i++) PetscCallMPI(MPI_Irecv(recvs2 + starts3[i], lens2[i], MPIU_INT, dest[i], tag3, comm, recv_waits + i));
128730dcb7c9SBarry Smith 
128830dcb7c9SBarry Smith   /* send the messages */
12899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nsends2 + 1, &send_waits));
129048a46eb9SPierre Jolivet   for (i = 0; i < nsends2; i++) PetscCallMPI(MPI_Isend(sends2 + starts2[i], nprocs[i], MPIU_INT, source[i], tag3, comm, send_waits + i));
129130dcb7c9SBarry Smith 
129230dcb7c9SBarry Smith   /* wait on receives */
12930c468ba9SBarry Smith   if (nrecvs2) {
12949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrecvs2, &recv_statuses));
12959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(nrecvs2, recv_waits, recv_statuses));
12969566063dSJacob Faibussowitsch     PetscCall(PetscFree(recv_statuses));
12970c468ba9SBarry Smith   }
12989566063dSJacob Faibussowitsch   PetscCall(PetscFree(recv_waits));
12999566063dSJacob Faibussowitsch   PetscCall(PetscFree(nprocs));
130030dcb7c9SBarry Smith 
130107b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
130230dcb7c9SBarry Smith     cnt = 0;
130330dcb7c9SBarry Smith     for (i = 0; i < nrecvs2; i++) {
130430dcb7c9SBarry Smith       nt = recvs2[cnt++];
130530dcb7c9SBarry Smith       for (j = 0; j < nt; j++) {
13069566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "[%d] local node %" PetscInt_FMT " number of subdomains %" PetscInt_FMT ": ", rank, recvs2[cnt], recvs2[cnt + 1]));
130748a46eb9SPierre Jolivet         for (k = 0; k < recvs2[cnt + 1]; k++) PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", recvs2[cnt + 2 + k]));
130830dcb7c9SBarry Smith         cnt += 2 + recvs2[cnt + 1];
13099566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
131030dcb7c9SBarry Smith       }
131130dcb7c9SBarry Smith     }
13129566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
131307b52d57SBarry Smith   } /* -----------------------------------  */
131430dcb7c9SBarry Smith 
131530dcb7c9SBarry Smith   /* count number subdomains for each local node */
13169566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &nprocs));
131730dcb7c9SBarry Smith   cnt = 0;
131830dcb7c9SBarry Smith   for (i = 0; i < nrecvs2; i++) {
131930dcb7c9SBarry Smith     nt = recvs2[cnt++];
132030dcb7c9SBarry Smith     for (j = 0; j < nt; j++) {
1321f6e5521dSKarl Rupp       for (k = 0; k < recvs2[cnt + 1]; k++) nprocs[recvs2[cnt + 2 + k]]++;
132230dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt + 1];
132330dcb7c9SBarry Smith     }
132430dcb7c9SBarry Smith   }
13259371c9d4SSatish Balay   nt = 0;
13269371c9d4SSatish Balay   for (i = 0; i < size; i++) nt += (nprocs[i] > 0);
132730dcb7c9SBarry Smith   *nproc = nt;
13289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nt + 1, procs));
13299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nt + 1, numprocs));
13309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nt + 1, indices));
13310298fd71SBarry Smith   for (i = 0; i < nt + 1; i++) (*indices)[i] = NULL;
13329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &bprocs));
133330dcb7c9SBarry Smith   cnt = 0;
133430dcb7c9SBarry Smith   for (i = 0; i < size; i++) {
133530dcb7c9SBarry Smith     if (nprocs[i] > 0) {
133630dcb7c9SBarry Smith       bprocs[i]        = cnt;
133730dcb7c9SBarry Smith       (*procs)[cnt]    = i;
133830dcb7c9SBarry Smith       (*numprocs)[cnt] = nprocs[i];
13399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nprocs[i], &(*indices)[cnt]));
134030dcb7c9SBarry Smith       cnt++;
134130dcb7c9SBarry Smith     }
134230dcb7c9SBarry Smith   }
134330dcb7c9SBarry Smith 
134430dcb7c9SBarry Smith   /* make the list of subdomains for each nontrivial local node */
13459566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(*numprocs, nt));
134630dcb7c9SBarry Smith   cnt = 0;
134730dcb7c9SBarry Smith   for (i = 0; i < nrecvs2; i++) {
134830dcb7c9SBarry Smith     nt = recvs2[cnt++];
134930dcb7c9SBarry Smith     for (j = 0; j < nt; j++) {
1350f6e5521dSKarl Rupp       for (k = 0; k < recvs2[cnt + 1]; k++) (*indices)[bprocs[recvs2[cnt + 2 + k]]][(*numprocs)[bprocs[recvs2[cnt + 2 + k]]]++] = recvs2[cnt];
135130dcb7c9SBarry Smith       cnt += 2 + recvs2[cnt + 1];
135230dcb7c9SBarry Smith     }
135330dcb7c9SBarry Smith   }
13549566063dSJacob Faibussowitsch   PetscCall(PetscFree(bprocs));
13559566063dSJacob Faibussowitsch   PetscCall(PetscFree(recvs2));
135630dcb7c9SBarry Smith 
135707b52d57SBarry Smith   /* sort the node indexing by their global numbers */
135807b52d57SBarry Smith   nt = *nproc;
135907b52d57SBarry Smith   for (i = 0; i < nt; i++) {
13609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*numprocs)[i], &tmp));
1361f6e5521dSKarl Rupp     for (j = 0; j < (*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]];
13629566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithArray((*numprocs)[i], tmp, (*indices)[i]));
13639566063dSJacob Faibussowitsch     PetscCall(PetscFree(tmp));
136407b52d57SBarry Smith   }
136507b52d57SBarry Smith 
136607b52d57SBarry Smith   if (debug) { /* -----------------------------------  */
136730dcb7c9SBarry Smith     nt = *nproc;
136830dcb7c9SBarry Smith     for (i = 0; i < nt; i++) {
13699566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] subdomain %" PetscInt_FMT " number of indices %" PetscInt_FMT ": ", rank, (*procs)[i], (*numprocs)[i]));
137048a46eb9SPierre Jolivet       for (j = 0; j < (*numprocs)[i]; j++) PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", (*indices)[i][j]));
13719566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
137230dcb7c9SBarry Smith     }
13739566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
137407b52d57SBarry Smith   } /* -----------------------------------  */
137530dcb7c9SBarry Smith 
137630dcb7c9SBarry Smith   /* wait on sends */
137730dcb7c9SBarry Smith   if (nsends2) {
13789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nsends2, &send_status));
13799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Waitall(nsends2, send_waits, send_status));
13809566063dSJacob Faibussowitsch     PetscCall(PetscFree(send_status));
138130dcb7c9SBarry Smith   }
138230dcb7c9SBarry Smith 
13839566063dSJacob Faibussowitsch   PetscCall(PetscFree(starts3));
13849566063dSJacob Faibussowitsch   PetscCall(PetscFree(dest));
13859566063dSJacob Faibussowitsch   PetscCall(PetscFree(send_waits));
13863677ff5aSBarry Smith 
13879566063dSJacob Faibussowitsch   PetscCall(PetscFree(nownedsenders));
13889566063dSJacob Faibussowitsch   PetscCall(PetscFree(ownedsenders));
13899566063dSJacob Faibussowitsch   PetscCall(PetscFree(starts));
13909566063dSJacob Faibussowitsch   PetscCall(PetscFree(starts2));
13919566063dSJacob Faibussowitsch   PetscCall(PetscFree(lens2));
139289d82c54SBarry Smith 
13939566063dSJacob Faibussowitsch   PetscCall(PetscFree(source));
13949566063dSJacob Faibussowitsch   PetscCall(PetscFree(len));
13959566063dSJacob Faibussowitsch   PetscCall(PetscFree(recvs));
13969566063dSJacob Faibussowitsch   PetscCall(PetscFree(nprocs));
13979566063dSJacob Faibussowitsch   PetscCall(PetscFree(sends2));
139824cf384cSBarry Smith 
139924cf384cSBarry Smith   /* put the information about myself as the first entry in the list */
140024cf384cSBarry Smith   first_procs    = (*procs)[0];
140124cf384cSBarry Smith   first_numprocs = (*numprocs)[0];
140224cf384cSBarry Smith   first_indices  = (*indices)[0];
140324cf384cSBarry Smith   for (i = 0; i < *nproc; i++) {
140424cf384cSBarry Smith     if ((*procs)[i] == rank) {
140524cf384cSBarry Smith       (*procs)[0]    = (*procs)[i];
140624cf384cSBarry Smith       (*numprocs)[0] = (*numprocs)[i];
140724cf384cSBarry Smith       (*indices)[0]  = (*indices)[i];
140824cf384cSBarry Smith       (*procs)[i]    = first_procs;
140924cf384cSBarry Smith       (*numprocs)[i] = first_numprocs;
141024cf384cSBarry Smith       (*indices)[i]  = first_indices;
141124cf384cSBarry Smith       break;
141224cf384cSBarry Smith     }
141324cf384cSBarry Smith   }
1414268a049cSStefano Zampini 
1415268a049cSStefano Zampini   /* save info for reuse */
1416268a049cSStefano Zampini   mapping->info_nproc    = *nproc;
1417268a049cSStefano Zampini   mapping->info_procs    = *procs;
1418268a049cSStefano Zampini   mapping->info_numprocs = *numprocs;
1419268a049cSStefano Zampini   mapping->info_indices  = *indices;
1420268a049cSStefano Zampini   mapping->info_cached   = PETSC_TRUE;
14213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
142289d82c54SBarry Smith }
142389d82c54SBarry Smith 
14246a818285SBarry Smith /*@C
1425cab54364SBarry Smith   ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockInfo()`
14266a818285SBarry Smith 
1427c3339decSBarry Smith   Collective
14286a818285SBarry Smith 
1429f899ff85SJose E. Roman   Input Parameter:
14306a818285SBarry Smith . mapping - the mapping from local to global indexing
14316a818285SBarry Smith 
1432d8d19677SJose E. Roman   Output Parameters:
14336a818285SBarry Smith + nproc    - number of processors that are connected to this one
143438b5cf2dSJacob Faibussowitsch . procs    - neighboring processors
143538b5cf2dSJacob Faibussowitsch . numprocs - number of indices for each processor
14366a818285SBarry Smith - indices  - indices of local nodes shared with neighbor (sorted by global numbering)
14376a818285SBarry Smith 
14386a818285SBarry Smith   Level: advanced
14396a818285SBarry Smith 
1440cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1441db781477SPatrick Sanan           `ISLocalToGlobalMappingGetInfo()`
14426a818285SBarry Smith @*/
1443d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1444d71ae5a4SJacob Faibussowitsch {
14456a818285SBarry Smith   PetscFunctionBegin;
1446cbc1caf0SMatthew G. Knepley   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1447268a049cSStefano Zampini   if (mapping->info_free) {
14489566063dSJacob Faibussowitsch     PetscCall(PetscFree(*numprocs));
14496a818285SBarry Smith     if (*indices) {
1450268a049cSStefano Zampini       PetscInt i;
1451268a049cSStefano Zampini 
14529566063dSJacob Faibussowitsch       PetscCall(PetscFree((*indices)[0]));
145348a46eb9SPierre Jolivet       for (i = 1; i < *nproc; i++) PetscCall(PetscFree((*indices)[i]));
14549566063dSJacob Faibussowitsch       PetscCall(PetscFree(*indices));
14556a818285SBarry Smith     }
1456268a049cSStefano Zampini   }
1457268a049cSStefano Zampini   *nproc    = 0;
1458268a049cSStefano Zampini   *procs    = NULL;
1459268a049cSStefano Zampini   *numprocs = NULL;
1460268a049cSStefano Zampini   *indices  = NULL;
14613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14626a818285SBarry Smith }
14636a818285SBarry Smith 
14646a818285SBarry Smith /*@C
14656a818285SBarry Smith   ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and
14666a818285SBarry Smith   each index shared by more than one processor
14676a818285SBarry Smith 
1468c3339decSBarry Smith   Collective
14696a818285SBarry Smith 
1470f899ff85SJose E. Roman   Input Parameter:
14716a818285SBarry Smith . mapping - the mapping from local to global indexing
14726a818285SBarry Smith 
1473d8d19677SJose E. Roman   Output Parameters:
14746a818285SBarry Smith + nproc    - number of processors that are connected to this one
147538b5cf2dSJacob Faibussowitsch . procs    - neighboring processors
147638b5cf2dSJacob Faibussowitsch . numprocs - number of indices for each subdomain (processor)
14776a818285SBarry Smith - indices  - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering)
14786a818285SBarry Smith 
14796a818285SBarry Smith   Level: advanced
14806a818285SBarry Smith 
1481cab54364SBarry Smith   Note:
1482cab54364SBarry Smith   The user needs to call `ISLocalToGlobalMappingRestoreInfo()` when the data is no longer needed.
14831bd0b88eSStefano Zampini 
148438b5cf2dSJacob Faibussowitsch   Fortran Notes:
1485*e33f79d8SJacob Faibussowitsch   There is no `ISLocalToGlobalMappingRestoreInfo()` in Fortran. You must make sure that
1486*e33f79d8SJacob Faibussowitsch   `procs`[], `numprocs`[] and `indices`[][] are large enough arrays, either by allocating them
1487*e33f79d8SJacob Faibussowitsch   dynamically or defining static ones large enough.
1488*e33f79d8SJacob Faibussowitsch 
1489cab54364SBarry Smith .vb
14906a818285SBarry Smith   PetscInt indices[nproc][numprocmax],ierr)
1491cab54364SBarry Smith   ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by
1492cab54364SBarry Smith   ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc],
1493cab54364SBarry Smith .ve
1494cab54364SBarry Smith 
1495cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1496db781477SPatrick Sanan           `ISLocalToGlobalMappingRestoreInfo()`
14976a818285SBarry Smith @*/
1498d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1499d71ae5a4SJacob Faibussowitsch {
15008a1f772fSStefano Zampini   PetscInt **bindices = NULL, *bnumprocs = NULL, bs, i, j, k;
15016a818285SBarry Smith 
15026a818285SBarry Smith   PetscFunctionBegin;
15036a818285SBarry Smith   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
15048a1f772fSStefano Zampini   bs = mapping->bs;
15059566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockInfo(mapping, nproc, procs, &bnumprocs, &bindices));
1506268a049cSStefano Zampini   if (bs > 1) { /* we need to expand the cached info */
15079566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(*nproc, &*indices));
15089566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(*nproc, &*numprocs));
15096a818285SBarry Smith     for (i = 0; i < *nproc; i++) {
15109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(bs * bnumprocs[i], &(*indices)[i]));
1511268a049cSStefano Zampini       for (j = 0; j < bnumprocs[i]; j++) {
1512ad540459SPierre Jolivet         for (k = 0; k < bs; k++) (*indices)[i][j * bs + k] = bs * bindices[i][j] + k;
15136a818285SBarry Smith       }
1514268a049cSStefano Zampini       (*numprocs)[i] = bnumprocs[i] * bs;
15156a818285SBarry Smith     }
1516268a049cSStefano Zampini     mapping->info_free = PETSC_TRUE;
1517268a049cSStefano Zampini   } else {
1518268a049cSStefano Zampini     *numprocs = bnumprocs;
1519268a049cSStefano Zampini     *indices  = bindices;
15206a818285SBarry Smith   }
15213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15226a818285SBarry Smith }
15236a818285SBarry Smith 
152407b52d57SBarry Smith /*@C
1525cab54364SBarry Smith   ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetInfo()`
152689d82c54SBarry Smith 
1527c3339decSBarry Smith   Collective
152807b52d57SBarry Smith 
1529f899ff85SJose E. Roman   Input Parameter:
153007b52d57SBarry Smith . mapping - the mapping from local to global indexing
153107b52d57SBarry Smith 
1532d8d19677SJose E. Roman   Output Parameters:
153307b52d57SBarry Smith + nproc    - number of processors that are connected to this one
153438b5cf2dSJacob Faibussowitsch . procs    - neighboring processors
153538b5cf2dSJacob Faibussowitsch . numprocs - number of indices for each processor
153607b52d57SBarry Smith - indices  - indices of local nodes shared with neighbor (sorted by global numbering)
153707b52d57SBarry Smith 
153807b52d57SBarry Smith   Level: advanced
153907b52d57SBarry Smith 
1540cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1541db781477SPatrick Sanan           `ISLocalToGlobalMappingGetInfo()`
154207b52d57SBarry Smith @*/
1543d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1544d71ae5a4SJacob Faibussowitsch {
154507b52d57SBarry Smith   PetscFunctionBegin;
15469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockInfo(mapping, nproc, procs, numprocs, indices));
15473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
154807b52d57SBarry Smith }
154986994e45SJed Brown 
155086994e45SJed Brown /*@C
1551cab54364SBarry Smith   ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information for each MPI rank
15521bd0b88eSStefano Zampini 
1553c3339decSBarry Smith   Collective
15541bd0b88eSStefano Zampini 
1555f899ff85SJose E. Roman   Input Parameter:
15561bd0b88eSStefano Zampini . mapping - the mapping from local to global indexing
15571bd0b88eSStefano Zampini 
1558d8d19677SJose E. Roman   Output Parameters:
1559cab54364SBarry Smith + nnodes  - number of local nodes (same `ISLocalToGlobalMappingGetSize()`)
15601bd0b88eSStefano Zampini . count   - number of neighboring processors per node
15611bd0b88eSStefano Zampini - indices - indices of processes sharing the node (sorted)
15621bd0b88eSStefano Zampini 
15631bd0b88eSStefano Zampini   Level: advanced
15641bd0b88eSStefano Zampini 
1565cab54364SBarry Smith   Note:
1566cab54364SBarry Smith   The user needs to call `ISLocalToGlobalMappingRestoreInfo()` when the data is no longer needed.
15671bd0b88eSStefano Zampini 
1568cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1569db781477SPatrick Sanan           `ISLocalToGlobalMappingGetInfo()`, `ISLocalToGlobalMappingRestoreNodeInfo()`
15701bd0b88eSStefano Zampini @*/
1571d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *nnodes, PetscInt *count[], PetscInt **indices[])
1572d71ae5a4SJacob Faibussowitsch {
15731bd0b88eSStefano Zampini   PetscInt n;
15741bd0b88eSStefano Zampini 
15751bd0b88eSStefano Zampini   PetscFunctionBegin;
15761bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
15779566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(mapping, &n));
15781bd0b88eSStefano Zampini   if (!mapping->info_nodec) {
15791bd0b88eSStefano Zampini     PetscInt i, m, n_neigh, *neigh, *n_shared, **shared;
15801bd0b88eSStefano Zampini 
15819566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(n + 1, &mapping->info_nodec, n, &mapping->info_nodei));
15829566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetInfo(mapping, &n_neigh, &neigh, &n_shared, &shared));
1583ad540459SPierre Jolivet     for (i = 0; i < n; i++) mapping->info_nodec[i] = 1;
1584071fcb05SBarry Smith     m                      = n;
1585071fcb05SBarry Smith     mapping->info_nodec[n] = 0;
15861bd0b88eSStefano Zampini     for (i = 1; i < n_neigh; i++) {
15871bd0b88eSStefano Zampini       PetscInt j;
15881bd0b88eSStefano Zampini 
15891bd0b88eSStefano Zampini       m += n_shared[i];
15901bd0b88eSStefano Zampini       for (j = 0; j < n_shared[i]; j++) mapping->info_nodec[shared[i][j]] += 1;
15911bd0b88eSStefano Zampini     }
15929566063dSJacob Faibussowitsch     if (n) PetscCall(PetscMalloc1(m, &mapping->info_nodei[0]));
15931bd0b88eSStefano Zampini     for (i = 1; i < n; i++) mapping->info_nodei[i] = mapping->info_nodei[i - 1] + mapping->info_nodec[i - 1];
15949566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(mapping->info_nodec, n));
15959371c9d4SSatish Balay     for (i = 0; i < n; i++) {
15969371c9d4SSatish Balay       mapping->info_nodec[i]    = 1;
15979371c9d4SSatish Balay       mapping->info_nodei[i][0] = neigh[0];
15989371c9d4SSatish Balay     }
15991bd0b88eSStefano Zampini     for (i = 1; i < n_neigh; i++) {
16001bd0b88eSStefano Zampini       PetscInt j;
16011bd0b88eSStefano Zampini 
16021bd0b88eSStefano Zampini       for (j = 0; j < n_shared[i]; j++) {
16031bd0b88eSStefano Zampini         PetscInt k = shared[i][j];
16041bd0b88eSStefano Zampini 
16051bd0b88eSStefano Zampini         mapping->info_nodei[k][mapping->info_nodec[k]] = neigh[i];
16061bd0b88eSStefano Zampini         mapping->info_nodec[k] += 1;
16071bd0b88eSStefano Zampini       }
16081bd0b88eSStefano Zampini     }
16099566063dSJacob Faibussowitsch     for (i = 0; i < n; i++) PetscCall(PetscSortRemoveDupsInt(&mapping->info_nodec[i], mapping->info_nodei[i]));
16109566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping, &n_neigh, &neigh, &n_shared, &shared));
16111bd0b88eSStefano Zampini   }
16121bd0b88eSStefano Zampini   if (nnodes) *nnodes = n;
16131bd0b88eSStefano Zampini   if (count) *count = mapping->info_nodec;
16141bd0b88eSStefano Zampini   if (indices) *indices = mapping->info_nodei;
16153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16161bd0b88eSStefano Zampini }
16171bd0b88eSStefano Zampini 
16181bd0b88eSStefano Zampini /*@C
1619cab54364SBarry Smith   ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetNodeInfo()`
16201bd0b88eSStefano Zampini 
1621c3339decSBarry Smith   Collective
16221bd0b88eSStefano Zampini 
1623f899ff85SJose E. Roman   Input Parameter:
16241bd0b88eSStefano Zampini . mapping - the mapping from local to global indexing
16251bd0b88eSStefano Zampini 
1626d8d19677SJose E. Roman   Output Parameters:
16271bd0b88eSStefano Zampini + nnodes  - number of local nodes
16281bd0b88eSStefano Zampini . count   - number of neighboring processors per node
16291bd0b88eSStefano Zampini - indices - indices of processes sharing the node (sorted)
16301bd0b88eSStefano Zampini 
16311bd0b88eSStefano Zampini   Level: advanced
16321bd0b88eSStefano Zampini 
1633cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1634db781477SPatrick Sanan           `ISLocalToGlobalMappingGetInfo()`
16351bd0b88eSStefano Zampini @*/
1636d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *nnodes, PetscInt *count[], PetscInt **indices[])
1637d71ae5a4SJacob Faibussowitsch {
16381bd0b88eSStefano Zampini   PetscFunctionBegin;
16391bd0b88eSStefano Zampini   PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
16401bd0b88eSStefano Zampini   if (nnodes) *nnodes = 0;
16411bd0b88eSStefano Zampini   if (count) *count = NULL;
16421bd0b88eSStefano Zampini   if (indices) *indices = NULL;
16433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16441bd0b88eSStefano Zampini }
16451bd0b88eSStefano Zampini 
16466ce40d10SBarry Smith /*MC
16476ce40d10SBarry Smith     ISLocalToGlobalMappingGetIndicesF90 - Get global indices for every local point that is mapped
16486ce40d10SBarry Smith 
16496ce40d10SBarry Smith     Synopsis:
16506ce40d10SBarry Smith     ISLocalToGlobalMappingGetIndicesF90(ISLocalToGlobalMapping ltog, PetscInt, pointer :: array(:)}, integer ierr)
16516ce40d10SBarry Smith 
16526ce40d10SBarry Smith     Not Collective
16536ce40d10SBarry Smith 
16546ce40d10SBarry Smith     Input Parameter:
16556ce40d10SBarry Smith .   A - the matrix
16566ce40d10SBarry Smith 
16572fe279fdSBarry Smith     Output Parameter:
16586ce40d10SBarry Smith .   array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
16596ce40d10SBarry Smith 
16606ce40d10SBarry Smith     Level: advanced
16616ce40d10SBarry Smith 
16626ce40d10SBarry Smith     Note:
16636ce40d10SBarry Smith     Use  `ISLocalToGlobalMappingGetIndicesF90()` when you no longer need access to the data
16646ce40d10SBarry Smith 
166520662ed9SBarry Smith .seealso: [](sec_fortranarrays), [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingGetIndices()`, `ISLocalToGlobalMappingRestoreIndices()`,
166620662ed9SBarry Smith           `ISLocalToGlobalMappingRestoreIndicesF90()`
16676ce40d10SBarry Smith M*/
16686ce40d10SBarry Smith 
16696ce40d10SBarry Smith /*MC
16706ce40d10SBarry Smith     ISLocalToGlobalMappingRestoreIndicesF90 - restores the global indices for every local point that is mapped obtained with `ISLocalToGlobalMappingGetIndicesF90()`
16716ce40d10SBarry Smith 
16726ce40d10SBarry Smith     Synopsis:
16736ce40d10SBarry Smith     ISLocalToGlobalMappingRestoreIndicesF90(ISLocalToGlobalMapping ltog, PetscInt, pointer :: array(:)}, integer ierr)
16746ce40d10SBarry Smith 
16756ce40d10SBarry Smith     Not Collective
16766ce40d10SBarry Smith 
16776ce40d10SBarry Smith     Input Parameters:
16786ce40d10SBarry Smith +   A - the matrix
16796ce40d10SBarry Smith -   array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
16806ce40d10SBarry Smith 
16816ce40d10SBarry Smith     Level: advanced
16826ce40d10SBarry Smith 
168320662ed9SBarry Smith .seealso: [](sec_fortranarrays), [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingGetIndices()`, `ISLocalToGlobalMappingRestoreIndices()`,
168420662ed9SBarry Smith           `ISLocalToGlobalMappingGetIndicesF90()`
16856ce40d10SBarry Smith M*/
16866ce40d10SBarry Smith 
16871bd0b88eSStefano Zampini /*@C
1688107e9a97SBarry Smith   ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
168986994e45SJed Brown 
169086994e45SJed Brown   Not Collective
169186994e45SJed Brown 
16924165533cSJose E. Roman   Input Parameter:
169386994e45SJed Brown . ltog - local to global mapping
169486994e45SJed Brown 
16954165533cSJose E. Roman   Output Parameter:
1696cab54364SBarry Smith . array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
169786994e45SJed Brown 
169886994e45SJed Brown   Level: advanced
169986994e45SJed Brown 
1700cab54364SBarry Smith   Note:
1701cab54364SBarry Smith   `ISLocalToGlobalMappingGetSize()` returns the length the this array
1702107e9a97SBarry Smith 
170320662ed9SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreIndices()`,
170420662ed9SBarry Smith           `ISLocalToGlobalMappingGetBlockIndices()`, `ISLocalToGlobalMappingRestoreBlockIndices()`
170586994e45SJed Brown @*/
1706d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1707d71ae5a4SJacob Faibussowitsch {
170886994e45SJed Brown   PetscFunctionBegin;
170986994e45SJed Brown   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
171086994e45SJed Brown   PetscValidPointer(array, 2);
171145b6f7e9SBarry Smith   if (ltog->bs == 1) {
171286994e45SJed Brown     *array = ltog->indices;
171345b6f7e9SBarry Smith   } else {
171445b6f7e9SBarry Smith     PetscInt       *jj, k, i, j, n = ltog->n, bs = ltog->bs;
171545b6f7e9SBarry Smith     const PetscInt *ii;
171645b6f7e9SBarry Smith 
17179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs * n, &jj));
171845b6f7e9SBarry Smith     *array = jj;
171945b6f7e9SBarry Smith     k      = 0;
172045b6f7e9SBarry Smith     ii     = ltog->indices;
172145b6f7e9SBarry Smith     for (i = 0; i < n; i++)
17229371c9d4SSatish Balay       for (j = 0; j < bs; j++) jj[k++] = bs * ii[i] + j;
172345b6f7e9SBarry Smith   }
17243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
172586994e45SJed Brown }
172686994e45SJed Brown 
172786994e45SJed Brown /*@C
1728cab54364SBarry Smith   ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with `ISLocalToGlobalMappingGetIndices()`
172986994e45SJed Brown 
173086994e45SJed Brown   Not Collective
173186994e45SJed Brown 
17324165533cSJose E. Roman   Input Parameters:
173386994e45SJed Brown + ltog  - local to global mapping
173486994e45SJed Brown - array - array of indices
173586994e45SJed Brown 
173686994e45SJed Brown   Level: advanced
173786994e45SJed Brown 
1738cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()`
173986994e45SJed Brown @*/
1740d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1741d71ae5a4SJacob Faibussowitsch {
174286994e45SJed Brown   PetscFunctionBegin;
174386994e45SJed Brown   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
174486994e45SJed Brown   PetscValidPointer(array, 2);
1745c9cc58a2SBarry Smith   PetscCheck(ltog->bs != 1 || *array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer");
174645b6f7e9SBarry Smith 
174748a46eb9SPierre Jolivet   if (ltog->bs > 1) PetscCall(PetscFree(*(void **)array));
17483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
174945b6f7e9SBarry Smith }
175045b6f7e9SBarry Smith 
175145b6f7e9SBarry Smith /*@C
175245b6f7e9SBarry Smith   ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
175345b6f7e9SBarry Smith 
175445b6f7e9SBarry Smith   Not Collective
175545b6f7e9SBarry Smith 
17564165533cSJose E. Roman   Input Parameter:
175745b6f7e9SBarry Smith . ltog - local to global mapping
175845b6f7e9SBarry Smith 
17594165533cSJose E. Roman   Output Parameter:
176045b6f7e9SBarry Smith . array - array of indices
176145b6f7e9SBarry Smith 
176245b6f7e9SBarry Smith   Level: advanced
176345b6f7e9SBarry Smith 
1764cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreBlockIndices()`
176545b6f7e9SBarry Smith @*/
1766d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1767d71ae5a4SJacob Faibussowitsch {
176845b6f7e9SBarry Smith   PetscFunctionBegin;
176945b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
177045b6f7e9SBarry Smith   PetscValidPointer(array, 2);
177145b6f7e9SBarry Smith   *array = ltog->indices;
17723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
177345b6f7e9SBarry Smith }
177445b6f7e9SBarry Smith 
177545b6f7e9SBarry Smith /*@C
1776cab54364SBarry Smith   ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with `ISLocalToGlobalMappingGetBlockIndices()`
177745b6f7e9SBarry Smith 
177845b6f7e9SBarry Smith   Not Collective
177945b6f7e9SBarry Smith 
17804165533cSJose E. Roman   Input Parameters:
178145b6f7e9SBarry Smith + ltog  - local to global mapping
178245b6f7e9SBarry Smith - array - array of indices
178345b6f7e9SBarry Smith 
178445b6f7e9SBarry Smith   Level: advanced
178545b6f7e9SBarry Smith 
1786cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()`
178745b6f7e9SBarry Smith @*/
1788d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1789d71ae5a4SJacob Faibussowitsch {
179045b6f7e9SBarry Smith   PetscFunctionBegin;
179145b6f7e9SBarry Smith   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
179245b6f7e9SBarry Smith   PetscValidPointer(array, 2);
179308401ef6SPierre Jolivet   PetscCheck(*array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer");
17940298fd71SBarry Smith   *array = NULL;
17953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
179686994e45SJed Brown }
1797f7efa3c7SJed Brown 
1798f7efa3c7SJed Brown /*@C
1799f7efa3c7SJed Brown   ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1800f7efa3c7SJed Brown 
1801f7efa3c7SJed Brown   Not Collective
1802f7efa3c7SJed Brown 
18034165533cSJose E. Roman   Input Parameters:
1804f7efa3c7SJed Brown + comm  - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1805f7efa3c7SJed Brown . n     - number of mappings to concatenate
1806f7efa3c7SJed Brown - ltogs - local to global mappings
1807f7efa3c7SJed Brown 
18084165533cSJose E. Roman   Output Parameter:
1809f7efa3c7SJed Brown . ltogcat - new mapping
1810f7efa3c7SJed Brown 
1811f7efa3c7SJed Brown   Level: advanced
1812f7efa3c7SJed Brown 
1813cab54364SBarry Smith   Note:
1814cab54364SBarry Smith   This currently always returns a mapping with block size of 1
1815cab54364SBarry Smith 
181638b5cf2dSJacob Faibussowitsch   Developer Notes:
1817cab54364SBarry Smith   If all the input mapping have the same block size we could easily handle that as a special case
1818cab54364SBarry Smith 
1819cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`
1820f7efa3c7SJed Brown @*/
1821d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm, PetscInt n, const ISLocalToGlobalMapping ltogs[], ISLocalToGlobalMapping *ltogcat)
1822d71ae5a4SJacob Faibussowitsch {
1823f7efa3c7SJed Brown   PetscInt i, cnt, m, *idx;
1824f7efa3c7SJed Brown 
1825f7efa3c7SJed Brown   PetscFunctionBegin;
182608401ef6SPierre Jolivet   PetscCheck(n >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Must have a non-negative number of mappings, given %" PetscInt_FMT, n);
1827f7efa3c7SJed Brown   if (n > 0) PetscValidPointer(ltogs, 3);
1828f7efa3c7SJed Brown   for (i = 0; i < n; i++) PetscValidHeaderSpecific(ltogs[i], IS_LTOGM_CLASSID, 3);
1829f7efa3c7SJed Brown   PetscValidPointer(ltogcat, 4);
1830f7efa3c7SJed Brown   for (cnt = 0, i = 0; i < n; i++) {
18319566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m));
1832f7efa3c7SJed Brown     cnt += m;
1833f7efa3c7SJed Brown   }
18349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(cnt, &idx));
1835f7efa3c7SJed Brown   for (cnt = 0, i = 0; i < n; i++) {
1836f7efa3c7SJed Brown     const PetscInt *subidx;
18379566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m));
18389566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(ltogs[i], &subidx));
18399566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&idx[cnt], subidx, m));
18409566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogs[i], &subidx));
1841f7efa3c7SJed Brown     cnt += m;
1842f7efa3c7SJed Brown   }
18439566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm, 1, cnt, idx, PETSC_OWN_POINTER, ltogcat));
18443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1845f7efa3c7SJed Brown }
184604a59952SBarry Smith 
1847413f72f0SBarry Smith /*MC
1848cab54364SBarry Smith       ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is
1849413f72f0SBarry Smith                                     used this is good for only small and moderate size problems.
1850413f72f0SBarry Smith 
185120662ed9SBarry Smith    Options Database Key:
1852a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type basic - select this method
1853413f72f0SBarry Smith 
1854413f72f0SBarry Smith    Level: beginner
1855413f72f0SBarry Smith 
1856cab54364SBarry Smith    Developer Note:
1857cab54364SBarry Smith    This stores all the mapping information on each MPI rank.
1858cab54364SBarry Smith 
1859cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGHASH`
1860413f72f0SBarry Smith M*/
1861d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)
1862d71ae5a4SJacob Faibussowitsch {
1863413f72f0SBarry Smith   PetscFunctionBegin;
1864413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Basic;
1865413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Basic;
1866413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic;
1867413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Basic;
18683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1869413f72f0SBarry Smith }
1870413f72f0SBarry Smith 
1871413f72f0SBarry Smith /*MC
1872cab54364SBarry Smith       ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is
1873ed56e8eaSBarry Smith                                     used this is good for large memory problems.
1874413f72f0SBarry Smith 
187520662ed9SBarry Smith    Options Database Key:
1876a2b725a8SWilliam Gropp .   -islocaltoglobalmapping_type hash - select this method
1877413f72f0SBarry Smith 
1878413f72f0SBarry Smith    Level: beginner
1879413f72f0SBarry Smith 
1880cab54364SBarry Smith    Note:
1881cab54364SBarry Smith     This is selected automatically for large problems if the user does not set the type.
1882cab54364SBarry Smith 
1883cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGBASIC`
1884413f72f0SBarry Smith M*/
1885d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)
1886d71ae5a4SJacob Faibussowitsch {
1887413f72f0SBarry Smith   PetscFunctionBegin;
1888413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapply      = ISGlobalToLocalMappingApply_Hash;
1889413f72f0SBarry Smith   ltog->ops->globaltolocalmappingsetup      = ISGlobalToLocalMappingSetUp_Hash;
1890413f72f0SBarry Smith   ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash;
1891413f72f0SBarry Smith   ltog->ops->destroy                        = ISLocalToGlobalMappingDestroy_Hash;
18923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1893413f72f0SBarry Smith }
1894413f72f0SBarry Smith 
1895413f72f0SBarry Smith /*@C
1896cab54364SBarry Smith   ISLocalToGlobalMappingRegister -  Registers a method for applying a global to local mapping with an `ISLocalToGlobalMapping`
1897413f72f0SBarry Smith 
1898413f72f0SBarry Smith   Not Collective
1899413f72f0SBarry Smith 
1900413f72f0SBarry Smith   Input Parameters:
1901413f72f0SBarry Smith + sname    - name of a new method
19022fe279fdSBarry Smith - function - routine to create method context
1903413f72f0SBarry Smith 
190438b5cf2dSJacob Faibussowitsch   Example Usage:
1905413f72f0SBarry Smith .vb
1906413f72f0SBarry Smith    ISLocalToGlobalMappingRegister("my_mapper", MyCreate);
1907413f72f0SBarry Smith .ve
1908413f72f0SBarry Smith 
1909ed56e8eaSBarry Smith   Then, your mapping can be chosen with the procedural interface via
1910413f72f0SBarry Smith $     ISLocalToGlobalMappingSetType(ltog, "my_mapper")
1911413f72f0SBarry Smith   or at runtime via the option
1912ed56e8eaSBarry Smith $     -islocaltoglobalmapping_type my_mapper
1913413f72f0SBarry Smith 
1914413f72f0SBarry Smith   Level: advanced
1915413f72f0SBarry Smith 
1916cab54364SBarry Smith   Note:
1917cab54364SBarry Smith   `ISLocalToGlobalMappingRegister()` may be called multiple times to add several user-defined mappings.
1918413f72f0SBarry Smith 
1919cab54364SBarry Smith .seealso: [](sec_scatter), `ISLocalToGlobalMappingRegisterAll()`, `ISLocalToGlobalMappingRegisterDestroy()`, `ISLOCALTOGLOBALMAPPINGBASIC`,
1920cab54364SBarry Smith           `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`
1921413f72f0SBarry Smith @*/
1922d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRegister(const char sname[], PetscErrorCode (*function)(ISLocalToGlobalMapping))
1923d71ae5a4SJacob Faibussowitsch {
1924413f72f0SBarry Smith   PetscFunctionBegin;
19259566063dSJacob Faibussowitsch   PetscCall(ISInitializePackage());
19269566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&ISLocalToGlobalMappingList, sname, function));
19273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1928413f72f0SBarry Smith }
1929413f72f0SBarry Smith 
1930413f72f0SBarry Smith /*@C
1931cab54364SBarry Smith   ISLocalToGlobalMappingSetType - Sets the implementation type `ISLocalToGlobalMapping` will use
1932413f72f0SBarry Smith 
1933c3339decSBarry Smith   Logically Collective
1934413f72f0SBarry Smith 
1935413f72f0SBarry Smith   Input Parameters:
1936cab54364SBarry Smith + ltog - the `ISLocalToGlobalMapping` object
1937413f72f0SBarry Smith - type - a known method
1938413f72f0SBarry Smith 
1939413f72f0SBarry Smith   Options Database Key:
1940cab54364SBarry Smith . -islocaltoglobalmapping_type  <method> - Sets the method; use -help for a list of available methods (for instance, basic or hash)
1941cab54364SBarry Smith 
1942cab54364SBarry Smith   Level: intermediate
1943413f72f0SBarry Smith 
1944413f72f0SBarry Smith   Notes:
194520662ed9SBarry Smith   See `ISLocalToGlobalMappingType` for available methods
1946413f72f0SBarry Smith 
1947cab54364SBarry Smith   Normally, it is best to use the `ISLocalToGlobalMappingSetFromOptions()` command and
1948cab54364SBarry Smith   then set the `ISLocalToGlobalMappingType` from the options database rather than by using
1949413f72f0SBarry Smith   this routine.
1950413f72f0SBarry Smith 
195138b5cf2dSJacob Faibussowitsch   Developer Notes:
1952cab54364SBarry Smith   `ISLocalToGlobalMappingRegister()` is used to add new types to `ISLocalToGlobalMappingList` from which they
1953cab54364SBarry Smith   are accessed by `ISLocalToGlobalMappingSetType()`.
1954413f72f0SBarry Smith 
195538b5cf2dSJacob Faibussowitsch .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingGetType()`
1956413f72f0SBarry Smith @*/
1957d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type)
1958d71ae5a4SJacob Faibussowitsch {
1959413f72f0SBarry Smith   PetscBool match;
19605f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(ISLocalToGlobalMapping) = NULL;
1961413f72f0SBarry Smith 
1962413f72f0SBarry Smith   PetscFunctionBegin;
1963413f72f0SBarry Smith   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1964a0d79125SStefano Zampini   if (type) PetscValidCharPointer(type, 2);
1965413f72f0SBarry Smith 
19669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)ltog, type, &match));
19673ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
1968413f72f0SBarry Smith 
1969a0d79125SStefano Zampini   /* L2G maps defer type setup at globaltolocal calls, allow passing NULL here */
1970a0d79125SStefano Zampini   if (type) {
19719566063dSJacob Faibussowitsch     PetscCall(PetscFunctionListFind(ISLocalToGlobalMappingList, type, &r));
1972a0d79125SStefano Zampini     PetscCheck(r, PetscObjectComm((PetscObject)ltog), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested ISLocalToGlobalMapping type %s", type);
1973a0d79125SStefano Zampini   }
1974413f72f0SBarry Smith   /* Destroy the previous private LTOG context */
1975dbbe0bcdSBarry Smith   PetscTryTypeMethod(ltog, destroy);
1976413f72f0SBarry Smith   ltog->ops->destroy = NULL;
1977dbbe0bcdSBarry Smith 
19789566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)ltog, type));
19799566063dSJacob Faibussowitsch   if (r) PetscCall((*r)(ltog));
19803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1981a0d79125SStefano Zampini }
1982a0d79125SStefano Zampini 
1983a0d79125SStefano Zampini /*@C
1984cab54364SBarry Smith   ISLocalToGlobalMappingGetType - Get the type of the `ISLocalToGlobalMapping`
1985a0d79125SStefano Zampini 
1986a0d79125SStefano Zampini   Not Collective
1987a0d79125SStefano Zampini 
1988a0d79125SStefano Zampini   Input Parameter:
1989cab54364SBarry Smith . ltog - the `ISLocalToGlobalMapping` object
1990a0d79125SStefano Zampini 
1991a0d79125SStefano Zampini   Output Parameter:
1992a0d79125SStefano Zampini . type - the type
1993a0d79125SStefano Zampini 
199449762cbcSSatish Balay   Level: intermediate
199549762cbcSSatish Balay 
199638b5cf2dSJacob Faibussowitsch .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`
1997a0d79125SStefano Zampini @*/
1998d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingGetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType *type)
1999d71ae5a4SJacob Faibussowitsch {
2000a0d79125SStefano Zampini   PetscFunctionBegin;
2001a0d79125SStefano Zampini   PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
2002a0d79125SStefano Zampini   PetscValidPointer(type, 2);
2003a0d79125SStefano Zampini   *type = ((PetscObject)ltog)->type_name;
20043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2005413f72f0SBarry Smith }
2006413f72f0SBarry Smith 
2007413f72f0SBarry Smith PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE;
2008413f72f0SBarry Smith 
2009413f72f0SBarry Smith /*@C
2010cab54364SBarry Smith   ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the `IS` package.
2011413f72f0SBarry Smith 
2012413f72f0SBarry Smith   Not Collective
2013413f72f0SBarry Smith 
2014413f72f0SBarry Smith   Level: advanced
2015413f72f0SBarry Smith 
2016cab54364SBarry Smith .seealso: [](sec_scatter), `ISRegister()`, `ISLocalToGlobalRegister()`
2017413f72f0SBarry Smith @*/
2018d71ae5a4SJacob Faibussowitsch PetscErrorCode ISLocalToGlobalMappingRegisterAll(void)
2019d71ae5a4SJacob Faibussowitsch {
2020413f72f0SBarry Smith   PetscFunctionBegin;
20213ba16761SJacob Faibussowitsch   if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
2022413f72f0SBarry Smith   ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE;
20239566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic));
20249566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash));
20253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2026413f72f0SBarry Smith }
2027