1 #include <petsc/private/isimpl.h> /*I "petscis.h" I*/
2 #include <petsc/private/hashmapi.h>
3 #include <petscsf.h>
4 #include <petscviewer.h>
5 #include <petscbt.h>
6
7 PetscClassId IS_LTOGM_CLASSID;
8 static PetscErrorCode ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping);
9
10 typedef struct {
11 PetscInt *globals;
12 } ISLocalToGlobalMapping_Basic;
13
14 typedef struct {
15 PetscHMapI globalht;
16 } ISLocalToGlobalMapping_Hash;
17
18 /*@C
19 ISGetPointRange - Returns a description of the points in an `IS` suitable for traversal
20
21 Not Collective
22
23 Input Parameter:
24 . pointIS - The `IS` object
25
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
30
31 Level: intermediate
32
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`
45
46 .seealso: [](sec_scatter), `IS`, `ISRestorePointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()`
47 @*/
ISGetPointRange(IS pointIS,PetscInt * pStart,PetscInt * pEnd,const PetscInt * points[])48 PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt *points[])
49 {
50 PetscInt numCells, step = 1;
51 PetscBool isStride;
52
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 }
63
64 /*@C
65 ISRestorePointRange - Destroys the traversal description created with `ISGetPointRange()`
66
67 Not Collective
68
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()`
74
75 Level: intermediate
76
77 .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()`
78 @*/
ISRestorePointRange(IS pointIS,PetscInt * pStart,PetscInt * pEnd,const PetscInt * points[])79 PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt *points[])
80 {
81 PetscInt step = 1;
82 PetscBool isStride;
83
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 }
90
91 /*@
92 ISGetPointSubrange - Configures the input `IS` to be a subrange for the traversal information given
93
94 Not Collective
95
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()`
101
102 Output Parameters:
103 . subpointIS - The `IS` object now configured to be a subrange
104
105 Level: intermediate
106
107 Note:
108 The input `IS` will now respond properly to calls to `ISGetPointRange()` and return the subrange.
109
110 .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISRestorePointRange()`, `ISGetIndices()`, `ISCreateStride()`
111 @*/
ISGetPointSubrange(IS subpointIS,PetscInt pStart,PetscInt pEnd,const PetscInt points[])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 }
124
125 /*
126 Creates the global mapping information in the ISLocalToGlobalMapping structure
127
128 If the user has not selected how to handle the global to local mapping then use HASH for "large" problems
129 */
ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping)130 static PetscErrorCode ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping)
131 {
132 PetscInt i, *idx = mapping->indices, n = mapping->n, end, start;
133
134 PetscFunctionBegin;
135 if (mapping->data) PetscFunctionReturn(PETSC_SUCCESS);
136 end = 0;
137 start = PETSC_INT_MAX;
138
139 for (i = 0; i < n; i++) {
140 if (idx[i] < 0) continue;
141 if (idx[i] < start) start = idx[i];
142 if (idx[i] > end) end = idx[i];
143 }
144 if (start > end) {
145 start = 0;
146 end = -1;
147 }
148 mapping->globalstart = start;
149 mapping->globalend = end;
150 if (!((PetscObject)mapping)->type_name) {
151 if ((end - start) > PetscMax(4 * n, 1000000)) {
152 PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGHASH));
153 } else {
154 PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGBASIC));
155 }
156 }
157 PetscTryTypeMethod(mapping, globaltolocalmappingsetup);
158 PetscFunctionReturn(PETSC_SUCCESS);
159 }
160
ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping)161 static PetscErrorCode ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping)
162 {
163 PetscInt i, *idx = mapping->indices, n = mapping->n, end, start, *globals;
164 ISLocalToGlobalMapping_Basic *map;
165
166 PetscFunctionBegin;
167 start = mapping->globalstart;
168 end = mapping->globalend;
169 PetscCall(PetscNew(&map));
170 PetscCall(PetscMalloc1(end - start + 2, &globals));
171 map->globals = globals;
172 for (i = 0; i < end - start + 1; i++) globals[i] = -1;
173 for (i = 0; i < n; i++) {
174 if (idx[i] < 0) continue;
175 globals[idx[i] - start] = i;
176 }
177 mapping->data = (void *)map;
178 PetscFunctionReturn(PETSC_SUCCESS);
179 }
180
ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping)181 static PetscErrorCode ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping)
182 {
183 PetscInt i, *idx = mapping->indices, n = mapping->n;
184 ISLocalToGlobalMapping_Hash *map;
185
186 PetscFunctionBegin;
187 PetscCall(PetscNew(&map));
188 PetscCall(PetscHMapICreate(&map->globalht));
189 for (i = 0; i < n; i++) {
190 if (idx[i] < 0) continue;
191 PetscCall(PetscHMapISet(map->globalht, idx[i], i));
192 }
193 mapping->data = (void *)map;
194 PetscFunctionReturn(PETSC_SUCCESS);
195 }
196
ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping)197 static PetscErrorCode ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping)
198 {
199 ISLocalToGlobalMapping_Basic *map = (ISLocalToGlobalMapping_Basic *)mapping->data;
200
201 PetscFunctionBegin;
202 if (!map) PetscFunctionReturn(PETSC_SUCCESS);
203 PetscCall(PetscFree(map->globals));
204 PetscCall(PetscFree(mapping->data));
205 PetscFunctionReturn(PETSC_SUCCESS);
206 }
207
ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping)208 static PetscErrorCode ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping)
209 {
210 ISLocalToGlobalMapping_Hash *map = (ISLocalToGlobalMapping_Hash *)mapping->data;
211
212 PetscFunctionBegin;
213 if (!map) PetscFunctionReturn(PETSC_SUCCESS);
214 PetscCall(PetscHMapIDestroy(&map->globalht));
215 PetscCall(PetscFree(mapping->data));
216 PetscFunctionReturn(PETSC_SUCCESS);
217 }
218
ISLocalToGlobalMappingResetBlockInfo_Private(ISLocalToGlobalMapping mapping)219 static PetscErrorCode ISLocalToGlobalMappingResetBlockInfo_Private(ISLocalToGlobalMapping mapping)
220 {
221 PetscFunctionBegin;
222 PetscCall(PetscFree(mapping->info_procs));
223 PetscCall(PetscFree(mapping->info_numprocs));
224 if (mapping->info_indices) {
225 for (PetscInt i = 0; i < mapping->info_nproc; i++) PetscCall(PetscFree(mapping->info_indices[i]));
226 PetscCall(PetscFree(mapping->info_indices));
227 }
228 if (mapping->info_nodei) PetscCall(PetscFree(mapping->info_nodei[0]));
229 PetscCall(PetscFree2(mapping->info_nodec, mapping->info_nodei));
230 PetscCall(PetscSFDestroy(&mapping->multileaves_sf));
231 PetscFunctionReturn(PETSC_SUCCESS);
232 }
233
234 #define GTOLTYPE _Basic
235 #define GTOLNAME _Basic
236 #define GTOLBS mapping->bs
237 #define GTOL(g, local) \
238 do { \
239 local = map->globals[g / bs - start]; \
240 if (local >= 0) local = bs * local + (g % bs); \
241 } while (0)
242
243 #include <../src/vec/is/utils/isltog.h>
244
245 #define GTOLTYPE _Basic
246 #define GTOLNAME Block_Basic
247 #define GTOLBS 1
248 #define GTOL(g, local) \
249 do { \
250 local = map->globals[g - start]; \
251 } while (0)
252 #include <../src/vec/is/utils/isltog.h>
253
254 #define GTOLTYPE _Hash
255 #define GTOLNAME _Hash
256 #define GTOLBS mapping->bs
257 #define GTOL(g, local) \
258 do { \
259 (void)PetscHMapIGet(map->globalht, g / bs, &local); \
260 if (local >= 0) local = bs * local + (g % bs); \
261 } while (0)
262 #include <../src/vec/is/utils/isltog.h>
263
264 #define GTOLTYPE _Hash
265 #define GTOLNAME Block_Hash
266 #define GTOLBS 1
267 #define GTOL(g, local) \
268 do { \
269 (void)PetscHMapIGet(map->globalht, g, &local); \
270 } while (0)
271 #include <../src/vec/is/utils/isltog.h>
272
273 /*@
274 ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object
275
276 Not Collective
277
278 Input Parameter:
279 . ltog - local to global mapping
280
281 Output Parameter:
282 . nltog - the duplicated local to global mapping
283
284 Level: advanced
285
286 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
287 @*/
ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping * nltog)288 PetscErrorCode ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog, ISLocalToGlobalMapping *nltog)
289 {
290 ISLocalToGlobalMappingType l2gtype;
291
292 PetscFunctionBegin;
293 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
294 PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog), ltog->bs, ltog->n, ltog->indices, PETSC_COPY_VALUES, nltog));
295 PetscCall(ISLocalToGlobalMappingGetType(ltog, &l2gtype));
296 PetscCall(ISLocalToGlobalMappingSetType(*nltog, l2gtype));
297 PetscFunctionReturn(PETSC_SUCCESS);
298 }
299
300 /*@
301 ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping
302
303 Not Collective
304
305 Input Parameter:
306 . mapping - local to global mapping
307
308 Output Parameter:
309 . n - the number of entries in the local mapping, `ISLocalToGlobalMappingGetIndices()` returns an array of this length
310
311 Level: advanced
312
313 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
314 @*/
ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt * n)315 PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping, PetscInt *n)
316 {
317 PetscFunctionBegin;
318 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
319 PetscAssertPointer(n, 2);
320 *n = mapping->bs * mapping->n;
321 PetscFunctionReturn(PETSC_SUCCESS);
322 }
323
324 /*@
325 ISLocalToGlobalMappingViewFromOptions - View an `ISLocalToGlobalMapping` based on values in the options database
326
327 Collective
328
329 Input Parameters:
330 + A - the local to global mapping object
331 . obj - Optional object that provides the options prefix used for the options database query
332 - name - command line option
333
334 Level: intermediate
335
336 Note:
337 See `PetscObjectViewFromOptions()` for the available `PetscViewer` and `PetscViewerFormat`
338
339 .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingView`, `PetscObjectViewFromOptions()`, `ISLocalToGlobalMappingCreate()`
340 @*/
ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A,PetscObject obj,const char name[])341 PetscErrorCode ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A, PetscObject obj, const char name[])
342 {
343 PetscFunctionBegin;
344 PetscValidHeaderSpecific(A, IS_LTOGM_CLASSID, 1);
345 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
346 PetscFunctionReturn(PETSC_SUCCESS);
347 }
348
349 /*@
350 ISLocalToGlobalMappingView - View a local to global mapping
351
352 Collective on viewer
353
354 Input Parameters:
355 + mapping - local to global mapping
356 - viewer - viewer
357
358 Level: intermediate
359
360 .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`
361 @*/
ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer)362 PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping, PetscViewer viewer)
363 {
364 PetscBool isascii, isbinary;
365 PetscViewerFormat format;
366
367 PetscFunctionBegin;
368 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
369 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping), &viewer));
370 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
371
372 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
373 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
374 PetscCall(PetscViewerGetFormat(viewer, &format));
375 if (isascii) {
376 if (format == PETSC_VIEWER_ASCII_MATLAB) {
377 const PetscInt *idxs;
378 IS is;
379 const char *name = ((PetscObject)mapping)->name;
380 char iname[PETSC_MAX_PATH_LEN];
381
382 PetscCall(PetscSNPrintf(iname, sizeof(iname), "%sl2g", name ? name : ""));
383 PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &idxs));
384 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mapping->n * mapping->bs, idxs, PETSC_USE_POINTER, &is));
385 PetscCall(PetscObjectSetName((PetscObject)is, iname));
386 PetscCall(ISView(is, viewer));
387 PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &idxs));
388 PetscCall(ISDestroy(&is));
389 } else {
390 PetscMPIInt rank;
391
392 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mapping), &rank));
393 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mapping, viewer));
394 PetscCall(PetscViewerASCIIPushSynchronized(viewer));
395 for (PetscInt i = 0; i < mapping->n; i++) {
396 PetscInt bs = mapping->bs, g = mapping->indices[i];
397 if (bs == 1) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT " %" PetscInt_FMT "\n", rank, i, g));
398 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));
399 }
400 PetscCall(PetscViewerFlush(viewer));
401 PetscCall(PetscViewerASCIIPopSynchronized(viewer));
402 }
403 } else if (isbinary) {
404 PetscBool skipHeader;
405
406 PetscCall(PetscViewerSetUp(viewer));
407 PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
408 if (!skipHeader) {
409 PetscMPIInt size;
410 PetscInt tr[3];
411
412 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
413 tr[0] = IS_LTOGM_FILE_CLASSID;
414 tr[1] = mapping->bs;
415 tr[2] = size;
416 PetscCall(PetscViewerBinaryWrite(viewer, tr, 3, PETSC_INT));
417 PetscCall(PetscViewerBinaryWriteAll(viewer, &mapping->n, 1, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
418 }
419 /* write block indices */
420 PetscCall(PetscViewerBinaryWriteAll(viewer, mapping->indices, mapping->n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
421 }
422 PetscFunctionReturn(PETSC_SUCCESS);
423 }
424
425 /*@
426 ISLocalToGlobalMappingLoad - Loads a local-to-global mapping that has been stored in binary format.
427
428 Collective on viewer
429
430 Input Parameters:
431 + mapping - the newly loaded map, this needs to have been created with `ISLocalToGlobalMappingCreate()` or some related function before a call to `ISLocalToGlobalMappingLoad()`
432 - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
433
434 Level: intermediate
435
436 .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingView()`, `ISLocalToGlobalMappingCreate()`
437 @*/
ISLocalToGlobalMappingLoad(ISLocalToGlobalMapping mapping,PetscViewer viewer)438 PetscErrorCode ISLocalToGlobalMappingLoad(ISLocalToGlobalMapping mapping, PetscViewer viewer)
439 {
440 PetscBool isbinary, skipHeader;
441
442 PetscFunctionBegin;
443 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
444 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
445 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
446 PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Invalid viewer of type %s", ((PetscObject)viewer)->type_name);
447
448 /* reset previous data */
449 PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(mapping));
450
451 PetscCall(PetscViewerSetUp(viewer));
452 PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
453
454 /* When skipping header, it assumes bs and n have been already set */
455 if (!skipHeader) {
456 MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
457 PetscInt tr[3], nold = mapping->n, *sizes, nmaps = PETSC_DECIDE, st = 0;
458
459 PetscCall(PetscViewerBinaryRead(viewer, tr, 3, NULL, PETSC_INT));
460 PetscCheck(tr[0] == IS_LTOGM_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a local-to-global map next in file");
461
462 mapping->bs = tr[1];
463 PetscCall(PetscMalloc1(tr[2], &sizes));
464 PetscCall(PetscViewerBinaryRead(viewer, sizes, tr[2], NULL, PETSC_INT));
465
466 /* consume the input, read multiple maps per process if needed */
467 PetscCall(PetscSplitOwnership(comm, &nmaps, &tr[2]));
468 PetscCallMPI(MPI_Exscan(&nmaps, &st, 1, MPIU_INT, MPI_SUM, comm));
469 mapping->n = 0;
470 for (PetscInt i = st; i < st + nmaps; i++) mapping->n += sizes[i];
471 PetscCall(PetscFree(sizes));
472
473 if (nold != mapping->n) {
474 if (mapping->dealloc_indices) PetscCall(PetscFree(mapping->indices));
475 mapping->indices = NULL;
476 }
477 }
478
479 /* read indices */
480 if (mapping->n && !mapping->indices) {
481 PetscCall(PetscMalloc1(mapping->n, &mapping->indices));
482 mapping->dealloc_indices = PETSC_TRUE;
483 }
484 PetscCall(PetscViewerBinaryReadAll(viewer, mapping->indices, mapping->n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
485 PetscFunctionReturn(PETSC_SUCCESS);
486 }
487
488 /*@
489 ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
490 ordering and a global parallel ordering.
491
492 Not Collective
493
494 Input Parameter:
495 . is - index set containing the global numbers for each local number
496
497 Output Parameter:
498 . mapping - new mapping data structure
499
500 Level: advanced
501
502 Note:
503 the block size of the `IS` determines the block size of the mapping
504
505 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetFromOptions()`
506 @*/
ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping * mapping)507 PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is, ISLocalToGlobalMapping *mapping)
508 {
509 PetscInt n, bs;
510 const PetscInt *indices;
511 MPI_Comm comm;
512 PetscBool isblock;
513
514 PetscFunctionBegin;
515 PetscValidHeaderSpecific(is, IS_CLASSID, 1);
516 PetscAssertPointer(mapping, 2);
517
518 PetscCall(PetscObjectGetComm((PetscObject)is, &comm));
519 PetscCall(ISGetLocalSize(is, &n));
520 PetscCall(PetscObjectTypeCompare((PetscObject)is, ISBLOCK, &isblock));
521 if (!isblock) {
522 PetscCall(ISGetIndices(is, &indices));
523 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, n, indices, PETSC_COPY_VALUES, mapping));
524 PetscCall(ISRestoreIndices(is, &indices));
525 } else {
526 PetscCall(ISGetBlockSize(is, &bs));
527 PetscCall(ISBlockGetIndices(is, &indices));
528 PetscCall(ISLocalToGlobalMappingCreate(comm, bs, n / bs, indices, PETSC_COPY_VALUES, mapping));
529 PetscCall(ISBlockRestoreIndices(is, &indices));
530 }
531 PetscFunctionReturn(PETSC_SUCCESS);
532 }
533
534 /*@
535 ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n) ordering and a global parallel ordering induced by a star forest.
536
537 Collective
538
539 Input Parameters:
540 + sf - star forest mapping contiguous local indices to (rank, offset)
541 - start - first global index on this process, or `PETSC_DECIDE` to compute contiguous global numbering automatically
542
543 Output Parameter:
544 . mapping - new mapping data structure
545
546 Level: advanced
547
548 Note:
549 If a process calls this function with `start` = `PETSC_DECIDE` then all processes must, otherwise the program will hang.
550
551 .seealso: [](sec_scatter), `PetscSF`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`
552 @*/
ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping * mapping)553 PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf, PetscInt start, ISLocalToGlobalMapping *mapping)
554 {
555 PetscInt i, maxlocal, nroots, nleaves, *globals, *ltog;
556 MPI_Comm comm;
557
558 PetscFunctionBegin;
559 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
560 PetscAssertPointer(mapping, 3);
561 PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
562 PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
563 if (start == PETSC_DECIDE) {
564 start = 0;
565 PetscCallMPI(MPI_Exscan(&nroots, &start, 1, MPIU_INT, MPI_SUM, comm));
566 } else PetscCheck(start >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "start must be nonnegative or PETSC_DECIDE");
567 PetscCall(PetscSFGetLeafRange(sf, NULL, &maxlocal));
568 ++maxlocal;
569 PetscCall(PetscMalloc1(nroots, &globals));
570 PetscCall(PetscMalloc1(maxlocal, <og));
571 for (i = 0; i < nroots; i++) globals[i] = start + i;
572 for (i = 0; i < maxlocal; i++) ltog[i] = -1;
573 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globals, ltog, MPI_REPLACE));
574 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globals, ltog, MPI_REPLACE));
575 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, maxlocal, ltog, PETSC_OWN_POINTER, mapping));
576 PetscCall(PetscFree(globals));
577 PetscFunctionReturn(PETSC_SUCCESS);
578 }
579
580 /*@
581 ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping
582
583 Not Collective
584
585 Input Parameters:
586 + mapping - mapping data structure
587 - bs - the blocksize
588
589 Level: advanced
590
591 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`
592 @*/
ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs)593 PetscErrorCode ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping, PetscInt bs)
594 {
595 PetscInt *nid;
596 const PetscInt *oid;
597 PetscInt i, cn, on, obs, nn;
598
599 PetscFunctionBegin;
600 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
601 PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid block size %" PetscInt_FMT, bs);
602 if (bs == mapping->bs) PetscFunctionReturn(PETSC_SUCCESS);
603 on = mapping->n;
604 obs = mapping->bs;
605 oid = mapping->indices;
606 nn = (on * obs) / bs;
607 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);
608
609 PetscCall(PetscMalloc1(nn, &nid));
610 PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &oid));
611 for (i = 0; i < nn; i++) {
612 PetscInt j;
613 for (j = 0, cn = 0; j < bs - 1; j++) {
614 if (oid[i * bs + j] < 0) {
615 cn++;
616 continue;
617 }
618 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]);
619 }
620 if (oid[i * bs + j] < 0) cn++;
621 if (cn) {
622 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);
623 nid[i] = -1;
624 } else {
625 nid[i] = oid[i * bs] / bs;
626 }
627 }
628 PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &oid));
629
630 mapping->n = nn;
631 mapping->bs = bs;
632 PetscCall(PetscFree(mapping->indices));
633 mapping->indices = nid;
634 mapping->globalstart = 0;
635 mapping->globalend = 0;
636
637 /* reset the cached information */
638 PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(mapping));
639 PetscTryTypeMethod(mapping, destroy);
640 PetscFunctionReturn(PETSC_SUCCESS);
641 }
642
643 /*@
644 ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping
645 ordering and a global parallel ordering.
646
647 Not Collective
648
649 Input Parameter:
650 . mapping - mapping data structure
651
652 Output Parameter:
653 . bs - the blocksize
654
655 Level: advanced
656
657 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`
658 @*/
ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt * bs)659 PetscErrorCode ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping, PetscInt *bs)
660 {
661 PetscFunctionBegin;
662 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
663 *bs = mapping->bs;
664 PetscFunctionReturn(PETSC_SUCCESS);
665 }
666
667 /*@
668 ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
669 ordering and a global parallel ordering.
670
671 Not Collective, but communicator may have more than one process
672
673 Input Parameters:
674 + comm - MPI communicator
675 . bs - the block size
676 . n - the number of local elements divided by the block size, or equivalently the number of block indices
677 . 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
678 - mode - see PetscCopyMode
679
680 Output Parameter:
681 . mapping - new mapping data structure
682
683 Level: advanced
684
685 Notes:
686 There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1
687
688 For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType`
689 of `ISLOCALTOGLOBALMAPPINGBASIC` will be used; this uses more memory but is faster; this approach is not scalable for extremely large mappings.
690
691 For large problems `ISLOCALTOGLOBALMAPPINGHASH` is used, this is scalable.
692 Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option
693 `-islocaltoglobalmapping_type` <`basic`,`hash`> to control which is used.
694
695 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`,
696 `ISLOCALTOGLOBALMAPPINGBASIC`, `ISLOCALTOGLOBALMAPPINGHASH`
697 `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType`
698 @*/
ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping * mapping)699 PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm comm, PetscInt bs, PetscInt n, const PetscInt indices[], PetscCopyMode mode, ISLocalToGlobalMapping *mapping)
700 {
701 PetscInt *in;
702
703 PetscFunctionBegin;
704 if (n) PetscAssertPointer(indices, 4);
705 PetscAssertPointer(mapping, 6);
706
707 *mapping = NULL;
708 PetscCall(ISInitializePackage());
709
710 PetscCall(PetscHeaderCreate(*mapping, IS_LTOGM_CLASSID, "ISLocalToGlobalMapping", "Local to global mapping", "IS", comm, ISLocalToGlobalMappingDestroy, ISLocalToGlobalMappingView));
711 (*mapping)->n = n;
712 (*mapping)->bs = bs;
713 if (mode == PETSC_COPY_VALUES) {
714 PetscCall(PetscMalloc1(n, &in));
715 PetscCall(PetscArraycpy(in, indices, n));
716 (*mapping)->indices = in;
717 (*mapping)->dealloc_indices = PETSC_TRUE;
718 } else if (mode == PETSC_OWN_POINTER) {
719 (*mapping)->indices = (PetscInt *)indices;
720 (*mapping)->dealloc_indices = PETSC_TRUE;
721 } else if (mode == PETSC_USE_POINTER) {
722 (*mapping)->indices = (PetscInt *)indices;
723 } else SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid mode %d", mode);
724 PetscFunctionReturn(PETSC_SUCCESS);
725 }
726
727 PetscFunctionList ISLocalToGlobalMappingList = NULL;
728
729 /*@
730 ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database.
731
732 Not Collective
733
734 Input Parameter:
735 . mapping - mapping data structure
736
737 Options Database Key:
738 . -islocaltoglobalmapping_type - <basic,hash> nonscalable and scalable versions
739
740 Level: advanced
741
742 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`,
743 `ISLocalToGlobalMappingCreateIS()`, `ISLOCALTOGLOBALMAPPINGBASIC`,
744 `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType`
745 @*/
ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)746 PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping)
747 {
748 char type[256];
749 ISLocalToGlobalMappingType defaulttype = "Not set";
750 PetscBool flg;
751
752 PetscFunctionBegin;
753 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
754 PetscCall(ISLocalToGlobalMappingRegisterAll());
755 PetscObjectOptionsBegin((PetscObject)mapping);
756 PetscCall(PetscOptionsFList("-islocaltoglobalmapping_type", "ISLocalToGlobalMapping method", "ISLocalToGlobalMappingSetType", ISLocalToGlobalMappingList, ((PetscObject)mapping)->type_name ? ((PetscObject)mapping)->type_name : defaulttype, type, 256, &flg));
757 if (flg) PetscCall(ISLocalToGlobalMappingSetType(mapping, type));
758 PetscOptionsEnd();
759 PetscFunctionReturn(PETSC_SUCCESS);
760 }
761
762 /*@
763 ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
764 ordering and a global parallel ordering.
765
766 Not Collective
767
768 Input Parameter:
769 . mapping - mapping data structure
770
771 Level: advanced
772
773 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`
774 @*/
ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping * mapping)775 PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping)
776 {
777 PetscFunctionBegin;
778 if (!*mapping) PetscFunctionReturn(PETSC_SUCCESS);
779 PetscValidHeaderSpecific(*mapping, IS_LTOGM_CLASSID, 1);
780 if (--((PetscObject)*mapping)->refct > 0) {
781 *mapping = NULL;
782 PetscFunctionReturn(PETSC_SUCCESS);
783 }
784 if ((*mapping)->dealloc_indices) PetscCall(PetscFree((*mapping)->indices));
785 PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(*mapping));
786 PetscTryTypeMethod(*mapping, destroy);
787 PetscCall(PetscHeaderDestroy(mapping));
788 PetscFunctionReturn(PETSC_SUCCESS);
789 }
790
791 /*@
792 ISLocalToGlobalMappingApplyIS - Creates from an `IS` in the local numbering
793 a new index set using the global numbering defined in an `ISLocalToGlobalMapping`
794 context.
795
796 Collective
797
798 Input Parameters:
799 + mapping - mapping between local and global numbering
800 - is - index set in local numbering
801
802 Output Parameter:
803 . newis - index set in global numbering
804
805 Level: advanced
806
807 Note:
808 The output `IS` will have the same communicator as the input `IS` as well as the same block size.
809
810 .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
811 `ISLocalToGlobalMappingDestroy()`, `ISGlobalToLocalMappingApply()`
812 @*/
ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS * newis)813 PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping, IS is, IS *newis)
814 {
815 PetscInt n, *idxout, bs;
816 const PetscInt *idxin;
817
818 PetscFunctionBegin;
819 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
820 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
821 PetscAssertPointer(newis, 3);
822
823 PetscCall(ISGetLocalSize(is, &n));
824 PetscCall(ISGetBlockSize(is, &bs));
825 PetscCall(ISGetIndices(is, &idxin));
826 PetscCall(PetscMalloc1(n, &idxout));
827 PetscCall(ISLocalToGlobalMappingApply(mapping, n, idxin, idxout));
828 PetscCall(ISRestoreIndices(is, &idxin));
829 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), n, idxout, PETSC_OWN_POINTER, newis));
830 PetscCall(ISSetBlockSize(*newis, bs));
831 PetscFunctionReturn(PETSC_SUCCESS);
832 }
833
834 /*@
835 ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
836 and converts them to the global numbering.
837
838 Not Collective
839
840 Input Parameters:
841 + mapping - the local to global mapping context
842 . N - number of integers
843 - in - input indices in local numbering
844
845 Output Parameter:
846 . out - indices in global numbering
847
848 Level: advanced
849
850 Note:
851 The `in` and `out` array parameters may be identical.
852
853 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`,
854 `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`,
855 `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()`
856 @*/
ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])857 PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[])
858 {
859 PetscInt i, bs, Nmax;
860
861 PetscFunctionBegin;
862 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
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 }
888
889 /*@
890 ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering
891
892 Not Collective
893
894 Input Parameters:
895 + mapping - the local to global mapping context
896 . N - number of integers
897 - in - input indices in local block numbering
898
899 Output Parameter:
900 . out - indices in global block numbering
901
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.
905
906 Level: advanced
907
908 Note:
909 The `in` and `out` array parameters may be identical.
910
911 .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`,
912 `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`,
913 `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()`
914 @*/
ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[])915 PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[])
916 {
917 PetscInt i, Nmax;
918 const PetscInt *idx;
919
920 PetscFunctionBegin;
921 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
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 }
934
935 /*@
936 ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
937 specified with a global numbering.
938
939 Not Collective
940
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
947
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.
955
956 Level: advanced
957
958 Notes:
959 Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical.
960
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.
965
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`.
969
970 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`,
971 `ISLocalToGlobalMappingDestroy()`
972 @*/
ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,PetscInt n,const PetscInt idx[],PetscInt * nout,PetscInt idxout[])973 PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[])
974 {
975 PetscFunctionBegin;
976 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
977 if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping));
978 PetscUseTypeMethod(mapping, globaltolocalmappingapply, type, n, idx, nout, idxout);
979 PetscFunctionReturn(PETSC_SUCCESS);
980 }
981
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.
986
987 Not Collective
988
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
994
995 Output Parameter:
996 . newis - index set in local numbering
997
998 Level: advanced
999
1000 Notes:
1001 The output `IS` will be sequential, as it encodes a purely local operation
1002
1003 If `type` is `IS_GTOLM_MASK`, `newis` will have the same block size as `is`
1004
1005 .seealso: [](sec_scatter), `ISGlobalToLocalMapping`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
1006 `ISLocalToGlobalMappingDestroy()`
1007 @*/
ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,IS is,IS * newis)1008 PetscErrorCode ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, IS is, IS *newis)
1009 {
1010 PetscInt n, nout, *idxout, bs;
1011 const PetscInt *idxin;
1012
1013 PetscFunctionBegin;
1014 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1015 PetscValidHeaderSpecific(is, IS_CLASSID, 3);
1016 PetscAssertPointer(newis, 4);
1017
1018 PetscCall(ISGetLocalSize(is, &n));
1019 PetscCall(ISGetIndices(is, &idxin));
1020 if (type == IS_GTOLM_MASK) {
1021 PetscCall(PetscMalloc1(n, &idxout));
1022 } else {
1023 PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, NULL));
1024 PetscCall(PetscMalloc1(nout, &idxout));
1025 }
1026 PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, idxout));
1027 PetscCall(ISRestoreIndices(is, &idxin));
1028 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nout, idxout, PETSC_OWN_POINTER, newis));
1029 if (type == IS_GTOLM_MASK) {
1030 PetscCall(ISGetBlockSize(is, &bs));
1031 PetscCall(ISSetBlockSize(*newis, bs));
1032 }
1033 PetscFunctionReturn(PETSC_SUCCESS);
1034 }
1035
1036 /*@
1037 ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers
1038 specified with a block global numbering.
1039
1040 Not Collective
1041
1042 Input Parameters:
1043 + mapping - mapping between local and global numbering
1044 . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them)
1045 `IS_GTOLM_DROP` - drops the indices with no local value from the output list
1046 . n - number of global indices to map
1047 - idx - global indices to map
1048
1049 Output Parameters:
1050 + nout - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n)
1051 - idxout - local index of each global index, one must pass in an array long enough
1052 to hold all the indices. You can call `ISGlobalToLocalMappingApplyBlock()` with
1053 idxout == NULL to determine the required length (returned in nout)
1054 and then allocate the required space and call `ISGlobalToLocalMappingApplyBlock()`
1055 a second time to set the values.
1056
1057 Level: advanced
1058
1059 Notes:
1060 Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical.
1061
1062 For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of
1063 `ISLOCALTOGLOBALMAPPINGBASIC` will be used;
1064 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.
1065 Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used.
1066
1067 Developer Notes:
1068 The manual page states that `idx` and `idxout` may be identical but the calling
1069 sequence declares `idx` as const so it cannot be the same as `idxout`.
1070
1071 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`,
1072 `ISLocalToGlobalMappingDestroy()`
1073 @*/
ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingMode type,PetscInt n,const PetscInt idx[],PetscInt * nout,PetscInt idxout[])1074 PetscErrorCode ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[])
1075 {
1076 PetscFunctionBegin;
1077 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1078 if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping));
1079 PetscUseTypeMethod(mapping, globaltolocalmappingapplyblock, type, n, idx, nout, idxout);
1080 PetscFunctionReturn(PETSC_SUCCESS);
1081 }
1082
1083 /*@C
1084 ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information
1085
1086 Collective the first time it is called
1087
1088 Input Parameter:
1089 . mapping - the mapping from local to global indexing
1090
1091 Output Parameters:
1092 + nproc - number of processes that are connected to the calling process
1093 . procs - neighboring processes
1094 . numprocs - number of block indices for each process
1095 - indices - block indices (in local numbering) shared with neighbors (sorted by global numbering)
1096
1097 Level: advanced
1098
1099 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1100 `ISLocalToGlobalMappingRestoreBlockInfo()`, `ISLocalToGlobalMappingGetBlockMultiLeavesSF()`
1101 @*/
ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt * nproc,PetscInt * procs[],PetscInt * numprocs[],PetscInt ** indices[])1102 PetscErrorCode ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1103 {
1104 PetscFunctionBegin;
1105 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1106 PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping));
1107 if (nproc) *nproc = mapping->info_nproc;
1108 if (procs) *procs = mapping->info_procs;
1109 if (numprocs) *numprocs = mapping->info_numprocs;
1110 if (indices) *indices = mapping->info_indices;
1111 PetscFunctionReturn(PETSC_SUCCESS);
1112 }
1113
1114 /*@C
1115 ISLocalToGlobalMappingGetBlockNodeInfo - Gets the neighbor information for each local block index
1116
1117 Collective the first time it is called
1118
1119 Input Parameter:
1120 . mapping - the mapping from local to global indexing
1121
1122 Output Parameters:
1123 + n - number of local block nodes
1124 . n_procs - an array storing the number of processes for each local block node (including self)
1125 - procs - the processes' rank for each local block node (sorted, self is first)
1126
1127 Level: advanced
1128
1129 Notes:
1130 The user needs to call `ISLocalToGlobalMappingRestoreBlockNodeInfo()` when the data is no longer needed.
1131 The information returned by this function complements that of `ISLocalToGlobalMappingGetBlockInfo()`.
1132 The latter only provides local information, and the neighboring information
1133 cannot be inferred in the general case, unless the mapping is locally one-to-one on each process.
1134
1135 .seealso: `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1136 `ISLocalToGlobalMappingGetBlockInfo()`, `ISLocalToGlobalMappingRestoreBlockNodeInfo()`, `ISLocalToGlobalMappingGetNodeInfo()`
1137 @*/
ISLocalToGlobalMappingGetBlockNodeInfo(ISLocalToGlobalMapping mapping,PetscInt * n,PetscInt * n_procs[],PetscInt ** procs[])1138 PetscErrorCode ISLocalToGlobalMappingGetBlockNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1139 {
1140 PetscFunctionBegin;
1141 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1142 PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping));
1143 if (n) *n = mapping->n;
1144 if (n_procs) *n_procs = mapping->info_nodec;
1145 if (procs) *procs = mapping->info_nodei;
1146 PetscFunctionReturn(PETSC_SUCCESS);
1147 }
1148
1149 /*@C
1150 ISLocalToGlobalMappingRestoreBlockNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockNodeInfo()`
1151
1152 Not Collective
1153
1154 Input Parameters:
1155 + mapping - the mapping from local to global indexing
1156 . n - number of local block nodes
1157 . n_procs - an array storing the number of processes for each local block nodes (including self)
1158 - procs - the processes' rank for each local block node (sorted, self is first)
1159
1160 Level: advanced
1161
1162 .seealso: `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1163 `ISLocalToGlobalMappingGetBlockNodeInfo()`
1164 @*/
ISLocalToGlobalMappingRestoreBlockNodeInfo(ISLocalToGlobalMapping mapping,PetscInt * n,PetscInt * n_procs[],PetscInt ** procs[])1165 PetscErrorCode ISLocalToGlobalMappingRestoreBlockNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1166 {
1167 PetscFunctionBegin;
1168 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1169 if (n) *n = 0;
1170 if (n_procs) *n_procs = NULL;
1171 if (procs) *procs = NULL;
1172 PetscFunctionReturn(PETSC_SUCCESS);
1173 }
1174
1175 /*@C
1176 ISLocalToGlobalMappingGetBlockMultiLeavesSF - Get the star-forest to communicate multi-leaf block data
1177
1178 Collective the first time it is called
1179
1180 Input Parameter:
1181 . mapping - the mapping from local to global indexing
1182
1183 Output Parameter:
1184 . mlsf - the `PetscSF`
1185
1186 Level: advanced
1187
1188 Notes:
1189 The returned star forest is suitable to exchange local information with other processes sharing the same global block index.
1190 For example, suppose a mapping with two processes has been created with
1191 .vb
1192 rank 0 global block indices: [0, 1, 2]
1193 rank 1 global block indices: [2, 3, 4]
1194 .ve
1195 and we want to share the local information
1196 .vb
1197 rank 0 data: [-1, -2, -3]
1198 rank 1 data: [1, 2, 3]
1199 .ve
1200 then, the broadcasting action of `mlsf` will allow to collect
1201 .vb
1202 rank 0 mlleafdata: [-1, -2, -3, 3]
1203 rank 1 mlleafdata: [-3, 3, 1, 2]
1204 .ve
1205 Use ``ISLocalToGlobalMappingGetBlockNodeInfo()`` to index into the multi-leaf data.
1206
1207 .seealso: [](sec_scatter), `ISLocalToGlobalMappingGetBlockNodeInfo()`, `PetscSF`
1208 @*/
ISLocalToGlobalMappingGetBlockMultiLeavesSF(ISLocalToGlobalMapping mapping,PetscSF * mlsf)1209 PetscErrorCode ISLocalToGlobalMappingGetBlockMultiLeavesSF(ISLocalToGlobalMapping mapping, PetscSF *mlsf)
1210 {
1211 PetscFunctionBegin;
1212 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1213 PetscAssertPointer(mlsf, 2);
1214 PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping));
1215 *mlsf = mapping->multileaves_sf;
1216 PetscFunctionReturn(PETSC_SUCCESS);
1217 }
1218
ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping mapping)1219 static PetscErrorCode ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping mapping)
1220 {
1221 PetscSF sf, sf2, imsf, msf;
1222 MPI_Comm comm;
1223 const PetscSFNode *sfnode;
1224 PetscSFNode *newsfnode;
1225 PetscLayout layout;
1226 PetscHMapI neighs;
1227 PetscHashIter iter;
1228 PetscBool missing;
1229 const PetscInt *gidxs, *rootdegree;
1230 PetscInt *mask, *mrootdata, *leafdata, *newleafdata, *leafrd, *tmpg;
1231 PetscInt nroots, nleaves, newnleaves, bs, i, j, m, mnroots, p;
1232 PetscMPIInt rank, size;
1233
1234 PetscFunctionBegin;
1235 if (mapping->multileaves_sf) PetscFunctionReturn(PETSC_SUCCESS);
1236 PetscCall(PetscObjectGetComm((PetscObject)mapping, &comm));
1237 PetscCallMPI(MPI_Comm_size(comm, &size));
1238 PetscCallMPI(MPI_Comm_rank(comm, &rank));
1239
1240 /* Get mapping indices */
1241 PetscCall(ISLocalToGlobalMappingGetBlockSize(mapping, &bs));
1242 PetscCall(ISLocalToGlobalMappingGetBlockIndices(mapping, &gidxs));
1243 PetscCall(ISLocalToGlobalMappingGetSize(mapping, &nleaves));
1244 nleaves /= bs;
1245
1246 /* Create layout for global indices */
1247 for (i = 0, m = 0; i < nleaves; i++) m = PetscMax(m, gidxs[i]);
1248 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &m, 1, MPIU_INT, MPI_MAX, comm));
1249 PetscCall(PetscLayoutCreate(comm, &layout));
1250 PetscCall(PetscLayoutSetSize(layout, m + 1));
1251 PetscCall(PetscLayoutSetUp(layout));
1252
1253 /* Create SF to share global indices */
1254 PetscCall(PetscSFCreate(comm, &sf));
1255 PetscCall(PetscSFSetGraphLayout(sf, layout, nleaves, NULL, PETSC_OWN_POINTER, gidxs));
1256 PetscCall(PetscSFSetUp(sf));
1257 PetscCall(PetscLayoutDestroy(&layout));
1258
1259 /* communicate root degree to leaves */
1260 PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, &sfnode));
1261 PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree));
1262 PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree));
1263 for (i = 0, mnroots = 0; i < nroots; i++) mnroots += rootdegree[i];
1264 PetscCall(PetscMalloc3(2 * PetscMax(mnroots, nroots), &mrootdata, 2 * nleaves, &leafdata, nleaves, &leafrd));
1265 for (i = 0, m = 0; i < nroots; i++) {
1266 mrootdata[2 * i + 0] = rootdegree[i];
1267 mrootdata[2 * i + 1] = m;
1268 m += rootdegree[i];
1269 }
1270 PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, mrootdata, leafdata, MPI_REPLACE));
1271 PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, mrootdata, leafdata, MPI_REPLACE));
1272
1273 /* allocate enough space to store ranks */
1274 for (i = 0, newnleaves = 0; i < nleaves; i++) {
1275 newnleaves += leafdata[2 * i];
1276 leafrd[i] = leafdata[2 * i];
1277 }
1278
1279 /* create new SF nodes to collect multi-root data at leaves */
1280 PetscCall(PetscMalloc1(newnleaves, &newsfnode));
1281 for (i = 0, m = 0; i < nleaves; i++) {
1282 for (j = 0; j < leafrd[i]; j++) {
1283 newsfnode[m].rank = sfnode[i].rank;
1284 newsfnode[m].index = leafdata[2 * i + 1] + j;
1285 m++;
1286 }
1287 }
1288
1289 /* gather ranks at multi roots */
1290 for (i = 0; i < mnroots; i++) mrootdata[i] = -1;
1291 for (i = 0; i < nleaves; i++) leafdata[i] = rank;
1292
1293 PetscCall(PetscSFGatherBegin(sf, MPIU_INT, leafdata, mrootdata));
1294 PetscCall(PetscSFGatherEnd(sf, MPIU_INT, leafdata, mrootdata));
1295
1296 /* from multi-roots to multi-leaves */
1297 PetscCall(PetscSFCreate(comm, &sf2));
1298 PetscCall(PetscSFSetGraph(sf2, mnroots, newnleaves, NULL, PETSC_OWN_POINTER, newsfnode, PETSC_OWN_POINTER));
1299 PetscCall(PetscSFSetUp(sf2));
1300
1301 /* broadcast multi-root data to multi-leaves */
1302 PetscCall(PetscMalloc1(newnleaves, &newleafdata));
1303 PetscCall(PetscSFBcastBegin(sf2, MPIU_INT, mrootdata, newleafdata, MPI_REPLACE));
1304 PetscCall(PetscSFBcastEnd(sf2, MPIU_INT, mrootdata, newleafdata, MPI_REPLACE));
1305
1306 /* sort sharing ranks */
1307 for (i = 0, m = 0; i < nleaves; i++) {
1308 PetscCall(PetscSortInt(leafrd[i], newleafdata + m));
1309 m += leafrd[i];
1310 }
1311
1312 /* Number of neighbors and their ranks */
1313 PetscCall(PetscHMapICreate(&neighs));
1314 for (i = 0; i < newnleaves; i++) PetscCall(PetscHMapIPut(neighs, newleafdata[i], &iter, &missing));
1315 PetscCall(PetscHMapIGetSize(neighs, &mapping->info_nproc));
1316 PetscCall(PetscMalloc1(mapping->info_nproc, &mapping->info_procs));
1317 PetscCall(PetscHMapIGetKeys(neighs, (i = 0, &i), mapping->info_procs));
1318 for (i = 0; i < mapping->info_nproc; i++) { /* put info for self first */
1319 if (mapping->info_procs[i] == rank) {
1320 PetscInt newr = mapping->info_procs[0];
1321
1322 mapping->info_procs[0] = rank;
1323 mapping->info_procs[i] = newr;
1324 break;
1325 }
1326 }
1327 if (mapping->info_nproc) PetscCall(PetscSortInt(mapping->info_nproc - 1, mapping->info_procs + 1));
1328 PetscCall(PetscHMapIDestroy(&neighs));
1329
1330 /* collect info data */
1331 PetscCall(PetscMalloc1(mapping->info_nproc, &mapping->info_numprocs));
1332 PetscCall(PetscMalloc1(mapping->info_nproc, &mapping->info_indices));
1333 for (i = 0; i < mapping->info_nproc; i++) mapping->info_indices[i] = NULL;
1334
1335 PetscCall(PetscMalloc1(nleaves, &mask));
1336 PetscCall(PetscMalloc1(nleaves, &tmpg));
1337 for (p = 0; p < mapping->info_nproc; p++) {
1338 PetscInt *tmp, trank = mapping->info_procs[p];
1339
1340 PetscCall(PetscMemzero(mask, nleaves * sizeof(*mask)));
1341 for (i = 0, m = 0; i < nleaves; i++) {
1342 for (j = 0; j < leafrd[i]; j++) {
1343 if (newleafdata[m] == trank) mask[i]++;
1344 if (!p && newleafdata[m] != rank) mask[i]++;
1345 m++;
1346 }
1347 }
1348 for (i = 0, m = 0; i < nleaves; i++)
1349 if (mask[i] > (!p ? 1 : 0)) m++;
1350
1351 PetscCall(PetscMalloc1(m, &tmp));
1352 for (i = 0, m = 0; i < nleaves; i++)
1353 if (mask[i] > (!p ? 1 : 0)) {
1354 tmp[m] = i;
1355 tmpg[m] = gidxs[i];
1356 m++;
1357 }
1358 PetscCall(PetscSortIntWithArray(m, tmpg, tmp));
1359 mapping->info_indices[p] = tmp;
1360 mapping->info_numprocs[p] = m;
1361 }
1362
1363 /* Node info */
1364 PetscCall(PetscMalloc2(nleaves, &mapping->info_nodec, nleaves + 1, &mapping->info_nodei));
1365 PetscCall(PetscArraycpy(mapping->info_nodec, leafrd, nleaves));
1366 PetscCall(PetscMalloc1(newnleaves, &mapping->info_nodei[0]));
1367 for (i = 0; i < nleaves - 1; i++) mapping->info_nodei[i + 1] = mapping->info_nodei[i] + mapping->info_nodec[i];
1368 PetscCall(PetscArraycpy(mapping->info_nodei[0], newleafdata, newnleaves));
1369
1370 /* Create SF from leaves to multi-leaves */
1371 PetscCall(PetscSFGetMultiSF(sf, &msf));
1372 PetscCall(PetscSFCreateInverseSF(msf, &imsf));
1373 PetscCall(PetscSFCompose(imsf, sf2, &mapping->multileaves_sf));
1374 PetscCall(PetscSFDestroy(&imsf));
1375 PetscCall(PetscSFDestroy(&sf));
1376 PetscCall(PetscSFDestroy(&sf2));
1377
1378 PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(mapping, &gidxs));
1379 PetscCall(PetscFree(tmpg));
1380 PetscCall(PetscFree(mask));
1381 PetscCall(PetscFree3(mrootdata, leafdata, leafrd));
1382 PetscCall(PetscFree(newleafdata));
1383 PetscFunctionReturn(PETSC_SUCCESS);
1384 }
1385
1386 /*@C
1387 ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockInfo()`
1388
1389 Not Collective
1390
1391 Input Parameters:
1392 + mapping - the mapping from local to global indexing
1393 . nproc - number of processes that are connected to the calling process
1394 . procs - neighboring processes
1395 . numprocs - number of block indices for each process
1396 - indices - block indices (in local numbering) shared with neighbors (sorted by global numbering)
1397
1398 Level: advanced
1399
1400 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1401 `ISLocalToGlobalMappingGetInfo()`
1402 @*/
ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt * nproc,PetscInt * procs[],PetscInt * numprocs[],PetscInt ** indices[])1403 PetscErrorCode ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1404 {
1405 PetscFunctionBegin;
1406 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1407 if (nproc) *nproc = 0;
1408 if (procs) *procs = NULL;
1409 if (numprocs) *numprocs = NULL;
1410 if (indices) *indices = NULL;
1411 PetscFunctionReturn(PETSC_SUCCESS);
1412 }
1413
1414 /*@C
1415 ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each process
1416
1417 Collective the first time it is called
1418
1419 Input Parameter:
1420 . mapping - the mapping from local to global indexing
1421
1422 Output Parameters:
1423 + nproc - number of processes that are connected to the calling process
1424 . procs - neighboring processes
1425 . numprocs - number of indices for each process
1426 - indices - indices (in local numbering) shared with neighbors (sorted by global numbering)
1427
1428 Level: advanced
1429
1430 Note:
1431 The user needs to call `ISLocalToGlobalMappingRestoreInfo()` when the data is no longer needed.
1432
1433 Fortran Notes:
1434 There is no `ISLocalToGlobalMappingRestoreInfo()` in Fortran. You must make sure that
1435 `procs`[], `numprocs`[] and `indices`[][] are large enough arrays, either by allocating them
1436 dynamically or defining static ones large enough.
1437
1438 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1439 `ISLocalToGlobalMappingRestoreInfo()`, `ISLocalToGlobalMappingGetNodeInfo()`
1440 @*/
ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt * nproc,PetscInt * procs[],PetscInt * numprocs[],PetscInt ** indices[])1441 PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1442 {
1443 PetscInt **bindices = NULL, *bnumprocs = NULL, bs, i, j, k, n, *bprocs;
1444
1445 PetscFunctionBegin;
1446 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1447 bs = mapping->bs;
1448 PetscCall(ISLocalToGlobalMappingGetBlockInfo(mapping, &n, &bprocs, &bnumprocs, &bindices));
1449 if (bs > 1) { /* we need to expand the cached info */
1450 if (indices) PetscCall(PetscCalloc1(n, indices));
1451 if (numprocs) PetscCall(PetscCalloc1(n, numprocs));
1452 if (indices || numprocs) {
1453 for (i = 0; i < n; i++) {
1454 if (indices) {
1455 PetscCall(PetscMalloc1(bs * bnumprocs[i], &(*indices)[i]));
1456 for (j = 0; j < bnumprocs[i]; j++) {
1457 for (k = 0; k < bs; k++) (*indices)[i][j * bs + k] = bs * bindices[i][j] + k;
1458 }
1459 }
1460 if (numprocs) (*numprocs)[i] = bnumprocs[i] * bs;
1461 }
1462 }
1463 } else {
1464 if (numprocs) *numprocs = bnumprocs;
1465 if (indices) *indices = bindices;
1466 }
1467 if (nproc) *nproc = n;
1468 if (procs) *procs = bprocs;
1469 PetscFunctionReturn(PETSC_SUCCESS);
1470 }
1471
1472 /*@C
1473 ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetInfo()`
1474
1475 Not Collective
1476
1477 Input Parameters:
1478 + mapping - the mapping from local to global indexing
1479 . nproc - number of processes that are connected to the calling process
1480 . procs - neighboring processes
1481 . numprocs - number of indices for each process
1482 - indices - indices (in local numbering) shared with neighbors (sorted by global numbering)
1483
1484 Level: advanced
1485
1486 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1487 `ISLocalToGlobalMappingGetInfo()`
1488 @*/
ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt * nproc,PetscInt * procs[],PetscInt * numprocs[],PetscInt ** indices[])1489 PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[])
1490 {
1491 PetscFunctionBegin;
1492 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1493 if (mapping->bs > 1) {
1494 if (numprocs) PetscCall(PetscFree(*numprocs));
1495 if (indices) {
1496 if (*indices)
1497 for (PetscInt i = 0; i < *nproc; i++) PetscCall(PetscFree((*indices)[i]));
1498 PetscCall(PetscFree(*indices));
1499 }
1500 }
1501 PetscFunctionReturn(PETSC_SUCCESS);
1502 }
1503
1504 /*@C
1505 ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information of local nodes
1506
1507 Collective the first time it is called
1508
1509 Input Parameter:
1510 . mapping - the mapping from local to global indexing
1511
1512 Output Parameters:
1513 + n - number of local nodes
1514 . n_procs - an array storing the number of processes for each local node (including self)
1515 - procs - the processes' rank for each local node (sorted, self is first)
1516
1517 Level: advanced
1518
1519 Note:
1520 The user needs to call `ISLocalToGlobalMappingRestoreNodeInfo()` when the data is no longer needed.
1521
1522 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1523 `ISLocalToGlobalMappingGetInfo()`, `ISLocalToGlobalMappingRestoreNodeInfo()`, `ISLocalToGlobalMappingGetBlockNodeInfo()`
1524 @*/
ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping,PetscInt * n,PetscInt * n_procs[],PetscInt ** procs[])1525 PetscErrorCode ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1526 {
1527 PetscInt **bprocs = NULL, *bn_procs = NULL, bs, i, j, k, bn;
1528
1529 PetscFunctionBegin;
1530 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1531 bs = mapping->bs;
1532 PetscCall(ISLocalToGlobalMappingGetBlockNodeInfo(mapping, &bn, &bn_procs, &bprocs));
1533 if (bs > 1) { /* we need to expand the cached info */
1534 PetscInt *tn_procs;
1535 PetscInt c;
1536
1537 PetscCall(PetscMalloc1(bn * bs, &tn_procs));
1538 for (i = 0, c = 0; i < bn; i++) {
1539 for (k = 0; k < bs; k++) tn_procs[i * bs + k] = bn_procs[i];
1540 c += bs * bn_procs[i];
1541 }
1542 if (n) *n = bn * bs;
1543 if (procs) {
1544 PetscInt **tprocs;
1545 PetscInt tn = bn * bs;
1546
1547 PetscCall(PetscMalloc1(tn, &tprocs));
1548 if (tn) PetscCall(PetscMalloc1(c, &tprocs[0]));
1549 for (i = 0; i < tn - 1; i++) tprocs[i + 1] = tprocs[i] + tn_procs[i];
1550 for (i = 0; i < bn; i++) {
1551 for (k = 0; k < bs; k++) {
1552 for (j = 0; j < bn_procs[i]; j++) tprocs[i * bs + k][j] = bprocs[i][j];
1553 }
1554 }
1555 *procs = tprocs;
1556 }
1557 if (n_procs) *n_procs = tn_procs;
1558 else PetscCall(PetscFree(tn_procs));
1559 } else {
1560 if (n) *n = bn;
1561 if (n_procs) *n_procs = bn_procs;
1562 if (procs) *procs = bprocs;
1563 }
1564 PetscFunctionReturn(PETSC_SUCCESS);
1565 }
1566
1567 /*@C
1568 ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetNodeInfo()`
1569
1570 Not Collective
1571
1572 Input Parameters:
1573 + mapping - the mapping from local to global indexing
1574 . n - number of local nodes
1575 . n_procs - an array storing the number of processes for each local node (including self)
1576 - procs - the processes' rank for each local node (sorted, self is first)
1577
1578 Level: advanced
1579
1580 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`,
1581 `ISLocalToGlobalMappingGetInfo()`
1582 @*/
ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping,PetscInt * n,PetscInt * n_procs[],PetscInt ** procs[])1583 PetscErrorCode ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[])
1584 {
1585 PetscFunctionBegin;
1586 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1);
1587 if (mapping->bs > 1) {
1588 if (n_procs) PetscCall(PetscFree(*n_procs));
1589 if (procs) {
1590 if (*procs) PetscCall(PetscFree((*procs)[0]));
1591 PetscCall(PetscFree(*procs));
1592 }
1593 }
1594 PetscCall(ISLocalToGlobalMappingRestoreBlockNodeInfo(mapping, n, n_procs, procs));
1595 PetscFunctionReturn(PETSC_SUCCESS);
1596 }
1597
1598 /*@C
1599 ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped
1600
1601 Not Collective
1602
1603 Input Parameter:
1604 . ltog - local to global mapping
1605
1606 Output Parameter:
1607 . array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()`
1608
1609 Level: advanced
1610
1611 Note:
1612 `ISLocalToGlobalMappingGetSize()` returns the length the this array
1613
1614 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreIndices()`,
1615 `ISLocalToGlobalMappingGetBlockIndices()`, `ISLocalToGlobalMappingRestoreBlockIndices()`
1616 @*/
ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt * array[])1617 PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog, const PetscInt *array[])
1618 {
1619 PetscFunctionBegin;
1620 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1621 PetscAssertPointer(array, 2);
1622 if (ltog->bs == 1) {
1623 *array = ltog->indices;
1624 } else {
1625 PetscInt *jj, k, i, j, n = ltog->n, bs = ltog->bs;
1626 const PetscInt *ii;
1627
1628 PetscCall(PetscMalloc1(bs * n, &jj));
1629 *array = jj;
1630 k = 0;
1631 ii = ltog->indices;
1632 for (i = 0; i < n; i++)
1633 for (j = 0; j < bs; j++) jj[k++] = bs * ii[i] + j;
1634 }
1635 PetscFunctionReturn(PETSC_SUCCESS);
1636 }
1637
1638 /*@C
1639 ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with `ISLocalToGlobalMappingGetIndices()`
1640
1641 Not Collective
1642
1643 Input Parameters:
1644 + ltog - local to global mapping
1645 - array - array of indices
1646
1647 Level: advanced
1648
1649 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()`
1650 @*/
ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt * array[])1651 PetscErrorCode ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog, const PetscInt *array[])
1652 {
1653 PetscFunctionBegin;
1654 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1655 PetscAssertPointer(array, 2);
1656 PetscCheck(ltog->bs != 1 || *array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer");
1657 if (ltog->bs > 1) PetscCall(PetscFree(*(void **)array));
1658 PetscFunctionReturn(PETSC_SUCCESS);
1659 }
1660
1661 /*@C
1662 ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block in a `ISLocalToGlobalMapping`
1663
1664 Not Collective
1665
1666 Input Parameter:
1667 . ltog - local to global mapping
1668
1669 Output Parameter:
1670 . array - array of indices
1671
1672 Level: advanced
1673
1674 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`,
1675 `ISLocalToGlobalMappingRestoreBlockIndices()`
1676 @*/
ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt * array[])1677 PetscErrorCode ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt *array[])
1678 {
1679 PetscFunctionBegin;
1680 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1681 PetscAssertPointer(array, 2);
1682 *array = ltog->indices;
1683 PetscFunctionReturn(PETSC_SUCCESS);
1684 }
1685
1686 /*@C
1687 ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with `ISLocalToGlobalMappingGetBlockIndices()`
1688
1689 Not Collective
1690
1691 Input Parameters:
1692 + ltog - local to global mapping
1693 - array - array of indices
1694
1695 Level: advanced
1696
1697 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()`
1698 @*/
ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt * array[])1699 PetscErrorCode ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt *array[])
1700 {
1701 PetscFunctionBegin;
1702 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1703 PetscAssertPointer(array, 2);
1704 PetscCheck(*array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer");
1705 *array = NULL;
1706 PetscFunctionReturn(PETSC_SUCCESS);
1707 }
1708
1709 /*@
1710 ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings
1711
1712 Not Collective
1713
1714 Input Parameters:
1715 + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate
1716 . n - number of mappings to concatenate
1717 - ltogs - local to global mappings
1718
1719 Output Parameter:
1720 . ltogcat - new mapping
1721
1722 Level: advanced
1723
1724 Note:
1725 This currently always returns a mapping with block size of 1
1726
1727 Developer Notes:
1728 If all the input mapping have the same block size we could easily handle that as a special case
1729
1730 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()`
1731 @*/
ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping * ltogcat)1732 PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm, PetscInt n, const ISLocalToGlobalMapping ltogs[], ISLocalToGlobalMapping *ltogcat)
1733 {
1734 PetscInt i, cnt, m, *idx;
1735
1736 PetscFunctionBegin;
1737 PetscCheck(n >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Must have a non-negative number of mappings, given %" PetscInt_FMT, n);
1738 if (n > 0) PetscAssertPointer(ltogs, 3);
1739 for (i = 0; i < n; i++) PetscValidHeaderSpecific(ltogs[i], IS_LTOGM_CLASSID, 3);
1740 PetscAssertPointer(ltogcat, 4);
1741 for (cnt = 0, i = 0; i < n; i++) {
1742 PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m));
1743 cnt += m;
1744 }
1745 PetscCall(PetscMalloc1(cnt, &idx));
1746 for (cnt = 0, i = 0; i < n; i++) {
1747 const PetscInt *subidx;
1748 PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m));
1749 PetscCall(ISLocalToGlobalMappingGetIndices(ltogs[i], &subidx));
1750 PetscCall(PetscArraycpy(&idx[cnt], subidx, m));
1751 PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogs[i], &subidx));
1752 cnt += m;
1753 }
1754 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, cnt, idx, PETSC_OWN_POINTER, ltogcat));
1755 PetscFunctionReturn(PETSC_SUCCESS);
1756 }
1757
1758 /*MC
1759 ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is
1760 used this is good for only small and moderate size problems.
1761
1762 Options Database Key:
1763 . -islocaltoglobalmapping_type basic - select this method
1764
1765 Level: beginner
1766
1767 Developer Note:
1768 This stores all the mapping information on each MPI rank.
1769
1770 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGHASH`
1771 M*/
ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)1772 PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog)
1773 {
1774 PetscFunctionBegin;
1775 ltog->ops->globaltolocalmappingapply = ISGlobalToLocalMappingApply_Basic;
1776 ltog->ops->globaltolocalmappingsetup = ISGlobalToLocalMappingSetUp_Basic;
1777 ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic;
1778 ltog->ops->destroy = ISLocalToGlobalMappingDestroy_Basic;
1779 PetscFunctionReturn(PETSC_SUCCESS);
1780 }
1781
1782 /*MC
1783 ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is
1784 used this is good for large memory problems.
1785
1786 Options Database Key:
1787 . -islocaltoglobalmapping_type hash - select this method
1788
1789 Level: beginner
1790
1791 Note:
1792 This is selected automatically for large problems if the user does not set the type.
1793
1794 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGBASIC`
1795 M*/
ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)1796 PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog)
1797 {
1798 PetscFunctionBegin;
1799 ltog->ops->globaltolocalmappingapply = ISGlobalToLocalMappingApply_Hash;
1800 ltog->ops->globaltolocalmappingsetup = ISGlobalToLocalMappingSetUp_Hash;
1801 ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash;
1802 ltog->ops->destroy = ISLocalToGlobalMappingDestroy_Hash;
1803 PetscFunctionReturn(PETSC_SUCCESS);
1804 }
1805
1806 /*@C
1807 ISLocalToGlobalMappingRegister - Registers a method for applying a global to local mapping with an `ISLocalToGlobalMapping`
1808
1809 Not Collective, No Fortran Support
1810
1811 Input Parameters:
1812 + sname - name of a new method
1813 - function - routine to create method context
1814
1815 Example Usage:
1816 .vb
1817 ISLocalToGlobalMappingRegister("my_mapper", MyCreate);
1818 .ve
1819
1820 Then, your mapping can be chosen with the procedural interface via
1821 .vb
1822 ISLocalToGlobalMappingSetType(ltog, "my_mapper")
1823 .ve
1824 or at runtime via the option
1825 .vb
1826 -islocaltoglobalmapping_type my_mapper
1827 .ve
1828
1829 Level: advanced
1830
1831 Note:
1832 `ISLocalToGlobalMappingRegister()` may be called multiple times to add several user-defined mappings.
1833
1834 .seealso: [](sec_scatter), `ISLocalToGlobalMappingRegisterAll()`, `ISLocalToGlobalMappingRegisterDestroy()`, `ISLOCALTOGLOBALMAPPINGBASIC`,
1835 `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`
1836 @*/
ISLocalToGlobalMappingRegister(const char sname[],PetscErrorCode (* function)(ISLocalToGlobalMapping))1837 PetscErrorCode ISLocalToGlobalMappingRegister(const char sname[], PetscErrorCode (*function)(ISLocalToGlobalMapping))
1838 {
1839 PetscFunctionBegin;
1840 PetscCall(ISInitializePackage());
1841 PetscCall(PetscFunctionListAdd(&ISLocalToGlobalMappingList, sname, function));
1842 PetscFunctionReturn(PETSC_SUCCESS);
1843 }
1844
1845 /*@
1846 ISLocalToGlobalMappingSetType - Sets the implementation type `ISLocalToGlobalMapping` will use
1847
1848 Logically Collective
1849
1850 Input Parameters:
1851 + ltog - the `ISLocalToGlobalMapping` object
1852 - type - a known method
1853
1854 Options Database Key:
1855 . -islocaltoglobalmapping_type <method> - Sets the method; use -help for a list of available methods (for instance, basic or hash)
1856
1857 Level: intermediate
1858
1859 Notes:
1860 See `ISLocalToGlobalMappingType` for available methods
1861
1862 Normally, it is best to use the `ISLocalToGlobalMappingSetFromOptions()` command and
1863 then set the `ISLocalToGlobalMappingType` from the options database rather than by using
1864 this routine.
1865
1866 Developer Notes:
1867 `ISLocalToGlobalMappingRegister()` is used to add new types to `ISLocalToGlobalMappingList` from which they
1868 are accessed by `ISLocalToGlobalMappingSetType()`.
1869
1870 .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingGetType()`
1871 @*/
ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog,ISLocalToGlobalMappingType type)1872 PetscErrorCode ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type)
1873 {
1874 PetscBool match;
1875 PetscErrorCode (*r)(ISLocalToGlobalMapping) = NULL;
1876
1877 PetscFunctionBegin;
1878 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1879 if (type) PetscAssertPointer(type, 2);
1880
1881 PetscCall(PetscObjectTypeCompare((PetscObject)ltog, type, &match));
1882 if (match) PetscFunctionReturn(PETSC_SUCCESS);
1883
1884 /* L2G maps defer type setup at globaltolocal calls, allow passing NULL here */
1885 if (type) {
1886 PetscCall(PetscFunctionListFind(ISLocalToGlobalMappingList, type, &r));
1887 PetscCheck(r, PetscObjectComm((PetscObject)ltog), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested ISLocalToGlobalMapping type %s", type);
1888 }
1889 /* Destroy the previous private LTOG context */
1890 PetscTryTypeMethod(ltog, destroy);
1891 ltog->ops->destroy = NULL;
1892
1893 PetscCall(PetscObjectChangeTypeName((PetscObject)ltog, type));
1894 if (r) PetscCall((*r)(ltog));
1895 PetscFunctionReturn(PETSC_SUCCESS);
1896 }
1897
1898 /*@
1899 ISLocalToGlobalMappingGetType - Get the type of the `ISLocalToGlobalMapping`
1900
1901 Not Collective
1902
1903 Input Parameter:
1904 . ltog - the `ISLocalToGlobalMapping` object
1905
1906 Output Parameter:
1907 . type - the type
1908
1909 Level: intermediate
1910
1911 .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`
1912 @*/
ISLocalToGlobalMappingGetType(ISLocalToGlobalMapping ltog,ISLocalToGlobalMappingType * type)1913 PetscErrorCode ISLocalToGlobalMappingGetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType *type)
1914 {
1915 PetscFunctionBegin;
1916 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1);
1917 PetscAssertPointer(type, 2);
1918 *type = ((PetscObject)ltog)->type_name;
1919 PetscFunctionReturn(PETSC_SUCCESS);
1920 }
1921
1922 PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE;
1923
1924 /*@C
1925 ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the `IS` package.
1926
1927 Not Collective
1928
1929 Level: advanced
1930
1931 .seealso: [](sec_scatter), `ISRegister()`, `ISLocalToGlobalRegister()`
1932 @*/
ISLocalToGlobalMappingRegisterAll(void)1933 PetscErrorCode ISLocalToGlobalMappingRegisterAll(void)
1934 {
1935 PetscFunctionBegin;
1936 if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
1937 ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE;
1938 PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic));
1939 PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash));
1940 PetscFunctionReturn(PETSC_SUCCESS);
1941 }
1942