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