Actual source code: isblock.c

  1: /* Routines to be used by MatIncreaseOverlap() for BAIJ and SBAIJ matrices */
  2: #include <petscis.h>
  3: #include <petscbt.h>
  4: #include <petsc/private/hashmapi.h>

  6: /*@
  7:   ISCompressIndicesGeneral - convert the indices of an array of `IS` into an array of `ISGENERAL` of block indices

  9:   Input Parameters:
 10: + n     - maximum possible length of the index set
 11: . nkeys - expected number of keys when using `PETSC_USE_CTABLE`
 12: . bs    - the size of block
 13: . imax  - the number of index sets
 14: - is_in - the non-blocked array of index sets

 16:   Output Parameter:
 17: . is_out - the blocked new index set, as `ISGENERAL`, not as `ISBLOCK`

 19:   Level: intermediate

 21: .seealso: [](sec_scatter), `IS`, `ISGENERAL`, `ISExpandIndicesGeneral()`
 22: @*/
 23: PetscErrorCode ISCompressIndicesGeneral(PetscInt n, PetscInt nkeys, PetscInt bs, PetscInt imax, const IS is_in[], IS is_out[])
 24: {
 25:   PetscInt        isz, len, i, j, ival, bbs;
 26:   const PetscInt *idx;
 27:   PetscBool       isblock;
 28: #if defined(PETSC_USE_CTABLE)
 29:   PetscHMapI    gid1_lid1 = NULL;
 30:   PetscInt      tt, gid1, *nidx;
 31:   PetscHashIter tpos;
 32: #else
 33:   PetscInt *nidx;
 34:   PetscInt  Nbs;
 35:   PetscBT   table;
 36: #endif

 38:   PetscFunctionBegin;
 39: #if defined(PETSC_USE_CTABLE)
 40:   PetscCall(PetscHMapICreateWithSize(nkeys / bs, &gid1_lid1));
 41: #else
 42:   Nbs = n / bs;
 43:   PetscCall(PetscMalloc1(Nbs, &nidx));
 44:   PetscCall(PetscBTCreate(Nbs, &table));
 45: #endif
 46:   for (i = 0; i < imax; i++) {
 47:     PetscCall(ISGetLocalSize(is_in[i], &len));
 48:     /* special case where IS is already block IS of the correct size */
 49:     PetscCall(PetscObjectTypeCompare((PetscObject)is_in[i], ISBLOCK, &isblock));
 50:     if (isblock) {
 51:       PetscCall(ISGetBlockSize(is_in[i], &bbs));
 52:       if (bs == bbs) {
 53:         len = len / bs;
 54:         PetscCall(ISBlockGetIndices(is_in[i], &idx));
 55:         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is_in[i]), len, idx, PETSC_COPY_VALUES, is_out + i));
 56:         PetscCall(ISBlockRestoreIndices(is_in[i], &idx));
 57:         continue;
 58:       }
 59:     }
 60:     isz = 0;
 61: #if defined(PETSC_USE_CTABLE)
 62:     PetscCall(PetscHMapIClear(gid1_lid1));
 63: #else
 64:     PetscCall(PetscBTMemzero(Nbs, table));
 65: #endif
 66:     PetscCall(ISGetIndices(is_in[i], &idx));
 67:     for (j = 0; j < len; j++) {
 68:       ival = idx[j] / bs; /* convert the indices into block indices */
 69: #if defined(PETSC_USE_CTABLE)
 70:       PetscCall(PetscHMapIGetWithDefault(gid1_lid1, ival + 1, 0, &tt));
 71:       if (!tt) {
 72:         PetscCall(PetscHMapISet(gid1_lid1, ival + 1, isz + 1));
 73:         isz++;
 74:       }
 75: #else
 76:       PetscCheck(ival <= Nbs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "index greater than mat-dim");
 77:       if (!PetscBTLookupSet(table, ival)) nidx[isz++] = ival;
 78: #endif
 79:     }
 80:     PetscCall(ISRestoreIndices(is_in[i], &idx));

 82: #if defined(PETSC_USE_CTABLE)
 83:     PetscCall(PetscMalloc1(isz, &nidx));
 84:     PetscHashIterBegin(gid1_lid1, tpos);
 85:     j = 0;
 86:     while (!PetscHashIterAtEnd(gid1_lid1, tpos)) {
 87:       PetscHashIterGetKey(gid1_lid1, tpos, gid1);
 88:       PetscHashIterGetVal(gid1_lid1, tpos, tt);
 89:       PetscCheck(tt-- <= isz, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "index greater than array-dim");
 90:       nidx[tt] = gid1 - 1;
 91:       j++;
 92:       PetscHashIterNext(gid1_lid1, tpos);
 93:     }
 94:     PetscCheck(j == isz, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "table error: jj != isz");
 95:     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is_in[i]), isz, nidx, PETSC_OWN_POINTER, is_out + i));
 96: #else
 97:     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is_in[i]), isz, nidx, PETSC_COPY_VALUES, is_out + i));
 98: #endif
 99:   }
100: #if defined(PETSC_USE_CTABLE)
101:   PetscCall(PetscHMapIDestroy(&gid1_lid1));
102: #else
103:   PetscCall(PetscBTDestroy(&table));
104:   PetscCall(PetscFree(nidx));
105: #endif
106:   PetscFunctionReturn(PETSC_SUCCESS);
107: }

109: /*@
110:   ISExpandIndicesGeneral - convert the indices of an array `IS` into non-block indices in an array of `ISGENERAL`

112:   Input Parameters:
113: + n     - the length of the index set (not being used)
114: . nkeys - expected number of keys when `PETSC_USE_CTABLE` is used
115: . bs    - the size of block
116: . imax  - the number of index sets
117: - is_in - the blocked array of index sets, must be as large as `imax`

119:   Output Parameter:
120: . is_out - the non-blocked new index set, as `ISGENERAL`, must be as large as `imax`

122:   Level: intermediate

124: .seealso: [](sec_scatter), `IS`, `ISGENERAL`, `ISCompressIndicesGeneral()`
125: @*/
126: PetscErrorCode ISExpandIndicesGeneral(PetscInt n, PetscInt nkeys, PetscInt bs, PetscInt imax, const IS is_in[], IS is_out[])
127: {
128:   PetscInt        len, i, j, k, *nidx;
129:   const PetscInt *idx;
130:   PetscInt        maxsz;

132:   PetscFunctionBegin;
133:   /* Check max size of is_in[] */
134:   maxsz = 0;
135:   for (i = 0; i < imax; i++) {
136:     PetscCall(ISGetLocalSize(is_in[i], &len));
137:     if (len > maxsz) maxsz = len;
138:   }
139:   PetscCall(PetscMalloc1(maxsz * bs, &nidx));

141:   for (i = 0; i < imax; i++) {
142:     PetscCall(ISGetLocalSize(is_in[i], &len));
143:     PetscCall(ISGetIndices(is_in[i], &idx));
144:     for (j = 0; j < len; ++j) {
145:       for (k = 0; k < bs; k++) nidx[j * bs + k] = idx[j] * bs + k;
146:     }
147:     PetscCall(ISRestoreIndices(is_in[i], &idx));
148:     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is_in[i]), len * bs, nidx, PETSC_COPY_VALUES, is_out + i));
149:   }
150:   PetscCall(PetscFree(nidx));
151:   PetscFunctionReturn(PETSC_SUCCESS);
152: }