Actual source code: block.c
1: /*
2: Provides the functions for index sets (IS) defined by a list of integers.
3: These are for blocks of data, each block is indicated with a single integer.
4: */
5: #include <petsc/private/isimpl.h>
6: #include <petscviewer.h>
8: typedef struct {
9: PetscBool sorted; /* are the blocks sorted? */
10: PetscBool allocated; /* did we allocate the index array ourselves? */
11: PetscInt *idx;
12: } IS_Block;
14: static PetscErrorCode ISDestroy_Block(IS is)
15: {
16: IS_Block *sub = (IS_Block *)is->data;
18: PetscFunctionBegin;
19: if (sub->allocated) PetscCall(PetscFree(sub->idx));
20: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockSetIndices_C", NULL));
21: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetIndices_C", NULL));
22: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockRestoreIndices_C", NULL));
23: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetSize_C", NULL));
24: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetLocalSize_C", NULL));
25: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISShift_C", NULL));
26: PetscCall(PetscFree(is->data));
27: PetscFunctionReturn(PETSC_SUCCESS);
28: }
30: static PetscErrorCode ISLocate_Block(IS is, PetscInt key, PetscInt *location)
31: {
32: IS_Block *sub = (IS_Block *)is->data;
33: PetscInt numIdx, i, bs, bkey, mkey;
34: PetscBool sorted;
36: PetscFunctionBegin;
37: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
38: PetscCall(PetscLayoutGetLocalSize(is->map, &numIdx));
39: numIdx /= bs;
40: bkey = key / bs;
41: mkey = key % bs;
42: if (mkey < 0) {
43: bkey--;
44: mkey += bs;
45: }
46: PetscCall(ISGetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, &sorted));
47: if (sorted) {
48: PetscCall(PetscFindInt(bkey, numIdx, sub->idx, location));
49: } else {
50: const PetscInt *idx = sub->idx;
52: *location = -1;
53: for (i = 0; i < numIdx; i++) {
54: if (idx[i] == bkey) {
55: *location = i;
56: break;
57: }
58: }
59: }
60: if (*location >= 0) *location = *location * bs + mkey;
61: PetscFunctionReturn(PETSC_SUCCESS);
62: }
64: static PetscErrorCode ISGetIndices_Block(IS in, const PetscInt *idx[])
65: {
66: IS_Block *sub = (IS_Block *)in->data;
67: PetscInt i, j, k, bs, n, *ii, *jj;
69: PetscFunctionBegin;
70: PetscCall(PetscLayoutGetBlockSize(in->map, &bs));
71: PetscCall(PetscLayoutGetLocalSize(in->map, &n));
72: n /= bs;
73: if (bs == 1) *idx = sub->idx;
74: else {
75: if (n) {
76: PetscCall(PetscMalloc1(bs * n, &jj));
77: *idx = jj;
78: k = 0;
79: ii = sub->idx;
80: for (i = 0; i < n; i++)
81: for (j = 0; j < bs; j++) jj[k++] = bs * ii[i] + j;
82: } else {
83: /* do not malloc for zero size because F90Array1dCreate() inside ISRestoreArrayF90() does not keep array when zero length array */
84: *idx = NULL;
85: }
86: }
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: static PetscErrorCode ISRestoreIndices_Block(IS is, const PetscInt *idx[])
91: {
92: IS_Block *sub = (IS_Block *)is->data;
93: PetscInt bs;
95: PetscFunctionBegin;
96: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
97: if (bs != 1) {
98: PetscCall(PetscFree(*(void **)idx));
99: } else {
100: /* F90Array1dCreate() inside ISRestoreArrayF90() does not keep array when zero length array */
101: PetscCheck(is->map->n <= 0 || *idx == sub->idx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must restore with value from ISGetIndices()");
102: }
103: PetscFunctionReturn(PETSC_SUCCESS);
104: }
106: static PetscErrorCode ISInvertPermutation_Block(IS is, PetscInt nlocal, IS *isout)
107: {
108: IS_Block *sub = (IS_Block *)is->data;
109: PetscInt i, *ii, bs, n, *idx = sub->idx;
110: PetscMPIInt size;
112: PetscFunctionBegin;
113: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)is), &size));
114: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
115: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
116: n /= bs;
117: if (size == 1) {
118: PetscCall(PetscMalloc1(n, &ii));
119: for (i = 0; i < n; i++) ii[idx[i]] = i;
120: PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n, ii, PETSC_OWN_POINTER, isout));
121: PetscCall(ISSetPermutation(*isout));
122: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No inversion written yet for block IS");
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: static PetscErrorCode ISView_Block(IS is, PetscViewer viewer)
127: {
128: IS_Block *sub = (IS_Block *)is->data;
129: PetscInt i, bs, n, *idx = sub->idx;
130: PetscBool iascii, ibinary;
132: PetscFunctionBegin;
133: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
134: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
135: n /= bs;
136: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
137: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
138: if (iascii) {
139: PetscViewerFormat fmt;
141: PetscCall(PetscViewerGetFormat(viewer, &fmt));
142: if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
143: IS ist;
144: const char *name;
145: const PetscInt *idx;
146: PetscInt n;
148: PetscCall(PetscObjectGetName((PetscObject)is, &name));
149: PetscCall(ISGetLocalSize(is, &n));
150: PetscCall(ISGetIndices(is, &idx));
151: PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), n, idx, PETSC_USE_POINTER, &ist));
152: PetscCall(PetscObjectSetName((PetscObject)ist, name));
153: PetscCall(ISView(ist, viewer));
154: PetscCall(ISDestroy(&ist));
155: PetscCall(ISRestoreIndices(is, &idx));
156: } else {
157: PetscBool isperm;
159: PetscCall(ISGetInfo(is, IS_PERMUTATION, IS_GLOBAL, PETSC_FALSE, &isperm));
160: if (isperm) PetscCall(PetscViewerASCIIPrintf(viewer, "Block Index set is permutation\n"));
161: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
162: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Block size %" PetscInt_FMT "\n", bs));
163: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Number of block indices in set %" PetscInt_FMT "\n", n));
164: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "The first indices of each block are\n"));
165: for (i = 0; i < n; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Block %" PetscInt_FMT " Index %" PetscInt_FMT "\n", i, idx[i]));
166: PetscCall(PetscViewerFlush(viewer));
167: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
168: }
169: } else if (ibinary) PetscCall(ISView_Binary(is, viewer));
170: PetscFunctionReturn(PETSC_SUCCESS);
171: }
173: static PetscErrorCode ISSort_Block(IS is)
174: {
175: IS_Block *sub = (IS_Block *)is->data;
176: PetscInt bs, n;
178: PetscFunctionBegin;
179: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
180: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
181: PetscCall(PetscIntSortSemiOrdered(n / bs, sub->idx));
182: PetscFunctionReturn(PETSC_SUCCESS);
183: }
185: static PetscErrorCode ISSortRemoveDups_Block(IS is)
186: {
187: IS_Block *sub = (IS_Block *)is->data;
188: PetscInt bs, n, nb;
189: PetscBool sorted;
191: PetscFunctionBegin;
192: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
193: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
194: nb = n / bs;
195: PetscCall(ISGetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, &sorted));
196: if (sorted) {
197: PetscCall(PetscSortedRemoveDupsInt(&nb, sub->idx));
198: } else {
199: PetscCall(PetscSortRemoveDupsInt(&nb, sub->idx));
200: }
201: PetscCall(PetscLayoutDestroy(&is->map));
202: PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is), nb * bs, PETSC_DECIDE, bs, &is->map));
203: PetscFunctionReturn(PETSC_SUCCESS);
204: }
206: static PetscErrorCode ISSorted_Block(IS is, PetscBool *flg)
207: {
208: PetscFunctionBegin;
209: PetscCall(ISGetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, flg));
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: static PetscErrorCode ISSortedLocal_Block(IS is, PetscBool *flg)
214: {
215: IS_Block *sub = (IS_Block *)is->data;
216: PetscInt n, bs, i, *idx;
218: PetscFunctionBegin;
219: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
220: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
221: n /= bs;
222: idx = sub->idx;
223: for (i = 1; i < n; i++)
224: if (idx[i] < idx[i - 1]) break;
225: if (i < n) *flg = PETSC_FALSE;
226: else *flg = PETSC_TRUE;
227: PetscFunctionReturn(PETSC_SUCCESS);
228: }
230: static PetscErrorCode ISUniqueLocal_Block(IS is, PetscBool *flg)
231: {
232: IS_Block *sub = (IS_Block *)is->data;
233: PetscInt n, bs, i, *idx, *idxcopy = NULL;
234: PetscBool sortedLocal;
236: PetscFunctionBegin;
237: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
238: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
239: n /= bs;
240: idx = sub->idx;
241: PetscCall(ISGetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, &sortedLocal));
242: if (!sortedLocal) {
243: PetscCall(PetscMalloc1(n, &idxcopy));
244: PetscCall(PetscArraycpy(idxcopy, idx, n));
245: PetscCall(PetscIntSortSemiOrdered(n, idxcopy));
246: idx = idxcopy;
247: }
248: for (i = 1; i < n; i++)
249: if (idx[i] == idx[i - 1]) break;
250: if (i < n) *flg = PETSC_FALSE;
251: else *flg = PETSC_TRUE;
252: PetscCall(PetscFree(idxcopy));
253: PetscFunctionReturn(PETSC_SUCCESS);
254: }
256: static PetscErrorCode ISPermutationLocal_Block(IS is, PetscBool *flg)
257: {
258: IS_Block *sub = (IS_Block *)is->data;
259: PetscInt n, bs, i, *idx, *idxcopy = NULL;
260: PetscBool sortedLocal;
262: PetscFunctionBegin;
263: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
264: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
265: n /= bs;
266: idx = sub->idx;
267: PetscCall(ISGetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, &sortedLocal));
268: if (!sortedLocal) {
269: PetscCall(PetscMalloc1(n, &idxcopy));
270: PetscCall(PetscArraycpy(idxcopy, idx, n));
271: PetscCall(PetscIntSortSemiOrdered(n, idxcopy));
272: idx = idxcopy;
273: }
274: for (i = 0; i < n; i++)
275: if (idx[i] != i) break;
276: if (i < n) *flg = PETSC_FALSE;
277: else *flg = PETSC_TRUE;
278: PetscCall(PetscFree(idxcopy));
279: PetscFunctionReturn(PETSC_SUCCESS);
280: }
282: static PetscErrorCode ISIntervalLocal_Block(IS is, PetscBool *flg)
283: {
284: IS_Block *sub = (IS_Block *)is->data;
285: PetscInt n, bs, i, *idx;
287: PetscFunctionBegin;
288: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
289: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
290: n /= bs;
291: idx = sub->idx;
292: for (i = 1; i < n; i++)
293: if (idx[i] != idx[i - 1] + 1) break;
294: if (i < n) *flg = PETSC_FALSE;
295: else *flg = PETSC_TRUE;
296: PetscFunctionReturn(PETSC_SUCCESS);
297: }
299: static PetscErrorCode ISDuplicate_Block(IS is, IS *newIS)
300: {
301: IS_Block *sub = (IS_Block *)is->data;
302: PetscInt bs, n;
304: PetscFunctionBegin;
305: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
306: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
307: n /= bs;
308: PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)is), bs, n, sub->idx, PETSC_COPY_VALUES, newIS));
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: static PetscErrorCode ISCopy_Block(IS is, IS isy)
313: {
314: IS_Block *is_block = (IS_Block *)is->data, *isy_block = (IS_Block *)isy->data;
315: PetscInt bs, n;
317: PetscFunctionBegin;
318: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
319: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
320: PetscCall(PetscArraycpy(isy_block->idx, is_block->idx, n / bs));
321: PetscFunctionReturn(PETSC_SUCCESS);
322: }
324: static PetscErrorCode ISOnComm_Block(IS is, MPI_Comm comm, PetscCopyMode mode, IS *newis)
325: {
326: IS_Block *sub = (IS_Block *)is->data;
327: PetscInt bs, n;
329: PetscFunctionBegin;
330: PetscCheck(mode != PETSC_OWN_POINTER, comm, PETSC_ERR_ARG_WRONG, "Cannot use PETSC_OWN_POINTER");
331: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
332: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
333: PetscCall(ISCreateBlock(comm, bs, n / bs, sub->idx, mode, newis));
334: PetscFunctionReturn(PETSC_SUCCESS);
335: }
337: static PetscErrorCode ISShift_Block(IS is, PetscInt shift, IS isy)
338: {
339: IS_Block *isb = (IS_Block *)is->data;
340: IS_Block *isby = (IS_Block *)isy->data;
341: PetscInt i, n, bs;
343: PetscFunctionBegin;
344: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
345: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
346: shift /= bs;
347: for (i = 0; i < n / bs; i++) isby->idx[i] = isb->idx[i] + shift;
348: PetscFunctionReturn(PETSC_SUCCESS);
349: }
351: static PetscErrorCode ISSetBlockSize_Block(IS is, PetscInt bs)
352: {
353: PetscFunctionBegin;
354: PetscCheck(is->map->bs <= 0 || bs == is->map->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot change blocksize %" PetscInt_FMT " (to %" PetscInt_FMT ") if ISType is ISBLOCK", is->map->bs, bs);
355: PetscCall(PetscLayoutSetBlockSize(is->map, bs));
356: PetscFunctionReturn(PETSC_SUCCESS);
357: }
359: static PetscErrorCode ISToGeneral_Block(IS inis)
360: {
361: IS_Block *sub = (IS_Block *)inis->data;
362: PetscInt bs, n;
363: const PetscInt *idx;
365: PetscFunctionBegin;
366: PetscCall(ISGetBlockSize(inis, &bs));
367: PetscCall(ISGetLocalSize(inis, &n));
368: PetscCall(ISGetIndices(inis, &idx));
369: if (bs == 1) {
370: PetscCopyMode mode = sub->allocated ? PETSC_OWN_POINTER : PETSC_USE_POINTER;
371: sub->allocated = PETSC_FALSE; /* prevent deallocation when changing the subtype*/
372: PetscCall(ISSetType(inis, ISGENERAL));
373: PetscCall(ISGeneralSetIndices(inis, n, idx, mode));
374: } else {
375: PetscCall(ISSetType(inis, ISGENERAL));
376: PetscCall(ISGeneralSetIndices(inis, n, idx, PETSC_OWN_POINTER));
377: }
378: PetscFunctionReturn(PETSC_SUCCESS);
379: }
381: // clang-format off
382: static const struct _ISOps myops = {
383: PetscDesignatedInitializer(getindices, ISGetIndices_Block),
384: PetscDesignatedInitializer(restoreindices, ISRestoreIndices_Block),
385: PetscDesignatedInitializer(invertpermutation, ISInvertPermutation_Block),
386: PetscDesignatedInitializer(sort, ISSort_Block),
387: PetscDesignatedInitializer(sortremovedups, ISSortRemoveDups_Block),
388: PetscDesignatedInitializer(sorted, ISSorted_Block),
389: PetscDesignatedInitializer(duplicate, ISDuplicate_Block),
390: PetscDesignatedInitializer(destroy, ISDestroy_Block),
391: PetscDesignatedInitializer(view, ISView_Block),
392: PetscDesignatedInitializer(load, ISLoad_Default),
393: PetscDesignatedInitializer(copy, ISCopy_Block),
394: PetscDesignatedInitializer(togeneral, ISToGeneral_Block),
395: PetscDesignatedInitializer(oncomm, ISOnComm_Block),
396: PetscDesignatedInitializer(setblocksize, ISSetBlockSize_Block),
397: PetscDesignatedInitializer(contiguous, NULL),
398: PetscDesignatedInitializer(locate, ISLocate_Block),
399: /* we can have specialized local routines for determining properties,
400: * but unless the block size is the same on each process (which is not guaranteed at
401: * the moment), then trying to do something specialized for global properties is too
402: * complicated */
403: PetscDesignatedInitializer(sortedlocal, ISSortedLocal_Block),
404: PetscDesignatedInitializer(sortedglobal, NULL),
405: PetscDesignatedInitializer(uniquelocal, ISUniqueLocal_Block),
406: PetscDesignatedInitializer(uniqueglobal, NULL),
407: PetscDesignatedInitializer(permlocal, ISPermutationLocal_Block),
408: PetscDesignatedInitializer(permglobal, NULL),
409: PetscDesignatedInitializer(intervallocal, ISIntervalLocal_Block),
410: PetscDesignatedInitializer(intervalglobal, NULL)
411: };
412: // clang-format on
414: /*@
415: ISBlockSetIndices - Set integers representing blocks of indices in an index set of `ISType` `ISBLOCK`
417: Collective
419: Input Parameters:
420: + is - the index set
421: . bs - number of elements in each block
422: . n - the length of the index set (the number of blocks)
423: . idx - the list of integers, one for each block, the integers contain the index of the first index of each block divided by the block size
424: - mode - see `PetscCopyMode`, only `PETSC_COPY_VALUES` and `PETSC_OWN_POINTER` are supported
426: Level: beginner
428: Notes:
429: When the communicator is not `MPI_COMM_SELF`, the operations on the
430: index sets, IS, are NOT conceptually the same as `MPI_Group` operations.
431: The index sets are then distributed sets of indices and thus certain operations
432: on them are collective.
434: The convenience routine `ISCreateBlock()` allows one to create the `IS` and provide the blocks in a single function call.
436: Example:
437: If you wish to index the values {0,1,4,5}, then use
438: a block size of 2 and idx of {0,2}.
440: .seealso: [](sec_scatter), `IS`, `ISCreateStride()`, `ISCreateGeneral()`, `ISAllGather()`, `ISCreateBlock()`, `ISBLOCK`, `ISGeneralSetIndices()`
441: @*/
442: PetscErrorCode ISBlockSetIndices(IS is, PetscInt bs, PetscInt n, const PetscInt idx[], PetscCopyMode mode)
443: {
444: PetscFunctionBegin;
445: PetscCall(ISClearInfoCache(is, PETSC_FALSE));
446: PetscUseMethod(is, "ISBlockSetIndices_C", (IS, PetscInt, PetscInt, const PetscInt[], PetscCopyMode), (is, bs, n, idx, mode));
447: PetscFunctionReturn(PETSC_SUCCESS);
448: }
450: static PetscErrorCode ISBlockSetIndices_Block(IS is, PetscInt bs, PetscInt n, const PetscInt idx[], PetscCopyMode mode)
451: {
452: PetscInt i, min, max;
453: IS_Block *sub = (IS_Block *)is->data;
454: PetscLayout map;
456: PetscFunctionBegin;
457: PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "block size < 1");
458: PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "length < 0");
459: if (n) PetscAssertPointer(idx, 4);
461: PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is), n * bs, is->map->N, bs, &map));
462: PetscCall(PetscLayoutDestroy(&is->map));
463: is->map = map;
465: if (sub->allocated) PetscCall(PetscFree(sub->idx));
466: if (mode == PETSC_COPY_VALUES) {
467: PetscCall(PetscMalloc1(n, &sub->idx));
468: PetscCall(PetscArraycpy(sub->idx, idx, n));
469: sub->allocated = PETSC_TRUE;
470: } else if (mode == PETSC_OWN_POINTER) {
471: sub->idx = (PetscInt *)idx;
472: sub->allocated = PETSC_TRUE;
473: } else if (mode == PETSC_USE_POINTER) {
474: sub->idx = (PetscInt *)idx;
475: sub->allocated = PETSC_FALSE;
476: }
478: if (n) {
479: min = max = idx[0];
480: for (i = 1; i < n; i++) {
481: if (idx[i] < min) min = idx[i];
482: if (idx[i] > max) max = idx[i];
483: }
484: is->min = bs * min;
485: is->max = bs * max + bs - 1;
486: } else {
487: is->min = PETSC_INT_MAX;
488: is->max = PETSC_INT_MIN;
489: }
490: PetscFunctionReturn(PETSC_SUCCESS);
491: }
493: /*@
494: ISCreateBlock - Creates a data structure for an index set containing
495: a list of integers. Each integer represents a fixed block size set of indices.
497: Collective
499: Input Parameters:
500: + comm - the MPI communicator
501: . bs - number of elements in each block
502: . n - the length of the index set (the number of blocks)
503: . idx - the list of integers, one for each block, the integers contain the index of the first entry of each block divided by the block size
504: - mode - see `PetscCopyMode`, only `PETSC_COPY_VALUES` and `PETSC_OWN_POINTER` are supported in this routine
506: Output Parameter:
507: . is - the new index set
509: Level: beginner
511: Notes:
512: When the communicator is not `MPI_COMM_SELF`, the operations on the
513: index sets, `IS`, are NOT conceptually the same as `MPI_Group` operations.
514: The index sets are then distributed sets of indices and thus certain operations
515: on them are collective.
517: The routine `ISBlockSetIndices()` can be used to provide the indices to a preexisting block `IS`
519: Example:
520: If you wish to index the values {0,1,6,7}, then use
521: a block size of 2 and idx of {0,3}.
523: .seealso: [](sec_scatter), `IS`, `ISCreateStride()`, `ISCreateGeneral()`, `ISAllGather()`, `ISBlockSetIndices()`, `ISBLOCK`, `ISGENERAL`
524: @*/
525: PetscErrorCode ISCreateBlock(MPI_Comm comm, PetscInt bs, PetscInt n, const PetscInt idx[], PetscCopyMode mode, IS *is)
526: {
527: PetscFunctionBegin;
528: PetscAssertPointer(is, 6);
529: PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "block size < 1");
530: PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "length < 0");
531: if (n) PetscAssertPointer(idx, 4);
533: PetscCall(ISCreate(comm, is));
534: PetscCall(ISSetType(*is, ISBLOCK));
535: PetscCall(ISBlockSetIndices(*is, bs, n, idx, mode));
536: PetscFunctionReturn(PETSC_SUCCESS);
537: }
539: static PetscErrorCode ISBlockGetIndices_Block(IS is, const PetscInt *idx[])
540: {
541: IS_Block *sub = (IS_Block *)is->data;
543: PetscFunctionBegin;
544: *idx = sub->idx;
545: PetscFunctionReturn(PETSC_SUCCESS);
546: }
548: static PetscErrorCode ISBlockRestoreIndices_Block(IS is, const PetscInt *idx[])
549: {
550: PetscFunctionBegin;
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }
554: /*@C
555: ISBlockGetIndices - Gets the indices associated with each block in an `ISBLOCK`
557: Not Collective
559: Input Parameter:
560: . is - the index set
562: Output Parameter:
563: . idx - the integer indices, one for each block and count of block not indices
565: Level: intermediate
567: Note:
568: Call `ISBlockRestoreIndices()` when you no longer need access to the indices
570: .seealso: [](sec_scatter), `IS`, `ISBLOCK`, `ISGetIndices()`, `ISBlockRestoreIndices()`, `ISBlockSetIndices()`, `ISCreateBlock()`
571: @*/
572: PetscErrorCode ISBlockGetIndices(IS is, const PetscInt *idx[])
573: {
574: PetscFunctionBegin;
575: PetscUseMethod(is, "ISBlockGetIndices_C", (IS, const PetscInt *[]), (is, idx));
576: PetscFunctionReturn(PETSC_SUCCESS);
577: }
579: /*@C
580: ISBlockRestoreIndices - Restores the indices associated with each block in an `ISBLOCK` obtained with `ISBlockGetIndices()`
582: Not Collective
584: Input Parameter:
585: . is - the index set
587: Output Parameter:
588: . idx - the integer indices
590: Level: intermediate
592: .seealso: [](sec_scatter), `IS`, `ISBLOCK`, `ISRestoreIndices()`, `ISBlockGetIndices()`
593: @*/
594: PetscErrorCode ISBlockRestoreIndices(IS is, const PetscInt *idx[])
595: {
596: PetscFunctionBegin;
597: PetscUseMethod(is, "ISBlockRestoreIndices_C", (IS, const PetscInt *[]), (is, idx));
598: PetscFunctionReturn(PETSC_SUCCESS);
599: }
601: /*@
602: ISBlockGetLocalSize - Returns the local number of blocks in the index set of `ISType` `ISBLOCK`
604: Not Collective
606: Input Parameter:
607: . is - the index set
609: Output Parameter:
610: . size - the local number of blocks
612: Level: intermediate
614: .seealso: [](sec_scatter), `IS`, `ISGetBlockSize()`, `ISBlockGetSize()`, `ISGetSize()`, `ISCreateBlock()`, `ISBLOCK`
615: @*/
616: PetscErrorCode ISBlockGetLocalSize(IS is, PetscInt *size)
617: {
618: PetscFunctionBegin;
619: PetscUseMethod(is, "ISBlockGetLocalSize_C", (IS, PetscInt *), (is, size));
620: PetscFunctionReturn(PETSC_SUCCESS);
621: }
623: static PetscErrorCode ISBlockGetLocalSize_Block(IS is, PetscInt *size)
624: {
625: PetscInt bs, n;
627: PetscFunctionBegin;
628: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
629: PetscCall(PetscLayoutGetLocalSize(is->map, &n));
630: *size = n / bs;
631: PetscFunctionReturn(PETSC_SUCCESS);
632: }
634: /*@
635: ISBlockGetSize - Returns the global number of blocks in parallel in the index set of `ISType` `ISBLOCK`
637: Not Collective
639: Input Parameter:
640: . is - the index set
642: Output Parameter:
643: . size - the global number of blocks
645: Level: intermediate
647: .seealso: [](sec_scatter), `IS`, `ISGetBlockSize()`, `ISBlockGetLocalSize()`, `ISGetSize()`, `ISCreateBlock()`, `ISBLOCK`
648: @*/
649: PetscErrorCode ISBlockGetSize(IS is, PetscInt *size)
650: {
651: PetscFunctionBegin;
652: PetscUseMethod(is, "ISBlockGetSize_C", (IS, PetscInt *), (is, size));
653: PetscFunctionReturn(PETSC_SUCCESS);
654: }
656: static PetscErrorCode ISBlockGetSize_Block(IS is, PetscInt *size)
657: {
658: PetscInt bs, N;
660: PetscFunctionBegin;
661: PetscCall(PetscLayoutGetBlockSize(is->map, &bs));
662: PetscCall(PetscLayoutGetSize(is->map, &N));
663: *size = N / bs;
664: PetscFunctionReturn(PETSC_SUCCESS);
665: }
667: PETSC_INTERN PetscErrorCode ISCreate_Block(IS is)
668: {
669: IS_Block *sub;
671: PetscFunctionBegin;
672: PetscCall(PetscNew(&sub));
673: is->data = (void *)sub;
674: is->ops[0] = myops;
675: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockSetIndices_C", ISBlockSetIndices_Block));
676: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetIndices_C", ISBlockGetIndices_Block));
677: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockRestoreIndices_C", ISBlockRestoreIndices_Block));
678: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetSize_C", ISBlockGetSize_Block));
679: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetLocalSize_C", ISBlockGetLocalSize_Block));
680: PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISShift_C", ISShift_Block));
681: PetscFunctionReturn(PETSC_SUCCESS);
682: }