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(PETSC_SUCCESS); 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(PetscLayoutGetLocalSize(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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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 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 411 Example: 412 If you wish to index the values {0,1,4,5}, then use 413 a block size of 2 and idx of {0,2}. 414 415 .seealso: [](sec_scatter), `IS`, `ISCreateStride()`, `ISCreateGeneral()`, `ISAllGather()`, `ISCreateBlock()`, `ISBLOCK`, `ISGeneralSetIndices()` 416 @*/ 417 PetscErrorCode ISBlockSetIndices(IS is, PetscInt bs, PetscInt n, const PetscInt idx[], PetscCopyMode mode) 418 { 419 PetscFunctionBegin; 420 PetscCall(ISClearInfoCache(is, PETSC_FALSE)); 421 PetscUseMethod(is, "ISBlockSetIndices_C", (IS, PetscInt, PetscInt, const PetscInt[], PetscCopyMode), (is, bs, n, idx, mode)); 422 PetscFunctionReturn(PETSC_SUCCESS); 423 } 424 425 static PetscErrorCode ISBlockSetIndices_Block(IS is, PetscInt bs, PetscInt n, const PetscInt idx[], PetscCopyMode mode) 426 { 427 PetscInt i, min, max; 428 IS_Block *sub = (IS_Block *)is->data; 429 PetscLayout map; 430 431 PetscFunctionBegin; 432 PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "block size < 1"); 433 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "length < 0"); 434 if (n) PetscValidIntPointer(idx, 4); 435 436 PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is), n * bs, is->map->N, bs, &map)); 437 PetscCall(PetscLayoutDestroy(&is->map)); 438 is->map = map; 439 440 if (sub->allocated) PetscCall(PetscFree(sub->idx)); 441 if (mode == PETSC_COPY_VALUES) { 442 PetscCall(PetscMalloc1(n, &sub->idx)); 443 PetscCall(PetscArraycpy(sub->idx, idx, n)); 444 sub->allocated = PETSC_TRUE; 445 } else if (mode == PETSC_OWN_POINTER) { 446 sub->idx = (PetscInt *)idx; 447 sub->allocated = PETSC_TRUE; 448 } else if (mode == PETSC_USE_POINTER) { 449 sub->idx = (PetscInt *)idx; 450 sub->allocated = PETSC_FALSE; 451 } 452 453 if (n) { 454 min = max = idx[0]; 455 for (i = 1; i < n; i++) { 456 if (idx[i] < min) min = idx[i]; 457 if (idx[i] > max) max = idx[i]; 458 } 459 is->min = bs * min; 460 is->max = bs * max + bs - 1; 461 } else { 462 is->min = PETSC_MAX_INT; 463 is->max = PETSC_MIN_INT; 464 } 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 ISCreateBlock - Creates a data structure for an index set containing 470 a list of integers. Each integer represents a fixed block size set of indices. 471 472 Collective 473 474 Input Parameters: 475 + comm - the MPI communicator 476 . bs - number of elements in each block 477 . n - the length of the index set (the number of blocks) 478 . 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 479 - mode - see `PetscCopyMode`, only `PETSC_COPY_VALUES` and `PETSC_OWN_POINTER` are supported in this routine 480 481 Output Parameter: 482 . is - the new index set 483 484 Level: beginner 485 486 Notes: 487 When the communicator is not `MPI_COMM_SELF`, the operations on the 488 index sets, `IS`, are NOT conceptually the same as `MPI_Group` operations. 489 The index sets are then distributed sets of indices and thus certain operations 490 on them are collective. 491 492 The routine `ISBlockSetIndices()` can be used to provide the indices to a preexisting block `IS` 493 494 Example: 495 If you wish to index the values {0,1,6,7}, then use 496 a block size of 2 and idx of {0,3}. 497 498 .seealso: [](sec_scatter), `IS`, `ISCreateStride()`, `ISCreateGeneral()`, `ISAllGather()`, `ISBlockSetIndices()`, `ISBLOCK`, `ISGENERAL` 499 @*/ 500 PetscErrorCode ISCreateBlock(MPI_Comm comm, PetscInt bs, PetscInt n, const PetscInt idx[], PetscCopyMode mode, IS *is) 501 { 502 PetscFunctionBegin; 503 PetscValidPointer(is, 6); 504 PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "block size < 1"); 505 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "length < 0"); 506 if (n) PetscValidIntPointer(idx, 4); 507 508 PetscCall(ISCreate(comm, is)); 509 PetscCall(ISSetType(*is, ISBLOCK)); 510 PetscCall(ISBlockSetIndices(*is, bs, n, idx, mode)); 511 PetscFunctionReturn(PETSC_SUCCESS); 512 } 513 514 static PetscErrorCode ISBlockGetIndices_Block(IS is, const PetscInt *idx[]) 515 { 516 IS_Block *sub = (IS_Block *)is->data; 517 518 PetscFunctionBegin; 519 *idx = sub->idx; 520 PetscFunctionReturn(PETSC_SUCCESS); 521 } 522 523 static PetscErrorCode ISBlockRestoreIndices_Block(IS is, const PetscInt *idx[]) 524 { 525 PetscFunctionBegin; 526 PetscFunctionReturn(PETSC_SUCCESS); 527 } 528 529 /*@C 530 ISBlockGetIndices - Gets the indices associated with each block in an `ISBLOCK` 531 532 Not Collective 533 534 Input Parameter: 535 . is - the index set 536 537 Output Parameter: 538 . idx - the integer indices, one for each block and count of block not indices 539 540 Level: intermediate 541 542 Note: 543 Call `ISBlockRestoreIndices()` when you no longer need access to the indices 544 545 .seealso: [](sec_scatter), `IS`, `ISBLOCK`, `ISGetIndices()`, `ISBlockRestoreIndices()`, `ISBlockSetIndices()`, `ISCreateBlock()` 546 @*/ 547 PetscErrorCode ISBlockGetIndices(IS is, const PetscInt *idx[]) 548 { 549 PetscFunctionBegin; 550 PetscUseMethod(is, "ISBlockGetIndices_C", (IS, const PetscInt *[]), (is, idx)); 551 PetscFunctionReturn(PETSC_SUCCESS); 552 } 553 554 /*@C 555 ISBlockRestoreIndices - Restores the indices associated with each block in an `ISBLOCK` obtained with `ISBlockGetIndices()` 556 557 Not Collective 558 559 Input Parameter: 560 . is - the index set 561 562 Output Parameter: 563 . idx - the integer indices 564 565 Level: intermediate 566 567 .seealso: [](sec_scatter), `IS`, `ISBLOCK`, `ISRestoreIndices()`, `ISBlockGetIndices()` 568 @*/ 569 PetscErrorCode ISBlockRestoreIndices(IS is, const PetscInt *idx[]) 570 { 571 PetscFunctionBegin; 572 PetscUseMethod(is, "ISBlockRestoreIndices_C", (IS, const PetscInt *[]), (is, idx)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 ISBlockGetLocalSize - Returns the local number of blocks in the index set of `ISType` `ISBLOCK` 578 579 Not Collective 580 581 Input Parameter: 582 . is - the index set 583 584 Output Parameter: 585 . size - the local number of blocks 586 587 Level: intermediate 588 589 .seealso: [](sec_scatter), `IS`, `ISGetBlockSize()`, `ISBlockGetSize()`, `ISGetSize()`, `ISCreateBlock()`, `ISBLOCK` 590 @*/ 591 PetscErrorCode ISBlockGetLocalSize(IS is, PetscInt *size) 592 { 593 PetscFunctionBegin; 594 PetscUseMethod(is, "ISBlockGetLocalSize_C", (IS, PetscInt *), (is, size)); 595 PetscFunctionReturn(PETSC_SUCCESS); 596 } 597 598 static PetscErrorCode ISBlockGetLocalSize_Block(IS is, PetscInt *size) 599 { 600 PetscInt bs, n; 601 602 PetscFunctionBegin; 603 PetscCall(PetscLayoutGetBlockSize(is->map, &bs)); 604 PetscCall(PetscLayoutGetLocalSize(is->map, &n)); 605 *size = n / bs; 606 PetscFunctionReturn(PETSC_SUCCESS); 607 } 608 609 /*@ 610 ISBlockGetSize - Returns the global number of blocks in parallel in the index set of `ISType` `ISBLOCK` 611 612 Not Collective 613 614 Input Parameter: 615 . is - the index set 616 617 Output Parameter: 618 . size - the global number of blocks 619 620 Level: intermediate 621 622 .seealso: [](sec_scatter), `IS`, `ISGetBlockSize()`, `ISBlockGetLocalSize()`, `ISGetSize()`, `ISCreateBlock()`, `ISBLOCK` 623 @*/ 624 PetscErrorCode ISBlockGetSize(IS is, PetscInt *size) 625 { 626 PetscFunctionBegin; 627 PetscUseMethod(is, "ISBlockGetSize_C", (IS, PetscInt *), (is, size)); 628 PetscFunctionReturn(PETSC_SUCCESS); 629 } 630 631 static PetscErrorCode ISBlockGetSize_Block(IS is, PetscInt *size) 632 { 633 PetscInt bs, N; 634 635 PetscFunctionBegin; 636 PetscCall(PetscLayoutGetBlockSize(is->map, &bs)); 637 PetscCall(PetscLayoutGetSize(is->map, &N)); 638 *size = N / bs; 639 PetscFunctionReturn(PETSC_SUCCESS); 640 } 641 642 PETSC_EXTERN PetscErrorCode ISCreate_Block(IS is) 643 { 644 IS_Block *sub; 645 646 PetscFunctionBegin; 647 PetscCall(PetscNew(&sub)); 648 is->data = (void *)sub; 649 is->ops[0] = myops; 650 PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockSetIndices_C", ISBlockSetIndices_Block)); 651 PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetIndices_C", ISBlockGetIndices_Block)); 652 PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockRestoreIndices_C", ISBlockRestoreIndices_Block)); 653 PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetSize_C", ISBlockGetSize_Block)); 654 PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISBlockGetLocalSize_C", ISBlockGetLocalSize_Block)); 655 PetscCall(PetscObjectComposeFunction((PetscObject)is, "ISShift_C", ISShift_Block)); 656 PetscFunctionReturn(PETSC_SUCCESS); 657 } 658