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