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