Actual source code: isltog.c
1: #include <petsc/private/isimpl.h>
2: #include <petsc/private/hashmapi.h>
3: #include <petscsf.h>
4: #include <petscviewer.h>
5: #include <petscbt.h>
7: PetscClassId IS_LTOGM_CLASSID;
8: static PetscErrorCode ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping);
10: typedef struct {
11: PetscInt *globals;
12: } ISLocalToGlobalMapping_Basic;
14: typedef struct {
15: PetscHMapI globalht;
16: } ISLocalToGlobalMapping_Hash;
18: /*@C
19: ISGetPointRange - Returns a description of the points in an `IS` suitable for traversal
21: Not Collective
23: Input Parameter:
24: . pointIS - The `IS` object
26: Output Parameters:
27: + pStart - The first index, see notes
28: . pEnd - One past the last index, see notes
29: - points - The indices, see notes
31: Level: intermediate
33: Notes:
34: If the `IS` contains contiguous indices in an `ISSTRIDE`, then the indices are contained in [pStart, pEnd) and points = `NULL`.
35: Otherwise, `pStart = 0`, `pEnd = numIndices`, and points is an array of the indices. This supports the following pattern
36: .vb
37: ISGetPointRange(is, &pStart, &pEnd, &points);
38: for (p = pStart; p < pEnd; ++p) {
39: const PetscInt point = points ? points[p] : p;
40: // use point
41: }
42: ISRestorePointRange(is, &pstart, &pEnd, &points);
43: .ve
44: Hence the same code can be written for `pointIS` being a `ISSTRIDE` or `ISGENERAL`
46: .seealso: [](sec_scatter), `IS`, `ISRestorePointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()`
47: @*/
48: PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
49: {
50: PetscInt numCells, step = 1;
51: PetscBool isStride;
53: PetscFunctionBeginHot;
54: *pStart = 0;
55: *points = NULL;
56: PetscCall(ISGetLocalSize(pointIS, &numCells));
57: PetscCall(PetscObjectTypeCompare((PetscObject)pointIS, ISSTRIDE, &isStride));
58: if (isStride) PetscCall(ISStrideGetInfo(pointIS, pStart, &step));
59: *pEnd = *pStart + numCells;
60: if (!isStride || step != 1) PetscCall(ISGetIndices(pointIS, points));
61: PetscFunctionReturn(PETSC_SUCCESS);
62: }
64: /*@C
65: ISRestorePointRange - Destroys the traversal description created with `ISGetPointRange()`
67: Not Collective
69: Input Parameters:
70: + pointIS - The `IS` object
71: . pStart - The first index, from `ISGetPointRange()`
72: . pEnd - One past the last index, from `ISGetPointRange()`
73: - points - The indices, from `ISGetPointRange()`
75: Level: intermediate
77: .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()`
78: @*/
79: PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points)
80: {
81: PetscInt step = 1;
82: PetscBool isStride;
84: PetscFunctionBeginHot;
85: PetscCall(PetscObjectTypeCompare((PetscObject)pointIS, ISSTRIDE, &isStride));
86: if (isStride) PetscCall(ISStrideGetInfo(pointIS, pStart, &step));
87: if (!isStride || step != 1) PetscCall(ISGetIndices(pointIS, points));
88: PetscFunctionReturn(PETSC_SUCCESS);
89: }
91: /*@C
92: ISGetPointSubrange - Configures the input `IS` to be a subrange for the traversal information given
94: Not Collective
96: Input Parameters:
97: + subpointIS - The `IS` object to be configured
98: . pStart - The first index of the subrange
99: . pEnd - One past the last index for the subrange
100: - points - The indices for the entire range, from `ISGetPointRange()`
102: Output Parameters:
103: . subpointIS - The `IS` object now configured to be a subrange
105: Level: intermediate
107: Note:
108: The input `IS` will now respond properly to calls to `ISGetPointRange()` and return the subrange.
110: .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISRestorePointRange()`, `ISGetIndices()`, `ISCreateStride()`
111: @*/
112: PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points)
113: {
114: PetscFunctionBeginHot;
115: if (points) {
116: PetscCall(ISSetType(subpointIS, ISGENERAL));
117: PetscCall(ISGeneralSetIndices(subpointIS, pEnd - pStart, &points[pStart], PETSC_USE_POINTER));
118: } else {
119: PetscCall(ISSetType(subpointIS, ISSTRIDE));
120: PetscCall(ISStrideSetStride(subpointIS, pEnd - pStart, pStart, 1));
121: }
122: PetscFunctionReturn(PETSC_SUCCESS);
123: }
125: /* -----------------------------------------------------------------------------------------*/
127: /*
128: Creates the global mapping information in the ISLocalToGlobalMapping structure
130: If the user has not selected how to handle the global to local mapping then use HASH for "large" problems
131: */
132: static PetscErrorCode ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping)
133: {
134: PetscInt i, *idx = mapping->indices, n = mapping->n, end, start;
136: PetscFunctionBegin;
137: if (mapping->data) PetscFunctionReturn(PETSC_SUCCESS);
138: end = 0;
139: start = PETSC_MAX_INT;
141: for (i = 0; i < n; i++) {
142: if (idx[i] < 0) continue;
143: if (idx[i] < start) start = idx[i];
144: if (idx[i] > end) end = idx[i];
145: }
146: if (start > end) {
147: start = 0;
148: end = -1;
149: }
150: mapping->globalstart = start;
151: mapping->globalend = end;
152: if (!((PetscObject)mapping)->type_name) {
153: if ((end - start) > PetscMax(4 * n, 1000000)) {
154: PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGHASH));
155: } else {
156: PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGBASIC));
157: }
158: }
159: PetscTryTypeMethod(mapping, globaltolocalmappingsetup);
160: PetscFunctionReturn(PETSC_SUCCESS);
161: }
163: static PetscErrorCode ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping)
164: {
165: PetscInt i, *idx = mapping->indices, n = mapping->n, end, start, *globals;
166: ISLocalToGlobalMapping_Basic *map;
168: PetscFunctionBegin;
169: start = mapping->globalstart;
170: end = mapping->globalend;
171: PetscCall(PetscNew(&map));
172: PetscCall(PetscMalloc1(end - start + 2, &globals));
173: map->globals = globals;
174: for (i = 0; i < end - start + 1; i++) globals[i] = -1;
175: for (i = 0; i < n; i++) {
176: if (idx[i] < 0) continue;
177: globals[idx[i] - start] = i;
178: }
179: mapping->data = (void *)map;
180: PetscFunctionReturn(PETSC_SUCCESS);
181: }
183: static PetscErrorCode ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping)
184: {
185: PetscInt i, *idx = mapping->indices, n = mapping->n;
186: ISLocalToGlobalMapping_Hash *map;
188: PetscFunctionBegin;
189: PetscCall(PetscNew(&map));
190: PetscCall(PetscHMapICreate(&map->globalht));
191: for (i = 0; i < n; i++) {
192: if (idx[i] < 0) continue;
193: PetscCall(PetscHMapISet(map->globalht, idx[i], i));
194: }
195: mapping->data = (void *)map;
196: PetscFunctionReturn(PETSC_SUCCESS);
197: }
199: static PetscErrorCode ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping)
200: {
201: ISLocalToGlobalMapping_Basic *map = (ISLocalToGlobalMapping_Basic *)mapping->data;
203: PetscFunctionBegin;
204: if (!map) PetscFunctionReturn(PETSC_SUCCESS);
205: PetscCall(PetscFree(map->globals));
206: PetscCall(PetscFree(mapping->data));
207: PetscFunctionReturn(PETSC_SUCCESS);
208: }
210: static PetscErrorCode ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping)
211: {
212: ISLocalToGlobalMapping_Hash *map = (ISLocalToGlobalMapping_Hash *)mapping->data;
214: PetscFunctionBegin;
215: if (!map) PetscFunctionReturn(PETSC_SUCCESS);
216: PetscCall(PetscHMapIDestroy(&map->globalht));
217: PetscCall(PetscFree(mapping->data));
218: PetscFunctionReturn(PETSC_SUCCESS);
219: }
221: static PetscErrorCode ISLocalToGlobalMappingResetBlockInfo_Private(ISLocalToGlobalMapping mapping)
222: {
223: PetscFunctionBegin;
224: PetscCall(PetscFree(mapping->info_procs));
225: PetscCall(PetscFree(mapping->info_numprocs));
226: if (mapping->info_indices) {
227: for (PetscInt i = 0; i < mapping->info_nproc; i++) PetscCall(PetscFree(mapping->info_indices[i]));
228: PetscCall(PetscFree(mapping->info_indices));
229: }
230: if (mapping->info_nodei) PetscCall(PetscFree(mapping->info_nodei[0]));
231: PetscCall(PetscFree2(mapping->info_nodec, mapping->info_nodei));
232: PetscCall(PetscSFDestroy(&mapping->multileaves_sf));
233: PetscFunctionReturn(PETSC_SUCCESS);
234: }
236: #define GTOLTYPE _Basic
237: #define GTOLNAME _Basic
238: #define GTOLBS mapping->bs
239: #define GTOL(g, local) \
240: do { \
241: local = map->globals[g / bs - start]; \
242: if (local >= 0) local = bs * local + (g % bs); \
243: } while (0)
245: #include <../src/vec/is/utils/isltog.h>
247: #define GTOLTYPE _Basic
248: #define GTOLNAME Block_Basic
249: #define GTOLBS 1
250: #define GTOL(g, local) \
251: do { \
252: local = map->globals[g - start]; \
253: } while (0)
254: #include <../src/vec/is/utils/isltog.h>
256: #define GTOLTYPE _Hash
257: #define GTOLNAME _Hash
258: #define GTOLBS mapping->bs
259: #define GTOL(g, local) \
260: do { \
261: (void)PetscHMapIGet(map->globalht, g / bs, &local); \
262: if (local >= 0) local = bs * local + (g % bs); \
263: } while (0)
264: #include <../src/vec/is/utils/isltog.h>
266: #define GTOLTYPE _Hash
267: #define GTOLNAME Block_Hash
268: #define GTOLBS 1
269: #define GTOL(g, local) \
270: do { \
271: (void)PetscHMapIGet(map->globalht, g, &local); \
272: } while (0)
273: #include <../src/vec/is/utils/isltog.h>
275: /*@
276: ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
278: Not Collective
280: Input Parameter:
281: . ltog - local to global mapping
283: Output Parameter:
284: . nltog - the duplicated local to global mapping
286: Level: advanced
288: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
289: @*/
290: PetscErrorCode ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog, ISLocalToGlobalMapping *nltog)
291: {
292: ISLocalToGlobalMappingType l2gtype;
294: PetscFunctionBegin;
296: PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog), ltog->bs, ltog->n, ltog->indices, PETSC_COPY_VALUES, nltog));
297: PetscCall(ISLocalToGlobalMappingGetType(ltog, &l2gtype));
298: PetscCall(ISLocalToGlobalMappingSetType(*nltog, l2gtype));
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: /*@
303: ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
305: Not Collective
307: Input Parameter:
308: . mapping - local to global mapping
310: Output Parameter:
311: . n - the number of entries in the local mapping, `ISLocalToGlobalMappingGetIndices()` returns an array of this length
313: Level: advanced
315: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
316: @*/
317: PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping, PetscInt *n)
318: {
319: PetscFunctionBegin;
321: PetscAssertPointer(n, 2);
322: *n = mapping->bs * mapping->n;
323: PetscFunctionReturn(PETSC_SUCCESS);
324: }
326: /*@C
327: ISLocalToGlobalMappingViewFromOptions - View an `ISLocalToGlobalMapping` based on values in the options database
329: Collective
331: Input Parameters:
332: + A - the local to global mapping object
333: . obj - Optional object that provides the options prefix used for the options database query
334: - name - command line option
336: Level: intermediate
338: Note:
339: See `PetscObjectViewFromOptions()` for the available `PetscViewer` and `PetscViewerFormat`
341: .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingView`, `PetscObjectViewFromOptions()`, `ISLocalToGlobalMappingCreate()`
342: @*/
343: PetscErrorCode ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A, PetscObject obj, const char name[])
344: {
345: PetscFunctionBegin;
347: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
348: PetscFunctionReturn(PETSC_SUCCESS);
349: }
351: /*@C
352: ISLocalToGlobalMappingView - View a local to global mapping
354: Collective on viewer
356: Input Parameters:
357: + mapping - local to global mapping
358: - viewer - viewer
360: Level: intermediate
362: .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
363: @*/
364: PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping, PetscViewer viewer)
365: {
366: PetscBool iascii, isbinary;
367: PetscViewerFormat format;
369: PetscFunctionBegin;
371: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping), &viewer));
374: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
375: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
376: PetscCall(PetscViewerGetFormat(viewer, &format));
377: if (iascii) {
378: if (format == PETSC_VIEWER_ASCII_MATLAB) {
379: const PetscInt *idxs;
380: IS is;
381: const char *name = ((PetscObject)mapping)->name;
382: char iname[PETSC_MAX_PATH_LEN];
384: PetscCall(PetscSNPrintf(iname, sizeof(iname), "%sl2g", name ? name : ""));
385: PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &idxs));
386: PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mapping->n * mapping->bs, idxs, PETSC_USE_POINTER, &is));
387: PetscCall(PetscObjectSetName((PetscObject)is, iname));
388: PetscCall(ISView(is, viewer));
389: PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &idxs));
390: PetscCall(ISDestroy(&is));
391: } else {
392: PetscMPIInt rank;
394: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mapping), &rank));
395: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mapping, viewer));
396: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
397: for (PetscInt i = 0; i < mapping->n; i++) {
398: PetscInt bs = mapping->bs, g = mapping->indices[i];
399: if (bs == 1) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT " %" PetscInt_FMT "\n", rank, i, g));
400: 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));
401: }
402: PetscCall(PetscViewerFlush(viewer));
403: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
404: }
405: } else if (isbinary) {
406: PetscBool skipHeader;
408: PetscCall(PetscViewerSetUp(viewer));
409: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
410: if (!skipHeader) {
411: PetscMPIInt size;
412: PetscInt tr[3];
414: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
415: tr[0] = IS_LTOGM_FILE_CLASSID;
416: tr[1] = mapping->bs;
417: tr[2] = size;
418: PetscCall(PetscViewerBinaryWrite(viewer, tr, 3, PETSC_INT));
419: PetscCall(PetscViewerBinaryWriteAll(viewer, &mapping->n, 1, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
420: }
421: /* write block indices */
422: PetscCall(PetscViewerBinaryWriteAll(viewer, mapping->indices, mapping->n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
423: }
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: /*@
428: ISLocalToGlobalMappingLoad - Loads a local-to-global mapping that has been stored in binary format.
430: Collective on viewer
432: Input Parameters:
433: + mapping - the newly loaded map, this needs to have been created with `ISLocalToGlobalMappingCreate()` or some related function before a call to `ISLocalToGlobalMappingLoad()`
434: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
436: Level: intermediate
438: .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingView()`, `ISLocalToGlobalMappingCreate()`
439: @*/
440: PetscErrorCode ISLocalToGlobalMappingLoad(ISLocalToGlobalMapping mapping, PetscViewer viewer)
441: {
442: PetscBool isbinary, skipHeader;
444: PetscFunctionBegin;
447: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
448: PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Invalid viewer of type %s", ((PetscObject)viewer)->type_name);
450: /* reset previous data */
451: PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(mapping));
453: PetscCall(PetscViewerSetUp(viewer));
454: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
456: /* When skipping header, it assumes bs and n have been already set */
457: if (!skipHeader) {
458: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
459: PetscInt tr[3], nold = mapping->n, *sizes, nmaps = PETSC_DECIDE, st = 0;
461: PetscCall(PetscViewerBinaryRead(viewer, tr, 3, NULL, PETSC_INT));
462: PetscCheck(tr[0] == IS_LTOGM_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a local-to-global map next in file");
464: mapping->bs = tr[1];
465: PetscCall(PetscMalloc1(tr[2], &sizes));
466: PetscCall(PetscViewerBinaryRead(viewer, sizes, tr[2], NULL, PETSC_INT));
468: /* consume the input, read multiple maps per process if needed */
469: PetscCall(PetscSplitOwnership(comm, &nmaps, &tr[2]));
470: PetscCallMPI(MPI_Exscan(&nmaps, &st, 1, MPIU_INT, MPI_SUM, comm));
471: mapping->n = 0;
472: for (PetscInt i = st; i < st + nmaps; i++) mapping->n += sizes[i];
473: PetscCall(PetscFree(sizes));
475: if (nold != mapping->n) {
476: if (mapping->dealloc_indices) PetscCall(PetscFree(mapping->indices));
477: mapping->indices = NULL;
478: }
479: }
481: /* read indices */
482: if (mapping->n && !mapping->indices) {
483: PetscCall(PetscMalloc1(mapping->n, &mapping->indices));
484: mapping->dealloc_indices = PETSC_TRUE;
485: }
486: PetscCall(PetscViewerBinaryReadAll(viewer, mapping->indices, mapping->n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
487: PetscFunctionReturn(PETSC_SUCCESS);
488: }
490: /*@
491: ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
492: ordering and a global parallel ordering.
494: Not Collective
496: Input Parameter:
497: . is - index set containing the global numbers for each local number
499: Output Parameter:
500: . mapping - new mapping data structure
502: Level: advanced
504: Note:
505: the block size of the `IS` determines the block size of the mapping
507: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetFromOptions()`
508: @*/
509: PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is, ISLocalToGlobalMapping *mapping)
510: {
511: PetscInt n, bs;
512: const PetscInt *indices;
513: MPI_Comm comm;
514: PetscBool isblock;
516: PetscFunctionBegin;
518: PetscAssertPointer(mapping, 2);
520: PetscCall(PetscObjectGetComm((PetscObject)is, &comm));
521: PetscCall(ISGetLocalSize(is, &n));
522: PetscCall(PetscObjectTypeCompare((PetscObject)is, ISBLOCK, &isblock));
523: if (!isblock) {
524: PetscCall(ISGetIndices(is, &indices));
525: PetscCall(ISLocalToGlobalMappingCreate(comm, 1, n, indices, PETSC_COPY_VALUES, mapping));
526: PetscCall(ISRestoreIndices(is, &indices));
527: } else {
528: PetscCall(ISGetBlockSize(is, &bs));
529: PetscCall(ISBlockGetIndices(is, &indices));
530: PetscCall(ISLocalToGlobalMappingCreate(comm, bs, n / bs, indices, PETSC_COPY_VALUES, mapping));
531: PetscCall(ISBlockRestoreIndices(is, &indices));
532: }
533: PetscFunctionReturn(PETSC_SUCCESS);
534: }
536: /*@C
537: ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n) ordering and a global parallel ordering induced by a star forest.
539: Collective
541: Input Parameters:
542: + sf - star forest mapping contiguous local indices to (rank, offset)
543: - start - first global index on this process, or `PETSC_DECIDE` to compute contiguous global numbering automatically
545: Output Parameter:
546: . mapping - new mapping data structure
548: Level: advanced
550: Note:
551: If a process calls this function with `start` = `PETSC_DECIDE` then all processes must, otherwise the program will hang.
553: .seealso: [](sec_scatter), `PetscSF`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`
554: @*/
555: PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf, PetscInt start, ISLocalToGlobalMapping *mapping)
556: {
557: PetscInt i, maxlocal, nroots, nleaves, *globals, *ltog;
558: MPI_Comm comm;
560: PetscFunctionBegin;
562: PetscAssertPointer(mapping, 3);
563: PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
564: PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
565: if (start == PETSC_DECIDE) {
566: start = 0;
567: PetscCallMPI(MPI_Exscan(&nroots, &start, 1, MPIU_INT, MPI_SUM, comm));
568: } else PetscCheck(start >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "start must be nonnegative or PETSC_DECIDE");
569: PetscCall(PetscSFGetLeafRange(sf, NULL, &maxlocal));
570: ++maxlocal;
571: PetscCall(PetscMalloc1(nroots, &globals));
572: PetscCall(PetscMalloc1(maxlocal, <og));
573: for (i = 0; i < nroots; i++) globals[i] = start + i;
574: for (i = 0; i < maxlocal; i++) ltog[i] = -1;
575: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globals, ltog, MPI_REPLACE));
576: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globals, ltog, MPI_REPLACE));
577: PetscCall(ISLocalToGlobalMappingCreate(comm, 1, maxlocal, ltog, PETSC_OWN_POINTER, mapping));
578: PetscCall(PetscFree(globals));
579: PetscFunctionReturn(PETSC_SUCCESS);
580: }
582: /*@
583: ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
585: Not Collective
587: Input Parameters:
588: + mapping - mapping data structure
589: - bs - the blocksize
591: Level: advanced
593: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`
594: @*/
595: PetscErrorCode ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping, PetscInt bs)
596: {
597: PetscInt *nid;
598: const PetscInt *oid;
599: PetscInt i, cn, on, obs, nn;
601: PetscFunctionBegin;
603: PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid block size %" PetscInt_FMT, bs);
604: if (bs == mapping->bs) PetscFunctionReturn(PETSC_SUCCESS);
605: on = mapping->n;
606: obs = mapping->bs;
607: oid = mapping->indices;
608: nn = (on * obs) / bs;
609: 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);
611: PetscCall(PetscMalloc1(nn, &nid));
612: PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &oid));
613: for (i = 0; i < nn; i++) {
614: PetscInt j;
615: for (j = 0, cn = 0; j < bs - 1; j++) {
616: if (oid[i * bs + j] < 0) {
617: cn++;
618: continue;
619: }
620: 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]);
621: }
622: if (oid[i * bs + j] < 0) cn++;
623: if (cn) {
624: 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);
625: nid[i] = -1;
626: } else {
627: nid[i] = oid[i * bs] / bs;
628: }
629: }
630: PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &oid));
632: mapping->n = nn;
633: mapping->bs = bs;
634: PetscCall(PetscFree(mapping->indices));
635: mapping->indices = nid;
636: mapping->globalstart = 0;
637: mapping->globalend = 0;
639: /* reset the cached information */
640: PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(mapping));
641: PetscTryTypeMethod(mapping, destroy);
642: PetscFunctionReturn(PETSC_SUCCESS);
643: }
645: /*@
646: ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
647: ordering and a global parallel ordering.
649: Not Collective
651: Input Parameter:
652: . mapping - mapping data structure
654: Output Parameter:
655: . bs - the blocksize
657: Level: advanced
659: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`
660: @*/
661: PetscErrorCode ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping, PetscInt *bs)
662: {
663: PetscFunctionBegin;
665: *bs = mapping->bs;
666: PetscFunctionReturn(PETSC_SUCCESS);
667: }
669: /*@
670: ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
671: ordering and a global parallel ordering.
673: Not Collective, but communicator may have more than one process
675: Input Parameters:
676: + comm - MPI communicator
677: . bs - the block size
678: . n - the number of local elements divided by the block size, or equivalently the number of block indices
679: . 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
680: - mode - see PetscCopyMode
682: Output Parameter:
683: . mapping - new mapping data structure
685: Level: advanced
687: Notes:
688: There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
690: For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType`
691: of `ISLOCALTOGLOBALMAPPINGBASIC` will be used; this uses more memory but is faster; this approach is not scalable for extremely large mappings.
693: For large problems `ISLOCALTOGLOBALMAPPINGHASH` is used, this is scalable.
694: Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option
695: `-islocaltoglobalmapping_type` <`basic`,`hash`> to control which is used.
697: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`,
698: `ISLOCALTOGLOBALMAPPINGBASIC`, `ISLOCALTOGLOBALMAPPINGHASH`
699: `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType`
700: @*/
701: PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm comm, PetscInt bs, PetscInt n, const PetscInt indices[], PetscCopyMode mode, ISLocalToGlobalMapping *mapping)
702: {
703: PetscInt *in;
705: PetscFunctionBegin;
706: if (n) PetscAssertPointer(indices, 4);
707: PetscAssertPointer(mapping, 6);
709: *mapping = NULL;
710: PetscCall(ISInitializePackage());
712: PetscCall(PetscHeaderCreate(*mapping, IS_LTOGM_CLASSID, "ISLocalToGlobalMapping", "Local to global mapping", "IS", comm, ISLocalToGlobalMappingDestroy, ISLocalToGlobalMappingView));
713: (*mapping)->n = n;
714: (*mapping)->bs = bs;
715: if (mode == PETSC_COPY_VALUES) {
716: PetscCall(PetscMalloc1(n, &in));
717: PetscCall(PetscArraycpy(in, indices, n));
718: (*mapping)->indices = in;
719: (*mapping)->dealloc_indices = PETSC_TRUE;
720: } else if (mode == PETSC_OWN_POINTER) {
721: (*mapping)->indices = (PetscInt *)indices;
722: (*mapping)->dealloc_indices = PETSC_TRUE;
723: } else if (mode == PETSC_USE_POINTER) {
724: (*mapping)->indices = (PetscInt *)indices;
725: } else SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid mode %d", mode);
726: PetscFunctionReturn(PETSC_SUCCESS);
727: }
729: PetscFunctionList ISLocalToGlobalMappingList = NULL;
731: /*@
732: ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database.
734: Not Collective
736: Input Parameter:
737: . mapping - mapping data structure
739: Options Database Key:
740: . -islocaltoglobalmapping_type - <basic,hash> nonscalable and scalable versions
742: Level: advanced
744: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`,
745: `ISLocalToGlobalMappingCreateIS()`, `ISLOCALTOGLOBALMAPPINGBASIC`,
746: `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType`
747: @*/
748: PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)
749: {
750: char type[256];
751: ISLocalToGlobalMappingType defaulttype = "Not set";
752: PetscBool flg;
754: PetscFunctionBegin;
756: PetscCall(ISLocalToGlobalMappingRegisterAll());
757: PetscObjectOptionsBegin((PetscObject)mapping);
758: PetscCall(PetscOptionsFList("-islocaltoglobalmapping_type", "ISLocalToGlobalMapping method", "ISLocalToGlobalMappingSetType", ISLocalToGlobalMappingList, (char *)(((PetscObject)mapping)->type_name) ? ((PetscObject)mapping)->type_name : defaulttype, type, 256, &flg));
759: if (flg) PetscCall(ISLocalToGlobalMappingSetType(mapping, type));
760: PetscOptionsEnd();
761: PetscFunctionReturn(PETSC_SUCCESS);
762: }
764: /*@
765: ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
766: ordering and a global parallel ordering.
768: Not Collective
770: Input Parameter:
771: . mapping - mapping data structure
773: Level: advanced
775: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`
776: @*/
777: PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
778: {
779: PetscFunctionBegin;
780: if (!*mapping) PetscFunctionReturn(PETSC_SUCCESS);
782: if (--((PetscObject)*mapping)->refct > 0) {
783: *mapping = NULL;
784: PetscFunctionReturn(PETSC_SUCCESS);
785: }
786: if ((*mapping)->dealloc_indices) PetscCall(PetscFree((*mapping)->indices));
787: PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(*mapping));
788: PetscTryTypeMethod(*mapping, destroy);
789: PetscCall(PetscHeaderDestroy(mapping));
790: PetscFunctionReturn(PETSC_SUCCESS);
791: }
793: /*@
794: ISLocalToGlobalMappingApplyIS - Creates from an `IS` in the local numbering
795: a new index set using the global numbering defined in an `ISLocalToGlobalMapping`
796: context.
798: Collective
800: Input Parameters:
801: + mapping - mapping between local and global numbering
802: - is - index set in local numbering
804: Output Parameter:
805: . newis - index set in global numbering
807: Level: advanced
809: Note:
810: The output `IS` will have the same communicator as the input `IS`.
812: .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
813: `ISLocalToGlobalMappingDestroy()`, `ISGlobalToLocalMappingApply()`
814: @*/
815: PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping, IS is, IS *newis)
816: {
817: PetscInt n, *idxout;
818: const PetscInt *idxin;
820: PetscFunctionBegin;
823: PetscAssertPointer(newis, 3);
825: PetscCall(ISGetLocalSize(is, &n));
826: PetscCall(ISGetIndices(is, &idxin));
827: PetscCall(PetscMalloc1(n, &idxout));
828: PetscCall(ISLocalToGlobalMappingApply(mapping, n, idxin, idxout));
829: PetscCall(ISRestoreIndices(is, &idxin));
830: PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), n, idxout, PETSC_OWN_POINTER, newis));
831: PetscFunctionReturn(PETSC_SUCCESS);
832: }
834: /*@
835: ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
836: and converts them to the global numbering.
838: Not Collective
840: Input Parameters:
841: + mapping - the local to global mapping context
842: . N - number of integers
843: - in - input indices in local numbering
845: Output Parameter:
846: . out - indices in global numbering
848: Level: advanced
850: Note:
851: The `in` and `out` array parameters may be identical.
853: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`,
854: `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`,
855: `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()`
856: @*/
857: PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[])
858: {
859: PetscInt i, bs, Nmax;
861: PetscFunctionBegin;
863: bs = mapping->bs;
864: Nmax = bs * mapping->n;
865: if (bs == 1) {
866: const PetscInt *idx = mapping->indices;
867: for (i = 0; i < N; i++) {
868: if (in[i] < 0) {
869: out[i] = in[i];
870: continue;
871: }
872: 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);
873: out[i] = idx[in[i]];
874: }
875: } else {
876: const PetscInt *idx = mapping->indices;
877: for (i = 0; i < N; i++) {
878: if (in[i] < 0) {
879: out[i] = in[i];
880: continue;
881: }
882: 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);
883: out[i] = idx[in[i] / bs] * bs + (in[i] % bs);
884: }
885: }
886: PetscFunctionReturn(PETSC_SUCCESS);
887: }
889: /*@
890: ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
892: Not Collective
894: Input Parameters:
895: + mapping - the local to global mapping context
896: . N - number of integers
897: - in - input indices in local block numbering
899: Output Parameter:
900: . out - indices in global block numbering
902: Example:
903: 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
904: (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3.
906: Level: advanced
908: Note:
909: The `in` and `out` array parameters may be identical.
911: .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`,
912: `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`,
913: `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()`
914: @*/
915: PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[])
916: {
917: PetscInt i, Nmax;
918: const PetscInt *idx;
920: PetscFunctionBegin;
922: Nmax = mapping->n;
923: idx = mapping->indices;
924: for (i = 0; i < N; i++) {
925: if (in[i] < 0) {
926: out[i] = in[i];
927: continue;
928: }
929: 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);
930: out[i] = idx[in[i]];
931: }
932: PetscFunctionReturn(PETSC_SUCCESS);
933: }
935: /*@
936: ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
937: specified with a global numbering.
939: Not Collective
941: Input Parameters:
942: + mapping - mapping between local and global numbering
943: . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
944: `IS_GTOLM_DROP` - drops the indices with no local value from the output list
945: . n - number of global indices to map
946: - idx - global indices to map
948: Output Parameters:
949: + nout - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n)
950: - idxout - local index of each global index, one must pass in an array long enough
951: to hold all the indices. You can call `ISGlobalToLocalMappingApply()` with
952: idxout == NULL to determine the required length (returned in nout)
953: and then allocate the required space and call `ISGlobalToLocalMappingApply()`
954: a second time to set the values.
956: Level: advanced
958: Notes:
959: Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical.
961: For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of
962: `ISLOCALTOGLOBALMAPPINGBASIC` will be used;
963: 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.
964: Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
966: Developer Notes:
967: The manual page states that `idx` and `idxout` may be identical but the calling
968: sequence declares `idx` as const so it cannot be the same as `idxout`.
970: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`,
971: `ISLocalToGlobalMappingDestroy()`
972: @*/
973: PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[])
974: {
975: PetscFunctionBegin;
977: if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping));
978: PetscUseTypeMethod(mapping, globaltolocalmappingapply, type, n, idx, nout, idxout);
979: PetscFunctionReturn(PETSC_SUCCESS);
980: }
982: /*@
983: ISGlobalToLocalMappingApplyIS - Creates from an `IS` in the global numbering
984: a new index set using the local numbering defined in an `ISLocalToGlobalMapping`
985: context.
987: Not Collective
989: Input Parameters:
990: + mapping - mapping between local and global numbering
991: . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
992: `IS_GTOLM_DROP` - drops the indices with no local value from the output list
993: - is - index set in global numbering
995: Output Parameter:
996: . newis - index set in local numbering
998: Level: advanced
1000: Note:
1001: The output `IS` will be sequential, as it encodes a purely local operation
1003: .seealso: [](sec_scatter), `ISGlobalToLocalMapping`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
1004: `ISLocalToGlobalMappingDestroy()`
1005: @*/
1006: PetscErrorCode ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, IS is, IS *newis)
1007: {
1008: PetscInt n, nout, *idxout;
1009: const PetscInt *idxin;
1011: PetscFunctionBegin;
1014: PetscAssertPointer(newis, 4);
1016: PetscCall(ISGetLocalSize(is, &n));
1017: PetscCall(ISGetIndices(is, &idxin));
1018: if (type == IS_GTOLM_MASK) {
1019: PetscCall(PetscMalloc1(n, &idxout));
1020: } else {
1021: PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, NULL));
1022: PetscCall(PetscMalloc1(nout, &idxout));
1023: }
1024: PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, idxout));
1025: PetscCall(ISRestoreIndices(is, &idxin));
1026: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nout, idxout, PETSC_OWN_POINTER, newis));
1027: PetscFunctionReturn(PETSC_SUCCESS);
1028: }
1030: /*@
1031: ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
1032: specified with a block global numbering.
1034: Not Collective
1036: Input Parameters:
1037: + mapping - mapping between local and global numbering
1038: . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
1039: `IS_GTOLM_DROP` - drops the indices with no local value from the output list
1040: . n - number of global indices to map
1041: - idx - global indices to map
1043: Output Parameters:
1044: + nout - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n)
1045: - idxout - local index of each global index, one must pass in an array long enough
1046: to hold all the indices. You can call `ISGlobalToLocalMappingApplyBlock()` with
1047: idxout == NULL to determine the required length (returned in nout)
1048: and then allocate the required space and call `ISGlobalToLocalMappingApplyBlock()`
1049: a second time to set the values.
1051: Level: advanced
1053: Notes:
1054: Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical.
1056: For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of
1057: `ISLOCALTOGLOBALMAPPINGBASIC` will be used;
1058: 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.
1059: Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
1061: Developer Notes:
1062: The manual page states that `idx` and `idxout` may be identical but the calling
1063: sequence declares `idx` as const so it cannot be the same as `idxout`.
1065: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
1066: `ISLocalToGlobalMappingDestroy()`
1067: @*/
1068: PetscErrorCode ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[])
1069: {
1070: PetscFunctionBegin;
1072: if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping));
1073: PetscUseTypeMethod(mapping, globaltolocalmappingapplyblock, type, n, idx, nout, idxout);
1074: PetscFunctionReturn(PETSC_SUCCESS);
1075: }
1077: /*@C
1078: ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information
1080: Collective the first time it is called
1082: Input Parameter:
1083: . mapping - the mapping from local to global indexing
1085: Output Parameters:
1086: + nproc - number of processes that are connected to the calling process
1087: . procs - neighboring processes
1088: . numprocs - number of block indices for each process
1089: - indices - block indices (in local numbering) shared with neighbors (sorted by global numbering)
1091: Level: advanced
1093: .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1094: `ISLocalToGlobalMappingRestoreBlockInfo()`, `ISLocalToGlobalMappingGetBlockMultiLeavesSF()`
1095: @*/
1096: PetscErrorCode ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1097: {
1098: PetscFunctionBegin;
1100: PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping));
1101: if (nproc) *nproc = mapping->info_nproc;
1102: if (procs) *procs = mapping->info_procs;
1103: if (numprocs) *numprocs = mapping->info_numprocs;
1104: if (indices) *indices = mapping->info_indices;
1105: PetscFunctionReturn(PETSC_SUCCESS);
1106: }
1108: /*@C
1109: ISLocalToGlobalMappingGetBlockNodeInfo - Gets the neighbor information for each local block index
1111: Collective the first time it is called
1113: Input Parameter:
1114: . mapping - the mapping from local to global indexing
1116: Output Parameters:
1117: + n - number of local block nodes
1118: . n_procs - an array storing the number of processes for each local block node (including self)
1119: - procs - the processes' rank for each local block node (sorted, self is first)
1121: Level: advanced
1123: Notes:
1124: The user needs to call `ISLocalToGlobalMappingRestoreBlockNodeInfo()` when the data is no longer needed.
1125: The information returned by this function complements that of `ISLocalToGlobalMappingGetBlockInfo()`.
1126: The latter only provides local information, and the neighboring information
1127: cannot be inferred in the general case, unless the mapping is locally one-to-one on each process.
1129: .seealso: `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1130: `ISLocalToGlobalMappingGetBlockInfo()`, `ISLocalToGlobalMappingRestoreBlockNodeInfo()`, `ISLocalToGlobalMappingGetNodeInfo()`
1131: @*/
1132: PetscErrorCode ISLocalToGlobalMappingGetBlockNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1133: {
1134: PetscFunctionBegin;
1136: PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping));
1137: if (n) *n = mapping->n;
1138: if (n_procs) *n_procs = mapping->info_nodec;
1139: if (procs) *procs = mapping->info_nodei;
1140: PetscFunctionReturn(PETSC_SUCCESS);
1141: }
1143: /*@C
1144: ISLocalToGlobalMappingRestoreBlockNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockNodeInfo()`
1146: Not Collective
1148: Input Parameters:
1149: + mapping - the mapping from local to global indexing
1150: . n - number of local block nodes
1151: . n_procs - an array storing the number of processes for each local block nodes (including self)
1152: - procs - the processes' rank for each local block node (sorted, self is first)
1154: Level: advanced
1156: .seealso: `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1157: `ISLocalToGlobalMappingGetBlockNodeInfo()`
1158: @*/
1159: PetscErrorCode ISLocalToGlobalMappingRestoreBlockNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1160: {
1161: PetscFunctionBegin;
1163: if (n) *n = 0;
1164: if (n_procs) *n_procs = NULL;
1165: if (procs) *procs = NULL;
1166: PetscFunctionReturn(PETSC_SUCCESS);
1167: }
1169: /*@C
1170: ISLocalToGlobalMappingGetBlockMultiLeavesSF - Get the star-forest to communicate multi-leaf block data
1172: Collective the first time it is called
1174: Input Parameter:
1175: . mapping - the mapping from local to global indexing
1177: Output Parameter:
1178: . mlsf - the `PetscSF`
1180: Level: advanced
1182: Notes:
1183: The returned star forest is suitable to exchange local information with other processes sharing the same global block index.
1184: For example, suppose a mapping with two processes has been created with
1185: .vb
1186: rank 0 global block indices: [0, 1, 2]
1187: rank 1 global block indices: [2, 3, 4]
1188: .ve
1189: and we want to share the local information
1190: .vb
1191: rank 0 data: [-1, -2, -3]
1192: rank 1 data: [1, 2, 3]
1193: .ve
1194: then, the broadcasting action of `mlsf` will allow to collect
1195: .vb
1196: rank 0 mlleafdata: [-1, -2, -3, 3]
1197: rank 1 mlleafdata: [-3, 3, 1, 2]
1198: .ve
1199: Use ``ISLocalToGlobalMappingGetBlockNodeInfo()`` to index into the multi-leaf data.
1201: .seealso: [](sec_scatter), `ISLocalToGlobalMappingGetBlockNodeInfo()`, `PetscSF`
1202: @*/
1203: PetscErrorCode ISLocalToGlobalMappingGetBlockMultiLeavesSF(ISLocalToGlobalMapping mapping, PetscSF *mlsf)
1204: {
1205: PetscFunctionBegin;
1207: PetscAssertPointer(mlsf, 2);
1208: PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping));
1209: *mlsf = mapping->multileaves_sf;
1210: PetscFunctionReturn(PETSC_SUCCESS);
1211: }
1213: static PetscErrorCode ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping mapping)
1214: {
1215: PetscSF sf, sf2, imsf, msf;
1216: MPI_Comm comm;
1217: const PetscSFNode *sfnode;
1218: PetscSFNode *newsfnode;
1219: PetscLayout layout;
1220: PetscHMapI neighs;
1221: PetscHashIter iter;
1222: PetscBool missing;
1223: const PetscInt *gidxs, *rootdegree;
1224: PetscInt *mask, *mrootdata, *leafdata, *newleafdata, *leafrd, *tmpg;
1225: PetscInt nroots, nleaves, newnleaves, bs, i, j, m, mnroots, p;
1226: PetscMPIInt rank, size;
1228: PetscFunctionBegin;
1229: if (mapping->multileaves_sf) PetscFunctionReturn(PETSC_SUCCESS);
1230: PetscCall(PetscObjectGetComm((PetscObject)mapping, &comm));
1231: PetscCallMPI(MPI_Comm_size(comm, &size));
1232: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1234: /* Get mapping indices */
1235: PetscCall(ISLocalToGlobalMappingGetBlockSize(mapping, &bs));
1236: PetscCall(ISLocalToGlobalMappingGetBlockIndices(mapping, &gidxs));
1237: PetscCall(ISLocalToGlobalMappingGetSize(mapping, &nleaves));
1238: nleaves /= bs;
1240: /* Create layout for global indices */
1241: for (i = 0, m = 0; i < nleaves; i++) m = PetscMax(m, gidxs[i]);
1242: PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &m, 1, MPIU_INT, MPI_MAX, comm));
1243: PetscCall(PetscLayoutCreate(comm, &layout));
1244: PetscCall(PetscLayoutSetSize(layout, m + 1));
1245: PetscCall(PetscLayoutSetUp(layout));
1247: /* Create SF to share global indices */
1248: PetscCall(PetscSFCreate(comm, &sf));
1249: PetscCall(PetscSFSetGraphLayout(sf, layout, nleaves, NULL, PETSC_OWN_POINTER, gidxs));
1250: PetscCall(PetscSFSetUp(sf));
1251: PetscCall(PetscLayoutDestroy(&layout));
1253: /* communicate root degree to leaves */
1254: PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, &sfnode));
1255: PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
1256: PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
1257: for (i = 0, mnroots = 0; i < nroots; i++) mnroots += rootdegree[i];
1258: PetscCall(PetscMalloc3(2 * PetscMax(mnroots, nroots), &mrootdata, 2 * nleaves, &leafdata, nleaves, &leafrd));
1259: for (i = 0, m = 0; i < nroots; i++) {
1260: mrootdata[2 * i + 0] = rootdegree[i];
1261: mrootdata[2 * i + 1] = m;
1262: m += rootdegree[i];
1263: }
1264: PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, mrootdata, leafdata, MPI_REPLACE));
1265: PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, mrootdata, leafdata, MPI_REPLACE));
1267: /* allocate enough space to store ranks */
1268: for (i = 0, newnleaves = 0; i < nleaves; i++) {
1269: newnleaves += leafdata[2 * i];
1270: leafrd[i] = leafdata[2 * i];
1271: }
1273: /* create new SF nodes to collect multi-root data at leaves */
1274: PetscCall(PetscMalloc1(newnleaves, &newsfnode));
1275: for (i = 0, m = 0; i < nleaves; i++) {
1276: for (j = 0; j < leafrd[i]; j++) {
1277: newsfnode[m].rank = sfnode[i].rank;
1278: newsfnode[m].index = leafdata[2 * i + 1] + j;
1279: m++;
1280: }
1281: }
1283: /* gather ranks at multi roots */
1284: for (i = 0; i < mnroots; i++) mrootdata[i] = -1;
1285: for (i = 0; i < nleaves; i++) leafdata[i] = (PetscInt)rank;
1287: PetscCall(PetscSFGatherBegin(sf, MPIU_INT, leafdata, mrootdata));
1288: PetscCall(PetscSFGatherEnd(sf, MPIU_INT, leafdata, mrootdata));
1290: /* from multi-roots to multi-leaves */
1291: PetscCall(PetscSFCreate(comm, &sf2));
1292: PetscCall(PetscSFSetGraph(sf2, mnroots, newnleaves, NULL, PETSC_OWN_POINTER, newsfnode, PETSC_OWN_POINTER));
1293: PetscCall(PetscSFSetUp(sf2));
1295: /* broadcast multi-root data to multi-leaves */
1296: PetscCall(PetscMalloc1(newnleaves, &newleafdata));
1297: PetscCall(PetscSFBcastBegin(sf2, MPIU_INT, mrootdata, newleafdata, MPI_REPLACE));
1298: PetscCall(PetscSFBcastEnd(sf2, MPIU_INT, mrootdata, newleafdata, MPI_REPLACE));
1300: /* sort sharing ranks */
1301: for (i = 0, m = 0; i < nleaves; i++) {
1302: PetscCall(PetscSortInt(leafrd[i], newleafdata + m));
1303: m += leafrd[i];
1304: }
1306: /* Number of neighbors and their ranks */
1307: PetscCall(PetscHMapICreate(&neighs));
1308: for (i = 0; i < newnleaves; i++) PetscCall(PetscHMapIPut(neighs, newleafdata[i], &iter, &missing));
1309: PetscCall(PetscHMapIGetSize(neighs, &mapping->info_nproc));
1310: PetscCall(PetscMalloc1(mapping->info_nproc + 1, &mapping->info_procs));
1311: PetscCall(PetscHMapIGetKeys(neighs, (i = 0, &i), mapping->info_procs));
1312: for (i = 0; i < mapping->info_nproc; i++) { /* put info for self first */
1313: if (mapping->info_procs[i] == rank) {
1314: PetscInt newr = mapping->info_procs[0];
1316: mapping->info_procs[0] = rank;
1317: mapping->info_procs[i] = newr;
1318: break;
1319: }
1320: }
1321: if (mapping->info_nproc) PetscCall(PetscSortInt(mapping->info_nproc - 1, mapping->info_procs + 1));
1322: PetscCall(PetscHMapIDestroy(&neighs));
1324: /* collect info data */
1325: PetscCall(PetscMalloc1(mapping->info_nproc, &mapping->info_numprocs));
1326: PetscCall(PetscMalloc1(mapping->info_nproc, &mapping->info_indices));
1327: for (i = 0; i < mapping->info_nproc; i++) mapping->info_indices[i] = NULL;
1329: PetscCall(PetscMalloc1(nleaves, &mask));
1330: PetscCall(PetscMalloc1(nleaves, &tmpg));
1331: for (p = 0; p < mapping->info_nproc; p++) {
1332: PetscInt *tmp, trank = mapping->info_procs[p];
1334: PetscCall(PetscMemzero(mask, nleaves * sizeof(*mask)));
1335: for (i = 0, m = 0; i < nleaves; i++) {
1336: for (j = 0; j < leafrd[i]; j++) {
1337: if (newleafdata[m] == trank) mask[i]++;
1338: if (!p && newleafdata[m] != rank) mask[i]++;
1339: m++;
1340: }
1341: }
1342: for (i = 0, m = 0; i < nleaves; i++)
1343: if (mask[i] > (!p ? 1 : 0)) m++;
1345: PetscCall(PetscMalloc1(m, &tmp));
1346: for (i = 0, m = 0; i < nleaves; i++)
1347: if (mask[i] > (!p ? 1 : 0)) {
1348: tmp[m] = i;
1349: tmpg[m] = gidxs[i];
1350: m++;
1351: }
1352: PetscCall(PetscSortIntWithArray(m, tmpg, tmp));
1353: mapping->info_indices[p] = tmp;
1354: mapping->info_numprocs[p] = m;
1355: }
1357: /* Node info */
1358: PetscCall(PetscMalloc2(nleaves, &mapping->info_nodec, nleaves + 1, &mapping->info_nodei));
1359: PetscCall(PetscArraycpy(mapping->info_nodec, leafrd, nleaves));
1360: PetscCall(PetscMalloc1(newnleaves, &mapping->info_nodei[0]));
1361: for (i = 0; i < nleaves - 1; i++) mapping->info_nodei[i + 1] = mapping->info_nodei[i] + mapping->info_nodec[i];
1362: PetscCall(PetscArraycpy(mapping->info_nodei[0], newleafdata, newnleaves));
1364: /* Create SF from leaves to multi-leaves */
1365: PetscCall(PetscSFGetMultiSF(sf, &msf));
1366: PetscCall(PetscSFCreateInverseSF(msf, &imsf));
1367: PetscCall(PetscSFCompose(imsf, sf2, &mapping->multileaves_sf));
1368: PetscCall(PetscSFDestroy(&imsf));
1369: PetscCall(PetscSFDestroy(&sf));
1370: PetscCall(PetscSFDestroy(&sf2));
1372: PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(mapping, &gidxs));
1373: PetscCall(PetscFree(tmpg));
1374: PetscCall(PetscFree(mask));
1375: PetscCall(PetscFree3(mrootdata, leafdata, leafrd));
1376: PetscCall(PetscFree(newleafdata));
1377: PetscFunctionReturn(PETSC_SUCCESS);
1378: }
1380: /*@C
1381: ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockInfo()`
1383: Not Collective
1385: Input Parameters:
1386: + mapping - the mapping from local to global indexing
1387: . nproc - number of processes that are connected to the calling process
1388: . procs - neighboring processes
1389: . numprocs - number of block indices for each process
1390: - indices - block indices (in local numbering) shared with neighbors (sorted by global numbering)
1392: Level: advanced
1394: .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1395: `ISLocalToGlobalMappingGetInfo()`
1396: @*/
1397: PetscErrorCode ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1398: {
1399: PetscFunctionBegin;
1401: if (nproc) *nproc = 0;
1402: if (procs) *procs = NULL;
1403: if (numprocs) *numprocs = NULL;
1404: if (indices) *indices = NULL;
1405: PetscFunctionReturn(PETSC_SUCCESS);
1406: }
1408: /*@C
1409: ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each process
1411: Collective the first time it is called
1413: Input Parameter:
1414: . mapping - the mapping from local to global indexing
1416: Output Parameters:
1417: + nproc - number of processes that are connected to the calling process
1418: . procs - neighboring processes
1419: . numprocs - number of indices for each process
1420: - indices - indices (in local numbering) shared with neighbors (sorted by global numbering)
1422: Level: advanced
1424: Note:
1425: The user needs to call `ISLocalToGlobalMappingRestoreInfo()` when the data is no longer needed.
1427: Fortran Notes:
1428: There is no `ISLocalToGlobalMappingRestoreInfo()` in Fortran. You must make sure that
1429: `procs`[], `numprocs`[] and `indices`[][] are large enough arrays, either by allocating them
1430: dynamically or defining static ones large enough.
1432: .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1433: `ISLocalToGlobalMappingRestoreInfo()`, `ISLocalToGlobalMappingGetNodeInfo()`
1434: @*/
1435: PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1436: {
1437: PetscInt **bindices = NULL, *bnumprocs = NULL, bs, i, j, k, n, *bprocs;
1439: PetscFunctionBegin;
1441: bs = mapping->bs;
1442: PetscCall(ISLocalToGlobalMappingGetBlockInfo(mapping, &n, &bprocs, &bnumprocs, &bindices));
1443: if (bs > 1) { /* we need to expand the cached info */
1444: if (indices) PetscCall(PetscCalloc1(n, indices));
1445: if (numprocs) PetscCall(PetscCalloc1(n, numprocs));
1446: if (indices || numprocs) {
1447: for (i = 0; i < n; i++) {
1448: if (indices) {
1449: PetscCall(PetscMalloc1(bs * bnumprocs[i], &(*indices)[i]));
1450: for (j = 0; j < bnumprocs[i]; j++) {
1451: for (k = 0; k < bs; k++) (*indices)[i][j * bs + k] = bs * bindices[i][j] + k;
1452: }
1453: }
1454: if (numprocs) (*numprocs)[i] = bnumprocs[i] * bs;
1455: }
1456: }
1457: } else {
1458: if (numprocs) *numprocs = bnumprocs;
1459: if (indices) *indices = bindices;
1460: }
1461: if (nproc) *nproc = n;
1462: if (procs) *procs = bprocs;
1463: PetscFunctionReturn(PETSC_SUCCESS);
1464: }
1466: /*@C
1467: ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetInfo()`
1469: Not Collective
1471: Input Parameters:
1472: + mapping - the mapping from local to global indexing
1473: . nproc - number of processes that are connected to the calling process
1474: . procs - neighboring processes
1475: . numprocs - number of indices for each process
1476: - indices - indices (in local numbering) shared with neighbors (sorted by global numbering)
1478: Level: advanced
1480: .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1481: `ISLocalToGlobalMappingGetInfo()`
1482: @*/
1483: PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1484: {
1485: PetscFunctionBegin;
1487: if (mapping->bs > 1) {
1488: if (numprocs) PetscCall(PetscFree(*numprocs));
1489: if (indices) {
1490: if (*indices)
1491: for (PetscInt i = 0; i < *nproc; i++) PetscCall(PetscFree((*indices)[i]));
1492: PetscCall(PetscFree(*indices));
1493: }
1494: }
1495: PetscFunctionReturn(PETSC_SUCCESS);
1496: }
1498: /*@C
1499: ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information of local nodes
1501: Collective the first time it is called
1503: Input Parameter:
1504: . mapping - the mapping from local to global indexing
1506: Output Parameters:
1507: + n - number of local nodes
1508: . n_procs - an array storing the number of processes for each local node (including self)
1509: - procs - the processes' rank for each local node (sorted, self is first)
1511: Level: advanced
1513: Note:
1514: The user needs to call `ISLocalToGlobalMappingRestoreNodeInfo()` when the data is no longer needed.
1516: .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1517: `ISLocalToGlobalMappingGetInfo()`, `ISLocalToGlobalMappingRestoreNodeInfo()`, `ISLocalToGlobalMappingGetBlockNodeInfo()`
1518: @*/
1519: PetscErrorCode ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1520: {
1521: PetscInt **bprocs = NULL, *bn_procs = NULL, bs, i, j, k, bn;
1523: PetscFunctionBegin;
1525: bs = mapping->bs;
1526: PetscCall(ISLocalToGlobalMappingGetBlockNodeInfo(mapping, &bn, &bn_procs, &bprocs));
1527: if (bs > 1) { /* we need to expand the cached info */
1528: PetscInt *tn_procs;
1529: PetscInt c;
1531: PetscCall(PetscMalloc1(bn * bs, &tn_procs));
1532: for (i = 0, c = 0; i < bn; i++) {
1533: for (k = 0; k < bs; k++) tn_procs[i * bs + k] = bn_procs[i];
1534: c += bs * bn_procs[i];
1535: }
1536: if (n) *n = bn * bs;
1537: if (procs) {
1538: PetscInt **tprocs;
1539: PetscInt tn = bn * bs;
1541: PetscCall(PetscMalloc1(tn, &tprocs));
1542: if (tn) PetscCall(PetscMalloc1(c, &tprocs[0]));
1543: for (i = 0; i < tn - 1; i++) tprocs[i + 1] = tprocs[i] + tn_procs[i];
1544: for (i = 0; i < bn; i++) {
1545: for (k = 0; k < bs; k++) {
1546: for (j = 0; j < bn_procs[i]; j++) tprocs[i * bs + k][j] = bprocs[i][j];
1547: }
1548: }
1549: *procs = tprocs;
1550: }
1551: if (n_procs) *n_procs = tn_procs;
1552: else PetscCall(PetscFree(tn_procs));
1553: } else {
1554: if (n) *n = bn;
1555: if (n_procs) *n_procs = bn_procs;
1556: if (procs) *procs = bprocs;
1557: }
1558: PetscFunctionReturn(PETSC_SUCCESS);
1559: }
1561: /*@C
1562: ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetNodeInfo()`
1564: Not Collective
1566: Input Parameters:
1567: + mapping - the mapping from local to global indexing
1568: . n - number of local nodes
1569: . n_procs - an array storing the number of processes for each local node (including self)
1570: - procs - the processes' rank for each local node (sorted, self is first)
1572: Level: advanced
1574: .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1575: `ISLocalToGlobalMappingGetInfo()`
1576: @*/
1577: PetscErrorCode ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1578: {
1579: PetscFunctionBegin;
1581: if (mapping->bs > 1) {
1582: if (n_procs) PetscCall(PetscFree(*n_procs));
1583: if (procs) {
1584: if (*procs) PetscCall(PetscFree((*procs)[0]));
1585: PetscCall(PetscFree(*procs));
1586: }
1587: }
1588: PetscCall(ISLocalToGlobalMappingRestoreBlockNodeInfo(mapping, n, n_procs, procs));
1589: PetscFunctionReturn(PETSC_SUCCESS);
1590: }
1592: /*MC
1593: ISLocalToGlobalMappingGetIndicesF90 - Get global indices for every local point that is mapped
1595: Synopsis:
1596: ISLocalToGlobalMappingGetIndicesF90(ISLocalToGlobalMapping ltog, PetscInt, pointer :: array(:)}, integer ierr)
1598: Not Collective
1600: Input Parameter:
1601: . A - the matrix
1603: Output Parameter:
1604: . array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
1606: Level: advanced
1608: Note:
1609: Use `ISLocalToGlobalMappingGetIndicesF90()` when you no longer need access to the data
1611: .seealso: [](sec_fortranarrays), [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingGetIndices()`, `ISLocalToGlobalMappingRestoreIndices()`,
1612: `ISLocalToGlobalMappingRestoreIndicesF90()`
1613: M*/
1615: /*MC
1616: ISLocalToGlobalMappingRestoreIndicesF90 - restores the global indices for every local point that is mapped obtained with `ISLocalToGlobalMappingGetIndicesF90()`
1618: Synopsis:
1619: ISLocalToGlobalMappingRestoreIndicesF90(ISLocalToGlobalMapping ltog, PetscInt, pointer :: array(:)}, integer ierr)
1621: Not Collective
1623: Input Parameters:
1624: + A - the matrix
1625: - array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
1627: Level: advanced
1629: .seealso: [](sec_fortranarrays), [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingGetIndices()`, `ISLocalToGlobalMappingRestoreIndices()`,
1630: `ISLocalToGlobalMappingGetIndicesF90()`
1631: M*/
1633: /*@C
1634: ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
1636: Not Collective
1638: Input Parameter:
1639: . ltog - local to global mapping
1641: Output Parameter:
1642: . array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
1644: Level: advanced
1646: Note:
1647: `ISLocalToGlobalMappingGetSize()` returns the length the this array
1649: .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreIndices()`,
1650: `ISLocalToGlobalMappingGetBlockIndices()`, `ISLocalToGlobalMappingRestoreBlockIndices()`
1651: @*/
1652: PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1653: {
1654: PetscFunctionBegin;
1656: PetscAssertPointer(array, 2);
1657: if (ltog->bs == 1) {
1658: *array = ltog->indices;
1659: } else {
1660: PetscInt *jj, k, i, j, n = ltog->n, bs = ltog->bs;
1661: const PetscInt *ii;
1663: PetscCall(PetscMalloc1(bs * n, &jj));
1664: *array = jj;
1665: k = 0;
1666: ii = ltog->indices;
1667: for (i = 0; i < n; i++)
1668: for (j = 0; j < bs; j++) jj[k++] = bs * ii[i] + j;
1669: }
1670: PetscFunctionReturn(PETSC_SUCCESS);
1671: }
1673: /*@C
1674: ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with `ISLocalToGlobalMappingGetIndices()`
1676: Not Collective
1678: Input Parameters:
1679: + ltog - local to global mapping
1680: - array - array of indices
1682: Level: advanced
1684: .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()`
1685: @*/
1686: PetscErrorCode ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1687: {
1688: PetscFunctionBegin;
1690: PetscAssertPointer(array, 2);
1691: PetscCheck(ltog->bs != 1 || *array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer");
1692: if (ltog->bs > 1) PetscCall(PetscFree(*(void **)array));
1693: PetscFunctionReturn(PETSC_SUCCESS);
1694: }
1696: /*@C
1697: ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block
1699: Not Collective
1701: Input Parameter:
1702: . ltog - local to global mapping
1704: Output Parameter:
1705: . array - array of indices
1707: Level: advanced
1709: .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreBlockIndices()`
1710: @*/
1711: PetscErrorCode ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1712: {
1713: PetscFunctionBegin;
1715: PetscAssertPointer(array, 2);
1716: *array = ltog->indices;
1717: PetscFunctionReturn(PETSC_SUCCESS);
1718: }
1720: /*@C
1721: ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with `ISLocalToGlobalMappingGetBlockIndices()`
1723: Not Collective
1725: Input Parameters:
1726: + ltog - local to global mapping
1727: - array - array of indices
1729: Level: advanced
1731: .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()`
1732: @*/
1733: PetscErrorCode ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt **array)
1734: {
1735: PetscFunctionBegin;
1737: PetscAssertPointer(array, 2);
1738: PetscCheck(*array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer");
1739: *array = NULL;
1740: PetscFunctionReturn(PETSC_SUCCESS);
1741: }
1743: /*@C
1744: ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1746: Not Collective
1748: Input Parameters:
1749: + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1750: . n - number of mappings to concatenate
1751: - ltogs - local to global mappings
1753: Output Parameter:
1754: . ltogcat - new mapping
1756: Level: advanced
1758: Note:
1759: This currently always returns a mapping with block size of 1
1761: Developer Notes:
1762: If all the input mapping have the same block size we could easily handle that as a special case
1764: .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`
1765: @*/
1766: PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm, PetscInt n, const ISLocalToGlobalMapping ltogs[], ISLocalToGlobalMapping *ltogcat)
1767: {
1768: PetscInt i, cnt, m, *idx;
1770: PetscFunctionBegin;
1771: PetscCheck(n >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Must have a non-negative number of mappings, given %" PetscInt_FMT, n);
1772: if (n > 0) PetscAssertPointer(ltogs, 3);
1774: PetscAssertPointer(ltogcat, 4);
1775: for (cnt = 0, i = 0; i < n; i++) {
1776: PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m));
1777: cnt += m;
1778: }
1779: PetscCall(PetscMalloc1(cnt, &idx));
1780: for (cnt = 0, i = 0; i < n; i++) {
1781: const PetscInt *subidx;
1782: PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m));
1783: PetscCall(ISLocalToGlobalMappingGetIndices(ltogs[i], &subidx));
1784: PetscCall(PetscArraycpy(&idx[cnt], subidx, m));
1785: PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogs[i], &subidx));
1786: cnt += m;
1787: }
1788: PetscCall(ISLocalToGlobalMappingCreate(comm, 1, cnt, idx, PETSC_OWN_POINTER, ltogcat));
1789: PetscFunctionReturn(PETSC_SUCCESS);
1790: }
1792: /*MC
1793: ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is
1794: used this is good for only small and moderate size problems.
1796: Options Database Key:
1797: . -islocaltoglobalmapping_type basic - select this method
1799: Level: beginner
1801: Developer Note:
1802: This stores all the mapping information on each MPI rank.
1804: .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGHASH`
1805: M*/
1806: PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)
1807: {
1808: PetscFunctionBegin;
1809: ltog->ops->globaltolocalmappingapply = ISGlobalToLocalMappingApply_Basic;
1810: ltog->ops->globaltolocalmappingsetup = ISGlobalToLocalMappingSetUp_Basic;
1811: ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic;
1812: ltog->ops->destroy = ISLocalToGlobalMappingDestroy_Basic;
1813: PetscFunctionReturn(PETSC_SUCCESS);
1814: }
1816: /*MC
1817: ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is
1818: used this is good for large memory problems.
1820: Options Database Key:
1821: . -islocaltoglobalmapping_type hash - select this method
1823: Level: beginner
1825: Note:
1826: This is selected automatically for large problems if the user does not set the type.
1828: .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGBASIC`
1829: M*/
1830: PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)
1831: {
1832: PetscFunctionBegin;
1833: ltog->ops->globaltolocalmappingapply = ISGlobalToLocalMappingApply_Hash;
1834: ltog->ops->globaltolocalmappingsetup = ISGlobalToLocalMappingSetUp_Hash;
1835: ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash;
1836: ltog->ops->destroy = ISLocalToGlobalMappingDestroy_Hash;
1837: PetscFunctionReturn(PETSC_SUCCESS);
1838: }
1840: /*@C
1841: ISLocalToGlobalMappingRegister - Registers a method for applying a global to local mapping with an `ISLocalToGlobalMapping`
1843: Not Collective
1845: Input Parameters:
1846: + sname - name of a new method
1847: - function - routine to create method context
1849: Example Usage:
1850: .vb
1851: ISLocalToGlobalMappingRegister("my_mapper", MyCreate);
1852: .ve
1854: Then, your mapping can be chosen with the procedural interface via
1855: $ ISLocalToGlobalMappingSetType(ltog, "my_mapper")
1856: or at runtime via the option
1857: $ -islocaltoglobalmapping_type my_mapper
1859: Level: advanced
1861: Note:
1862: `ISLocalToGlobalMappingRegister()` may be called multiple times to add several user-defined mappings.
1864: .seealso: [](sec_scatter), `ISLocalToGlobalMappingRegisterAll()`, `ISLocalToGlobalMappingRegisterDestroy()`, `ISLOCALTOGLOBALMAPPINGBASIC`,
1865: `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`
1866: @*/
1867: PetscErrorCode ISLocalToGlobalMappingRegister(const char sname[], PetscErrorCode (*function)(ISLocalToGlobalMapping))
1868: {
1869: PetscFunctionBegin;
1870: PetscCall(ISInitializePackage());
1871: PetscCall(PetscFunctionListAdd(&ISLocalToGlobalMappingList, sname, function));
1872: PetscFunctionReturn(PETSC_SUCCESS);
1873: }
1875: /*@C
1876: ISLocalToGlobalMappingSetType - Sets the implementation type `ISLocalToGlobalMapping` will use
1878: Logically Collective
1880: Input Parameters:
1881: + ltog - the `ISLocalToGlobalMapping` object
1882: - type - a known method
1884: Options Database Key:
1885: . -islocaltoglobalmapping_type <method> - Sets the method; use -help for a list of available methods (for instance, basic or hash)
1887: Level: intermediate
1889: Notes:
1890: See `ISLocalToGlobalMappingType` for available methods
1892: Normally, it is best to use the `ISLocalToGlobalMappingSetFromOptions()` command and
1893: then set the `ISLocalToGlobalMappingType` from the options database rather than by using
1894: this routine.
1896: Developer Notes:
1897: `ISLocalToGlobalMappingRegister()` is used to add new types to `ISLocalToGlobalMappingList` from which they
1898: are accessed by `ISLocalToGlobalMappingSetType()`.
1900: .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingGetType()`
1901: @*/
1902: PetscErrorCode ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type)
1903: {
1904: PetscBool match;
1905: PetscErrorCode (*r)(ISLocalToGlobalMapping) = NULL;
1907: PetscFunctionBegin;
1909: if (type) PetscAssertPointer(type, 2);
1911: PetscCall(PetscObjectTypeCompare((PetscObject)ltog, type, &match));
1912: if (match) PetscFunctionReturn(PETSC_SUCCESS);
1914: /* L2G maps defer type setup at globaltolocal calls, allow passing NULL here */
1915: if (type) {
1916: PetscCall(PetscFunctionListFind(ISLocalToGlobalMappingList, type, &r));
1917: PetscCheck(r, PetscObjectComm((PetscObject)ltog), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested ISLocalToGlobalMapping type %s", type);
1918: }
1919: /* Destroy the previous private LTOG context */
1920: PetscTryTypeMethod(ltog, destroy);
1921: ltog->ops->destroy = NULL;
1923: PetscCall(PetscObjectChangeTypeName((PetscObject)ltog, type));
1924: if (r) PetscCall((*r)(ltog));
1925: PetscFunctionReturn(PETSC_SUCCESS);
1926: }
1928: /*@C
1929: ISLocalToGlobalMappingGetType - Get the type of the `ISLocalToGlobalMapping`
1931: Not Collective
1933: Input Parameter:
1934: . ltog - the `ISLocalToGlobalMapping` object
1936: Output Parameter:
1937: . type - the type
1939: Level: intermediate
1941: .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`
1942: @*/
1943: PetscErrorCode ISLocalToGlobalMappingGetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType *type)
1944: {
1945: PetscFunctionBegin;
1947: PetscAssertPointer(type, 2);
1948: *type = ((PetscObject)ltog)->type_name;
1949: PetscFunctionReturn(PETSC_SUCCESS);
1950: }
1952: PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE;
1954: /*@C
1955: ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the `IS` package.
1957: Not Collective
1959: Level: advanced
1961: .seealso: [](sec_scatter), `ISRegister()`, `ISLocalToGlobalRegister()`
1962: @*/
1963: PetscErrorCode ISLocalToGlobalMappingRegisterAll(void)
1964: {
1965: PetscFunctionBegin;
1966: if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
1967: ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE;
1968: PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic));
1969: PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash));
1970: PetscFunctionReturn(PETSC_SUCCESS);
1971: }