Date: 2022-03-04T17:37:32+00:00

Actual source code: block.c

      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>
      7: #include <petscviewer.h>

      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;

     15: static PetscErrorCode ISDestroy_Block(IS is)
     16: {
     17:   IS_Block       *sub = (IS_Block*)is->data;

     21:   if (sub->allocated) {PetscFree(sub->idx);}
     22:   PetscObjectComposeFunction((PetscObject)is,"ISBlockSetIndices_C",NULL);
     23:   PetscObjectComposeFunction((PetscObject)is,"ISBlockGetIndices_C",NULL);
     24:   PetscObjectComposeFunction((PetscObject)is,"ISBlockRestoreIndices_C",NULL);
     25:   PetscObjectComposeFunction((PetscObject)is,"ISBlockGetSize_C",NULL);
     26:   PetscObjectComposeFunction((PetscObject)is,"ISBlockGetLocalSize_C",NULL);
     27:   PetscFree(is->data);
     28:   return(0);
     29: }

     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;

     39:   PetscLayoutGetBlockSize(is->map,&bs);
     40:   PetscLayoutGetSize(is->map,&numIdx);
     41:   numIdx /= bs;
     42:   bkey    = key / bs;
     43:   mkey    = key % bs;
     44:   if (mkey < 0) {
     45:     bkey--;
     46:     mkey += bs;
     47:   }
     48:   ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,&sorted);
     49:   if (sorted) {
     50:     PetscFindInt(bkey,numIdx,sub->idx,location);
     51:   } else {
     52:     const PetscInt *idx = sub->idx;

     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:   return(0);
     66: }

     68: static PetscErrorCode ISGetIndices_Block(IS in,const PetscInt *idx[])
     69: {
     70:   IS_Block       *sub = (IS_Block*)in->data;
     72:   PetscInt       i,j,k,bs,n,*ii,*jj;

     75:   PetscLayoutGetBlockSize(in->map, &bs);
     76:   PetscLayoutGetLocalSize(in->map, &n);
     77:   n   /= bs;
     78:   if (bs == 1) *idx = sub->idx;
     79:   else {
     80:     if (n) {
     81:       PetscMalloc1(bs*n,&jj);
     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:   return(0);
     94: }

     96: static PetscErrorCode ISRestoreIndices_Block(IS is,const PetscInt *idx[])
     97: {
     98:   IS_Block       *sub = (IS_Block*)is->data;
     99:   PetscInt       bs;

    103:   PetscLayoutGetBlockSize(is->map, &bs);
    104:   if (bs != 1) {
    105:     PetscFree(*(void**)idx);
    106:   } else {
    107:     /* F90Array1dCreate() inside ISRestoreArrayF90() does not keep array when zero length array */
    108:     if (is->map->n > 0  && *idx != sub->idx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
    109:   }
    110:   return(0);
    111: }

    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;

    121:   MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);
    122:   PetscLayoutGetBlockSize(is->map, &bs);
    123:   PetscLayoutGetLocalSize(is->map, &n);
    124:   n   /= bs;
    125:   if (size == 1) {
    126:     PetscMalloc1(n,&ii);
    127:     for (i=0; i<n; i++) ii[idx[i]] = i;
    128:     ISCreateBlock(PETSC_COMM_SELF,bs,n,ii,PETSC_OWN_POINTER,isout);
    129:     ISSetPermutation(*isout);
    130:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No inversion written yet for block IS");
    131:   return(0);
    132: }

    134: static PetscErrorCode ISView_Block(IS is, PetscViewer viewer)
    135: {
    136:   IS_Block       *sub = (IS_Block*)is->data;
    138:   PetscInt       i,bs,n,*idx = sub->idx;
    139:   PetscBool      iascii,ibinary;

    142:   PetscLayoutGetBlockSize(is->map, &bs);
    143:   PetscLayoutGetLocalSize(is->map, &n);
    144:   n   /= bs;
    145:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    146:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary);
    147:   if (iascii) {
    148:     PetscViewerFormat fmt;

    150:     PetscViewerGetFormat(viewer,&fmt);
    151:     if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
    152:       IS             ist;
    153:       const char     *name;
    154:       const PetscInt *idx;
    155:       PetscInt       n;

    157:       PetscObjectGetName((PetscObject)is,&name);
    158:       ISGetLocalSize(is,&n);
    159:       ISGetIndices(is,&idx);
    160:       ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idx,PETSC_USE_POINTER,&ist);
    161:       PetscObjectSetName((PetscObject)ist,name);
    162:       ISView(ist,viewer);
    163:       ISDestroy(&ist);
    164:       ISRestoreIndices(is,&idx);
    165:     } else {
    166:       PetscBool isperm;

    168:       ISGetInfo(is,IS_PERMUTATION,IS_GLOBAL,PETSC_FALSE,&isperm);
    169:       if (isperm) {PetscViewerASCIIPrintf(viewer,"Block Index set is permutation\n");}
    170:       PetscViewerASCIIPushSynchronized(viewer);
    171:       PetscViewerASCIISynchronizedPrintf(viewer,"Block size %D\n",bs);
    172:       PetscViewerASCIISynchronizedPrintf(viewer,"Number of block indices in set %D\n",n);
    173:       PetscViewerASCIISynchronizedPrintf(viewer,"The first indices of each block are\n");
    174:       for (i=0; i<n; i++) {
    175:         PetscViewerASCIISynchronizedPrintf(viewer,"Block %D Index %D\n",i,idx[i]);
    176:       }
    177:       PetscViewerFlush(viewer);
    178:       PetscViewerASCIIPopSynchronized(viewer);
    179:     }
    180:   } else if (ibinary) {
    181:     ISView_Binary(is,viewer);
    182:   }
    183:   return(0);
    184: }

    186: static PetscErrorCode ISSort_Block(IS is)
    187: {
    188:   IS_Block       *sub = (IS_Block*)is->data;
    189:   PetscInt       bs, n;

    193:   PetscLayoutGetBlockSize(is->map, &bs);
    194:   PetscLayoutGetLocalSize(is->map, &n);
    195:   PetscIntSortSemiOrdered(n/bs,sub->idx);
    196:   return(0);
    197: }

    199: static PetscErrorCode ISSortRemoveDups_Block(IS is)
    200: {
    201:   IS_Block       *sub = (IS_Block*)is->data;
    202:   PetscInt       bs, n, nb;
    203:   PetscBool      sorted;

    207:   PetscLayoutGetBlockSize(is->map, &bs);
    208:   PetscLayoutGetLocalSize(is->map, &n);
    209:   nb   = n/bs;
    210:   ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,&sorted);
    211:   if (sorted) {
    212:     PetscSortedRemoveDupsInt(&nb,sub->idx);
    213:   } else {
    214:     PetscSortRemoveDupsInt(&nb,sub->idx);
    215:   }
    216:   PetscLayoutDestroy(&is->map);
    217:   PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is), nb*bs, PETSC_DECIDE, bs, &is->map);
    218:   return(0);
    219: }

    221: static PetscErrorCode ISSorted_Block(IS is,PetscBool  *flg)
    222: {

    226:   ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,flg);
    227:   return(0);
    228: }

    230: static PetscErrorCode ISSortedLocal_Block(IS is,PetscBool *flg)
    231: {
    232:   IS_Block       *sub = (IS_Block*)is->data;
    233:   PetscInt       n, bs, i, *idx;

    237:   PetscLayoutGetLocalSize(is->map, &n);
    238:   PetscLayoutGetBlockSize(is->map, &bs);
    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:   return(0);
    245: }

    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;

    255:   PetscLayoutGetLocalSize(is->map, &n);
    256:   PetscLayoutGetBlockSize(is->map, &bs);
    257:   n   /= bs;
    258:   idx  = sub->idx;
    259:   ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,&sortedLocal);
    260:   if (!sortedLocal) {
    261:     PetscMalloc1(n, &idxcopy);
    262:     PetscArraycpy(idxcopy, idx, n);
    263:     PetscIntSortSemiOrdered(n, idxcopy);
    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:   PetscFree(idxcopy);
    270:   return(0);
    271: }

    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;

    281:   PetscLayoutGetLocalSize(is->map, &n);
    282:   PetscLayoutGetBlockSize(is->map, &bs);
    283:   n   /= bs;
    284:   idx  = sub->idx;
    285:   ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,&sortedLocal);
    286:   if (!sortedLocal) {
    287:     PetscMalloc1(n, &idxcopy);
    288:     PetscArraycpy(idxcopy, idx, n);
    289:     PetscIntSortSemiOrdered(n, idxcopy);
    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:   PetscFree(idxcopy);
    296:   return(0);
    297: }

    299: static PetscErrorCode ISIntervalLocal_Block(IS is,PetscBool *flg)
    300: {
    301:   IS_Block       *sub = (IS_Block*)is->data;
    302:   PetscInt       n, bs, i, *idx;

    306:   PetscLayoutGetLocalSize(is->map, &n);
    307:   PetscLayoutGetBlockSize(is->map, &bs);
    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:   return(0);
    314: }

    316: static PetscErrorCode ISDuplicate_Block(IS is,IS *newIS)
    317: {
    319:   IS_Block       *sub = (IS_Block*)is->data;
    320:   PetscInt        bs, n;

    323:   PetscLayoutGetBlockSize(is->map, &bs);
    324:   PetscLayoutGetLocalSize(is->map, &n);
    325:   n   /= bs;
    326:   ISCreateBlock(PetscObjectComm((PetscObject)is),bs,n,sub->idx,PETSC_COPY_VALUES,newIS);
    327:   return(0);
    328: }

    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;

    337:   PetscLayoutGetBlockSize(is->map, &bs);
    338:   PetscLayoutGetLocalSize(is->map, &n);
    339:   PetscLayoutGetSize(is->map, &N);
    340:   PetscLayoutGetBlockSize(isy->map, &bsy);
    341:   PetscLayoutGetLocalSize(isy->map, &ny);
    342:   PetscLayoutGetSize(isy->map, &Ny);
    343:   if (n != ny || N != Ny || bs != bsy) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Index sets incompatible");
    344:   PetscArraycpy(isy_block->idx,is_block->idx,(n/bs));
    345:   return(0);
    346: }

    348: static PetscErrorCode ISOnComm_Block(IS is,MPI_Comm comm,PetscCopyMode mode,IS *newis)
    349: {
    351:   IS_Block       *sub = (IS_Block*)is->data;
    352:   PetscInt       bs, n;

    355:   if (mode == PETSC_OWN_POINTER) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Cannot use PETSC_OWN_POINTER");
    356:   PetscLayoutGetBlockSize(is->map, &bs);
    357:   PetscLayoutGetLocalSize(is->map, &n);
    358:   ISCreateBlock(comm,bs,n/bs,sub->idx,mode,newis);
    359:   return(0);
    360: }

    362: static PetscErrorCode ISSetBlockSize_Block(IS is,PetscInt bs)
    363: {

    367:   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);
    368:   PetscLayoutSetBlockSize(is->map, bs);
    369:   return(0);
    370: }

    372: static PetscErrorCode ISToGeneral_Block(IS inis)
    373: {
    374:   IS_Block       *sub   = (IS_Block*)inis->data;
    375:   PetscInt       bs,n;
    376:   const PetscInt *idx;

    380:   ISGetBlockSize(inis,&bs);
    381:   ISGetLocalSize(inis,&n);
    382:   ISGetIndices(inis,&idx);
    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:     ISSetType(inis,ISGENERAL);
    387:     ISGeneralSetIndices(inis,n,idx,mode);
    388:   } else {
    389:     ISSetType(inis,ISGENERAL);
    390:     ISGeneralSetIndices(inis,n,idx,PETSC_OWN_POINTER);
    391:   }
    392:   return(0);
    393: }

    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};

    424: /*@
    425:    ISBlockSetIndices - Set integers representing blocks of indices in an index set.

    427:    Collective on IS

    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

    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.

    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}.

    446:    Level: beginner

    448: .seealso: ISCreateStride(), ISCreateGeneral(), ISAllGather(), ISCreateBlock(), ISBLOCK, ISGeneralSetIndices()
    449: @*/
    450: PetscErrorCode  ISBlockSetIndices(IS is,PetscInt bs,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
    451: {

    455:   ISClearInfoCache(is,PETSC_FALSE);
    456:   PetscUseMethod(is,"ISBlockSetIndices_C",(IS,PetscInt,PetscInt,const PetscInt[],PetscCopyMode),(is,bs,n,idx,mode));
    457:   return(0);
    458: }

    460: static PetscErrorCode  ISBlockSetIndices_Block(IS is,PetscInt bs,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
    461: {
    463:   PetscInt       i,min,max;
    464:   IS_Block       *sub = (IS_Block*)is->data;
    465:   PetscLayout    map;

    468:   if (bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"block size < 1");
    469:   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");

    472:   PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is),n*bs,is->map->N,bs,&map);
    473:   PetscLayoutDestroy(&is->map);
    474:   is->map = map;

    476:   if (sub->allocated) {PetscFree(sub->idx);}
    477:   if (mode == PETSC_COPY_VALUES) {
    478:     PetscMalloc1(n,&sub->idx);
    479:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
    480:     PetscArraycpy(sub->idx,idx,n);
    481:     sub->allocated = PETSC_TRUE;
    482:   } else if (mode == PETSC_OWN_POINTER) {
    483:     sub->idx = (PetscInt*) idx;
    484:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
    485:     sub->allocated = PETSC_TRUE;
    486:   } else if (mode == PETSC_USE_POINTER) {
    487:     sub->idx = (PetscInt*) idx;
    488:     sub->allocated = PETSC_FALSE;
    489:   }

    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:   return(0);
    504: }

    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.

    510:    Collective

    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

    519:    Output Parameter:
    520: .  is - the new index set

    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.

    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}.

    532:    Level: beginner

    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: {

    542:   if (bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"block size < 1");
    543:   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");

    546:   ISCreate(comm,is);
    547:   ISSetType(*is,ISBLOCK);
    548:   ISBlockSetIndices(*is,bs,n,idx,mode);
    549:   return(0);
    550: }

    552: static PetscErrorCode  ISBlockGetIndices_Block(IS is,const PetscInt *idx[])
    553: {
    554:   IS_Block *sub = (IS_Block*)is->data;

    557:   *idx = sub->idx;
    558:   return(0);
    559: }

    561: static PetscErrorCode  ISBlockRestoreIndices_Block(IS is,const PetscInt *idx[])
    562: {
    564:   return(0);
    565: }

    567: /*@C
    568:    ISBlockGetIndices - Gets the indices associated with each block.

    570:    Not Collective

    572:    Input Parameter:
    573: .  is - the index set

    575:    Output Parameter:
    576: .  idx - the integer indices, one for each block and count of block not indices

    578:    Level: intermediate

    580: .seealso: ISGetIndices(), ISBlockRestoreIndices(), ISBLOCK, ISBlockSetIndices(), ISCreateBlock()
    581: @*/
    582: PetscErrorCode  ISBlockGetIndices(IS is,const PetscInt *idx[])
    583: {

    587:   PetscUseMethod(is,"ISBlockGetIndices_C",(IS,const PetscInt*[]),(is,idx));
    588:   return(0);
    589: }

    591: /*@C
    592:    ISBlockRestoreIndices - Restores the indices associated with each block.

    594:    Not Collective

    596:    Input Parameter:
    597: .  is - the index set

    599:    Output Parameter:
    600: .  idx - the integer indices

    602:    Level: intermediate

    604: .seealso: ISRestoreIndices(), ISBlockGetIndices()
    605: @*/
    606: PetscErrorCode  ISBlockRestoreIndices(IS is,const PetscInt *idx[])
    607: {

    611:   PetscUseMethod(is,"ISBlockRestoreIndices_C",(IS,const PetscInt*[]),(is,idx));
    612:   return(0);
    613: }

    615: /*@
    616:    ISBlockGetLocalSize - Returns the local number of blocks in the index set.

    618:    Not Collective

    620:    Input Parameter:
    621: .  is - the index set

    623:    Output Parameter:
    624: .  size - the local number of blocks

    626:    Level: intermediate

    628: .seealso: ISGetBlockSize(), ISBlockGetSize(), ISGetSize(), ISCreateBlock(), ISBLOCK
    629: @*/
    630: PetscErrorCode  ISBlockGetLocalSize(IS is,PetscInt *size)
    631: {

    635:   PetscUseMethod(is,"ISBlockGetLocalSize_C",(IS,PetscInt*),(is,size));
    636:   return(0);
    637: }

    639: static PetscErrorCode  ISBlockGetLocalSize_Block(IS is,PetscInt *size)
    640: {
    641:   PetscInt       bs, n;

    645:   PetscLayoutGetBlockSize(is->map, &bs);
    646:   PetscLayoutGetLocalSize(is->map, &n);
    647:   *size = n/bs;
    648:   return(0);
    649: }

    651: /*@
    652:    ISBlockGetSize - Returns the global number of blocks in the index set.

    654:    Not Collective

    656:    Input Parameter:
    657: .  is - the index set

    659:    Output Parameter:
    660: .  size - the global number of blocks

    662:    Level: intermediate

    664: .seealso: ISGetBlockSize(), ISBlockGetLocalSize(), ISGetSize(), ISCreateBlock(), ISBLOCK
    665: @*/
    666: PetscErrorCode  ISBlockGetSize(IS is,PetscInt *size)
    667: {

    671:   PetscUseMethod(is,"ISBlockGetSize_C",(IS,PetscInt*),(is,size));
    672:   return(0);
    673: }

    675: static PetscErrorCode  ISBlockGetSize_Block(IS is,PetscInt *size)
    676: {
    677:   PetscInt       bs, N;

    681:   PetscLayoutGetBlockSize(is->map, &bs);
    682:   PetscLayoutGetSize(is->map, &N);
    683:   *size = N/bs;
    684:   return(0);
    685: }

    687: PETSC_EXTERN PetscErrorCode ISCreate_Block(IS is)
    688: {
    690:   IS_Block       *sub;

    693:   PetscNewLog(is,&sub);
    694:   is->data = (void *) sub;
    695:   PetscMemcpy(is->ops,&myops,sizeof(myops));
    696:   PetscObjectComposeFunction((PetscObject)is,"ISBlockSetIndices_C",ISBlockSetIndices_Block);
    697:   PetscObjectComposeFunction((PetscObject)is,"ISBlockGetIndices_C",ISBlockGetIndices_Block);
    698:   PetscObjectComposeFunction((PetscObject)is,"ISBlockRestoreIndices_C",ISBlockRestoreIndices_Block);
    699:   PetscObjectComposeFunction((PetscObject)is,"ISBlockGetSize_C",ISBlockGetSize_Block);
    700:   PetscObjectComposeFunction((PetscObject)is,"ISBlockGetLocalSize_C",ISBlockGetLocalSize_Block);
    701:   return(0);
    702: }