Actual source code: general.c

  1: /*
  2:      Provides the functions for index sets (IS) defined by a list of integers.
  3: */
 4:  #include src/vec/is/impls/general/general.h

  6: EXTERN PetscErrorCode VecInitializePackage(char *);

 10: PetscErrorCode ISDuplicate_General(IS is,IS *newIS)
 11: {
 13:   IS_General     *sub = (IS_General *)is->data;

 16:   ISCreateGeneral(is->comm,sub->n,sub->idx,newIS);
 17:   return(0);
 18: }

 22: PetscErrorCode ISDestroy_General(IS is)
 23: {
 24:   IS_General     *is_general = (IS_General*)is->data;

 28:   if (is_general->allocated) {
 29:     PetscFree(is_general->idx);
 30:   }
 31:   PetscFree(is_general);
 32:   PetscLogObjectDestroy(is);
 33:   PetscHeaderDestroy(is);
 34:   return(0);
 35: }

 39: PetscErrorCode ISIdentity_General(IS is,PetscTruth *ident)
 40: {
 41:   IS_General *is_general = (IS_General*)is->data;
 42:   PetscInt   i,n = is_general->n,*idx = is_general->idx;

 45:   is->isidentity = PETSC_TRUE;
 46:   *ident         = PETSC_TRUE;
 47:   for (i=0; i<n; i++) {
 48:     if (idx[i] != i) {
 49:       is->isidentity = PETSC_FALSE;
 50:       *ident         = PETSC_FALSE;
 51:       break;
 52:     }
 53:   }
 54:   return(0);
 55: }

 59: PetscErrorCode ISGetIndices_General(IS in,PetscInt **idx)
 60: {
 61:   IS_General *sub = (IS_General*)in->data;

 64:   *idx = sub->idx;
 65:   return(0);
 66: }

 70: PetscErrorCode ISRestoreIndices_General(IS in,PetscInt **idx)
 71: {
 72:   IS_General *sub = (IS_General*)in->data;

 75:   if (*idx != sub->idx) {
 76:     SETERRQ(PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
 77:   }
 78:   return(0);
 79: }

 83: PetscErrorCode ISGetSize_General(IS is,PetscInt *size)
 84: {
 85:   IS_General *sub = (IS_General *)is->data;

 88:   *size = sub->N;
 89:   return(0);
 90: }

 94: PetscErrorCode ISGetLocalSize_General(IS is,PetscInt *size)
 95: {
 96:   IS_General *sub = (IS_General *)is->data;

 99:   *size = sub->n;
100:   return(0);
101: }

105: PetscErrorCode ISInvertPermutation_General(IS is,PetscInt nlocal,IS *isout)
106: {
107:   IS_General     *sub = (IS_General *)is->data;
108:   PetscInt       i,*ii,n = sub->n,*idx = sub->idx,nstart;
109:   PetscMPIInt    size;
110:   IS             istmp,nistmp;

114:   MPI_Comm_size(is->comm,&size);
115:   if (size == 1) {
116:     PetscMalloc(n*sizeof(PetscInt),&ii);
117:     for (i=0; i<n; i++) {
118:       ii[idx[i]] = i;
119:     }
120:     ISCreateGeneral(PETSC_COMM_SELF,n,ii,isout);
121:     ISSetPermutation(*isout);
122:     PetscFree(ii);
123:   } else {
124:     /* crude, nonscalable get entire IS on each processor */
125:     ISAllGather(is,&istmp);
126:     ISSetPermutation(istmp);
127:     ISInvertPermutation(istmp,PETSC_DECIDE,&nistmp);
128:     ISDestroy(istmp);
129:     /* get the part we need */
130:     MPI_Scan(&nlocal,&nstart,1,MPIU_INT,MPI_SUM,is->comm);
131:     nstart -= nlocal;
132:     ISGetIndices(nistmp,&idx);
133:     ISCreateGeneral(is->comm,nlocal,idx+nstart,isout);
134:     ISRestoreIndices(nistmp,&idx);
135:     ISDestroy(nistmp);
136:   }
137:   return(0);
138: }

142: PetscErrorCode ISView_General(IS is,PetscViewer viewer)
143: {
144:   IS_General     *sub = (IS_General *)is->data;
146:   PetscInt       i,n = sub->n,*idx = sub->idx;
147:   PetscTruth     iascii;

150:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
151:   if (iascii) {
152:     MPI_Comm    comm;
153:     PetscMPIInt rank,size;

155:     PetscObjectGetComm((PetscObject)viewer,&comm);
156:     MPI_Comm_rank(comm,&rank);
157:     MPI_Comm_size(comm,&size);

159:     if (size > 1) {
160:       if (is->isperm) {
161:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutation\n",rank);
162:       }
163:       PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
164:       for (i=0; i<n; i++) {
165:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,idx[i]);
166:       }
167:     } else {
168:       if (is->isperm) {
169:         PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutation\n");
170:       }
171:       PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
172:       for (i=0; i<n; i++) {
173:         PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i,idx[i]);
174:       }
175:     }
176:     PetscViewerFlush(viewer);
177:   } else {
178:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for this object",((PetscObject)viewer)->type_name);
179:   }
180:   return(0);
181: }

185: PetscErrorCode ISSort_General(IS is)
186: {
187:   IS_General     *sub = (IS_General *)is->data;

191:   if (sub->sorted) return(0);
192:   PetscSortInt(sub->n,sub->idx);
193:   sub->sorted = PETSC_TRUE;
194:   return(0);
195: }

199: PetscErrorCode ISSorted_General(IS is,PetscTruth *flg)
200: {
201:   IS_General *sub = (IS_General *)is->data;

204:   *flg = sub->sorted;
205:   return(0);
206: }

