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