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