208: static struct _ISOps myops = { ISGetSize_General,
209:                                ISGetLocalSize_General,
210:                                ISGetIndices_General,
211:                                ISRestoreIndices_General,
212:                                ISInvertPermutation_General,
213:                                ISSort_General,
214:                                ISSorted_General,
215:                                ISDuplicate_General,
216:                                ISDestroy_General,
217:                                ISView_General,
218:                                ISIdentity_General };

222: PetscErrorCode ISCreateGeneral_Private(MPI_Comm comm,IS *is)
223: {
225:   IS             Nindex = *is;
226:   IS_General     *sub = (IS_General*)Nindex->data;
227:   PetscInt       n = sub->n,i,min,max;
228:   const PetscInt *idx = sub->idx;
229:   PetscTruth     sorted = PETSC_TRUE;
230:   PetscTruth     flg;

234:   if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
236:   *is = PETSC_NULL;
237: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
238:   VecInitializePackage(PETSC_NULL);
239: #endif

241:   MPI_Allreduce(&n,&sub->N,1,MPIU_INT,MPI_SUM,comm);
242:   for (i=1; i<n; i++) {
243:     if (idx[i] < idx[i-1]) {sorted = PETSC_FALSE; break;}
244:   }
245:   if (n) {min = max = idx[0];} else {min = max = 0;}
246:   for (i=1; i<n; i++) {
247:     if (idx[i] < min) min = idx[i];
248:     if (idx[i] > max) max = idx[i];
249:   }
250:   sub->sorted     = sorted;
251:   Nindex->min     = min;
252:   Nindex->max     = max;
253:   PetscMemcpy(Nindex->ops,&myops,sizeof(myops));
254:   Nindex->isperm     = PETSC_FALSE;
255:   Nindex->isidentity = PETSC_FALSE;
256:   PetscOptionsHasName(PETSC_NULL,"-is_view",&flg);
257:   if (flg) {
258:     ISView(Nindex,PETSC_VIEWER_STDOUT_(Nindex->comm));
259:   }
260:   *is = Nindex;
261:   return(0);
262: }

264: /*@C
265:    ISCreateGeneral - Creates a data structure for an index set 
266:    containing a list of integers.

268:    Collective on MPI_Comm

270:    Input Parameters:
271: +  comm - the MPI communicator
272: .  n - the length of the index set
273: -  idx - the list of integers

275:    Output Parameter:
276: .  is - the new index set

278:    Notes:
279:    The index array is copied to internally allocated storage. After the call,
280:    the user can free the index array.

282:    When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
283:    conceptually the same as MPI_Group operations. The IS are then
284:    distributed sets of indices and thus certain operations on them are
285:    collective.

287:    Level: beginner

289:   Concepts: index sets^creating
290:   Concepts: IS^creating

292: .seealso: ISCreateGeneralWithArray(), ISCreateStride(), ISCreateBlock(), ISAllGather()
293: @*/
294: PetscErrorCode ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],IS *is)
295: {
297:   IS             Nindex;
298:   IS_General     *sub;

302:   if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
304:   *is = PETSC_NULL;
305: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
306:   VecInitializePackage(PETSC_NULL);
307: #endif

309:   PetscHeaderCreate(Nindex,_p_IS,struct _ISOps,IS_COOKIE,IS_GENERAL,"IS",comm,ISDestroy,ISView);
310:   PetscLogObjectCreate(Nindex);
311:   PetscNew(IS_General,&sub);
312:   PetscLogObjectMemory(Nindex,sizeof(IS_General)+n*sizeof(PetscInt)+sizeof(struct _p_IS));
313:   PetscMalloc(n*sizeof(PetscInt),&sub->idx);
314:   PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));
315:   sub->n         = n;
316:   sub->allocated = PETSC_TRUE;
317:   Nindex->data   = (void*)sub;

319:   *is = Nindex;
320:   ISCreateGeneral_Private(comm,is);

322:   return(0);
323: }

325: /*@C
326:    ISCreateGeneralWithArray - Creates a data structure for an index set 
327:    containing a list of integers.

329:    Collective on MPI_Comm

331:    Input Parameters:
332: +  comm - the MPI communicator
333: .  n - the length of the index set
334: -  idx - the list of integers

336:    Output Parameter:
337: .  is - the new index set

339:    Notes:
340:    Unlike with ISCreateGeneral, the indices are not copied to internally
341:    allocated storage. The user array is not freed by ISDestroy.

343:    When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
344:    conceptually the same as MPI_Group operations. The IS are then
345:    distributed sets of indices and thus certain operations on them are collective.

347:    Level: beginner

349:   Concepts: index sets^creating
350:   Concepts: IS^creating

352: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather()
353: @*/
354: PetscErrorCode ISCreateGeneralWithArray(MPI_Comm comm,PetscInt n,PetscInt idx[],IS *is)
355: {
357:   IS             Nindex;
358:   IS_General     *sub;

362:   if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
364:   *is = PETSC_NULL;
365: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
366:   VecInitializePackage(PETSC_NULL);
367: #endif

369:   PetscHeaderCreate(Nindex,_p_IS,struct _ISOps,IS_COOKIE,IS_GENERAL,"IS",comm,ISDestroy,ISView);
370:   PetscLogObjectCreate(Nindex);
371:   PetscNew(IS_General,&sub);
372:   PetscLogObjectMemory(Nindex,sizeof(IS_General)+n*sizeof(PetscInt)+sizeof(struct _p_IS));
373:   sub->idx       = idx;
374:   sub->n         = n;
375:   sub->allocated = PETSC_FALSE;
376:   Nindex->data   = (void*)sub;

378:   *is = Nindex;
379:   ISCreateGeneral_Private(comm,is);

381:   return(0);
382: }