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