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