Actual source code: general.c

petsc-3.8.2 2017-11-09
Report Typos and Errors

  2: /*
  3:      Provides the functions for index sets (IS) defined by a list of integers.
  4: */
  5:  #include <../src/vec/is/is/impls/general/general.h>
  6:  #include <petscvec.h>
  7:  #include <petscviewer.h>
  8: #include <petscviewerhdf5.h>

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

 17:   PetscLayoutGetLocalSize(is->map, &n);
 18:   ISCreateGeneral(PetscObjectComm((PetscObject) is), n, sub->idx, PETSC_COPY_VALUES, newIS);
 19:   return(0);
 20: }

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

 28:   if (is_general->allocated) {PetscFree(is_general->idx);}
 29:   PetscObjectComposeFunction((PetscObject)is,"ISGeneralSetIndices_C",NULL);
 30:   PetscFree(is->data);
 31:   return(0);
 32: }

 34: static PetscErrorCode ISIdentity_General(IS is, PetscBool *ident)
 35: {
 36:   IS_General *is_general = (IS_General*)is->data;
 37:   PetscInt   i,n,*idx = is_general->idx;

 41:   PetscLayoutGetLocalSize(is->map, &n);
 42:   is->isidentity = PETSC_TRUE;
 43:   *ident         = PETSC_TRUE;
 44:   for (i=0; i<n; i++) {
 45:     if (idx[i] != i) {
 46:       is->isidentity = PETSC_FALSE;
 47:       *ident         = PETSC_FALSE;
 48:       break;
 49:     }
 50:   }
 51:   return(0);
 52: }

 54: static PetscErrorCode ISCopy_General(IS is,IS isy)
 55: {
 56:   IS_General     *is_general = (IS_General*)is->data,*isy_general = (IS_General*)isy->data;
 57:   PetscInt       n, N, ny, Ny;

 61:   PetscLayoutGetLocalSize(is->map, &n);
 62:   PetscLayoutGetSize(is->map, &N);
 63:   PetscLayoutGetLocalSize(isy->map, &ny);
 64:   PetscLayoutGetSize(isy->map, &Ny);
 65:   if (n != ny || N != Ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Index sets incompatible");
 66:   isy_general->sorted = is_general->sorted;
 67:   PetscMemcpy(isy_general->idx,is_general->idx,n*sizeof(PetscInt));
 68:   return(0);
 69: }

 71: static PetscErrorCode ISOnComm_General(IS is,MPI_Comm comm,PetscCopyMode mode,IS *newis)
 72: {
 74:   IS_General     *sub = (IS_General*)is->data;
 75:   PetscInt       n;

 78:   if (mode == PETSC_OWN_POINTER) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Cannot use PETSC_OWN_POINTER");
 79:   PetscLayoutGetLocalSize(is->map, &n);
 80:   ISCreateGeneral(comm,n,sub->idx,mode,newis);
 81:   return(0);
 82: }

 84: static PetscErrorCode ISSetBlockSize_General(IS is,PetscInt bs)
 85: {
 86: #if defined(PETSC_USE_DEBUG)
 87:   IS_General    *sub = (IS_General*)is->data;
 88:   PetscInt       n;
 89: #endif

 93:   PetscLayoutSetBlockSize(is->map, bs);
 94: #if defined(PETSC_USE_DEBUG)
 95:   PetscLayoutGetLocalSize(is->map, &n);
 96:   {
 97:     PetscInt i,j;
 98:     for (i=0; i<n; i+=bs) {
 99:       for (j=0; j<bs; j++) {
100:         if (sub->idx[i+j] != sub->idx[i]+j) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Index set does not have block structure, cannot set block size to %D",bs);
101:       }
102:     }
103:   }
104: #endif
105:   return(0);
106: }

108: static PetscErrorCode ISContiguousLocal_General(IS is,PetscInt gstart,PetscInt gend,PetscInt *start,PetscBool *contig)
109: {
110:   IS_General *sub = (IS_General*)is->data;
111:   PetscInt   n,i,p;

115:   *start  = 0;
116:   *contig = PETSC_TRUE;
117:   PetscLayoutGetLocalSize(is->map, &n);
118:   if (!n) return(0);
119:   p = sub->idx[0];
120:   if (p < gstart) goto nomatch;
121:   *start = p - gstart;
122:   if (n > gend-p) goto nomatch;
123:   for (i=1; i<n; i++,p++) {
124:     if (sub->idx[i] != p+1) goto nomatch;
125:   }
126:   return(0);
127: nomatch:
128:   *start  = -1;
129:   *contig = PETSC_FALSE;
130:   return(0);
131: }

133: static PetscErrorCode ISLocate_General(IS is,PetscInt key,PetscInt *location)
134: {
135:   IS_General     *sub = (IS_General*)is->data;
136:   PetscInt       numIdx, i;

140:   PetscLayoutGetLocalSize(is->map,&numIdx);
141:   if (sub->sorted) { PetscFindInt(key,numIdx,sub->idx,location);}
142:   else {
143:     const PetscInt *idx = sub->idx;

145:     *location = -1;
146:     for (i = 0; i < numIdx; i++) {
147:       if (idx[i] == key) {
148:         *location = i;
149:         return(0);
150:       }
151:     }
152:   }
153:   return(0);
154: }

156: static PetscErrorCode ISGetIndices_General(IS in,const PetscInt *idx[])
157: {
158:   IS_General *sub = (IS_General*)in->data;

161:   *idx = sub->idx;
162:   return(0);
163: }

165: static PetscErrorCode ISRestoreIndices_General(IS in,const PetscInt *idx[])
166: {
167:   IS_General *sub = (IS_General*)in->data;

170:   if (*idx != sub->idx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
171:   return(0);
172: }

174: static PetscErrorCode ISGetSize_General(IS is,PetscInt *size)
175: {

179:   PetscLayoutGetSize(is->map, size);
180:   return(0);
181: }

183: static PetscErrorCode ISGetLocalSize_General(IS is,PetscInt *size)
184: {

188:   PetscLayoutGetLocalSize(is->map, size);
189:   return(0);
190: }

192: static PetscErrorCode ISInvertPermutation_General(IS is,PetscInt nlocal,IS *isout)
193: {
194:   IS_General     *sub = (IS_General*)is->data;
195:   PetscInt       i,*ii,n,nstart;
196:   const PetscInt *idx = sub->idx;
197:   PetscMPIInt    size;
198:   IS             istmp,nistmp;

202:   PetscLayoutGetLocalSize(is->map, &n);
203:   MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);
204:   if (size == 1) {
205:     PetscMalloc1(n,&ii);
206:     for (i=0; i<n; i++) ii[idx[i]] = i;
207:     ISCreateGeneral(PETSC_COMM_SELF,n,ii,PETSC_OWN_POINTER,isout);
208:     ISSetPermutation(*isout);
209:   } else {
210:     /* crude, nonscalable get entire IS on each processor */
211:     if (nlocal == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Do not yet support nlocal of PETSC_DECIDE");
212:     ISAllGather(is,&istmp);
213:     ISSetPermutation(istmp);
214:     ISInvertPermutation(istmp,PETSC_DECIDE,&nistmp);
215:     ISDestroy(&istmp);
216:     /* get the part we need */
217:     MPI_Scan(&nlocal,&nstart,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)is));
218: #if defined(PETSC_USE_DEBUG)
219:     {
220:       PetscInt    N;
221:       PetscMPIInt rank;
222:       MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
223:       PetscLayoutGetSize(is->map, &N);
224:       if (rank == size-1) {
225:         if (nstart != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of nlocal lengths %d != total IS length %d",nstart,N);
226:       }
227:     }
228: #endif
229:     nstart -= nlocal;
230:     ISGetIndices(nistmp,&idx);
231:     ISCreateGeneral(PetscObjectComm((PetscObject)is),nlocal,idx+nstart,PETSC_COPY_VALUES,isout);
232:     ISRestoreIndices(nistmp,&idx);
233:     ISDestroy(&nistmp);
234:   }
235:   return(0);
236: }

238: #if defined(PETSC_HAVE_HDF5)
239: static PetscErrorCode ISView_General_HDF5(IS is, PetscViewer viewer)
240: {
241:   hid_t           filespace;  /* file dataspace identifier */
242:   hid_t           chunkspace; /* chunk dataset property identifier */
243:   hid_t           plist_id;   /* property list identifier */
244:   hid_t           dset_id;    /* dataset identifier */
245:   hid_t           memspace;   /* memory dataspace identifier */
246:   hid_t           inttype;    /* int type (H5T_NATIVE_INT or H5T_NATIVE_LLONG) */
247:   hid_t           file_id, group;
248:   hsize_t         dim, maxDims[3], dims[3], chunkDims[3], count[3],offset[3];
249:   PetscInt        bs, N, n, timestep, low;
250:   const PetscInt *ind;
251:   const char     *isname;
252:   PetscErrorCode  ierr;

255:   ISGetBlockSize(is,&bs);
256:   PetscViewerHDF5OpenGroup(viewer, &file_id, &group);
257:   PetscViewerHDF5GetTimestep(viewer, &timestep);

259:   /* Create the dataspace for the dataset.
260:    *
261:    * dims - holds the current dimensions of the dataset
262:    *
263:    * maxDims - holds the maximum dimensions of the dataset (unlimited
264:    * for the number of time steps with the current dimensions for the
265:    * other dimensions; so only additional time steps can be added).
266:    *
267:    * chunkDims - holds the size of a single time step (required to
268:    * permit extending dataset).
269:    */
270:   dim = 0;
271:   if (timestep >= 0) {
272:     dims[dim]      = timestep+1;
273:     maxDims[dim]   = H5S_UNLIMITED;
274:     chunkDims[dim] = 1;
275:     ++dim;
276:   }
277:   ISGetSize(is, &N);
278:   ISGetLocalSize(is, &n);
279:   PetscHDF5IntCast(N/bs,dims + dim);

281:   maxDims[dim]   = dims[dim];
282:   chunkDims[dim] = dims[dim];
283:   ++dim;
284:   if (bs >= 1) {
285:     dims[dim]      = bs;
286:     maxDims[dim]   = dims[dim];
287:     chunkDims[dim] = dims[dim];
288:     ++dim;
289:   }
290:   PetscStackCallHDF5Return(filespace,H5Screate_simple,(dim, dims, maxDims));

292: #if defined(PETSC_USE_64BIT_INDICES)
293:   inttype = H5T_NATIVE_LLONG;
294: #else
295:   inttype = H5T_NATIVE_INT;
296: #endif

298:   /* Create the dataset with default properties and close filespace */
299:   PetscObjectGetName((PetscObject) is, &isname);
300:   if (!H5Lexists(group, isname, H5P_DEFAULT)) {
301:     /* Create chunk */
302:     PetscStackCallHDF5Return(chunkspace,H5Pcreate,(H5P_DATASET_CREATE));
303:     PetscStackCallHDF5(H5Pset_chunk,(chunkspace, dim, chunkDims));

305: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
306:     PetscStackCallHDF5Return(dset_id,H5Dcreate2,(group, isname, inttype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT));
307: #else
308:     PetscStackCallHDF5Return(dset_id,H5Dcreate,(group, isname, inttype, filespace, H5P_DEFAULT));
309: #endif
310:     PetscStackCallHDF5(H5Pclose,(chunkspace));
311:   } else {
312:     PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, isname, H5P_DEFAULT));
313:     PetscStackCallHDF5(H5Dset_extent,(dset_id, dims));
314:   }
315:   PetscStackCallHDF5(H5Sclose,(filespace));

317:   /* Each process defines a dataset and writes it to the hyperslab in the file */
318:   dim = 0;
319:   if (timestep >= 0) {
320:     count[dim] = 1;
321:     ++dim;
322:   }
323:   PetscHDF5IntCast(n/bs,count + dim);
324:   ++dim;
325:   if (bs >= 1) {
326:     count[dim] = bs;
327:     ++dim;
328:   }
329:   if (n > 0) {
330:     PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL));
331:   } else {
332:     /* Can't create dataspace with zero for any dimension, so create null dataspace. */
333:     PetscStackCallHDF5Return(memspace,H5Screate,(H5S_NULL));
334:   }

336:   /* Select hyperslab in the file */
337:   PetscLayoutGetRange(is->map, &low, NULL);
338:   dim  = 0;
339:   if (timestep >= 0) {
340:     offset[dim] = timestep;
341:     ++dim;
342:   }
343:   PetscHDF5IntCast(low/bs,offset + dim);
344:   ++dim;
345:   if (bs >= 1) {
346:     offset[dim] = 0;
347:     ++dim;
348:   }
349:   if (n > 0) {
350:     PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id));
351:     PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL));
352:   } else {
353:     /* Create null filespace to match null memspace. */
354:     PetscStackCallHDF5Return(filespace,H5Screate,(H5S_NULL));
355:   }

357:   /* Create property list for collective dataset write */
358:   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER));
359: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
360:   PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE));
361: #endif
362:   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */

364:   ISGetIndices(is, &ind);
365:   PetscStackCallHDF5(H5Dwrite,(dset_id, inttype, memspace, filespace, plist_id, ind));
366:   PetscStackCallHDF5(H5Fflush,(file_id, H5F_SCOPE_GLOBAL));
367:   ISGetIndices(is, &ind);

369:   /* Close/release resources */
370:   if (group != file_id) PetscStackCallHDF5(H5Gclose,(group));
371:   PetscStackCallHDF5(H5Pclose,(plist_id));
372:   PetscStackCallHDF5(H5Sclose,(filespace));
373:   PetscStackCallHDF5(H5Sclose,(memspace));
374:   PetscStackCallHDF5(H5Dclose,(dset_id));
375:   PetscInfo1(is, "Wrote IS object with name %s\n", isname);
376:   return(0);
377: }
378: #endif

380: static PetscErrorCode ISView_General_Binary(IS is,PetscViewer viewer)
381: {
383:   IS_General     *isa = (IS_General*) is->data;
384:   PetscMPIInt    rank,size,mesgsize,tag = ((PetscObject)viewer)->tag, mesglen;
385:   PetscInt       n,N,len,j,tr[2];
386:   int            fdes;
387:   MPI_Status     status;
388:   PetscInt       message_count,flowcontrolcount,*values;

391:   PetscLayoutGetLocalSize(is->map, &n);
392:   PetscLayoutGetSize(is->map, &N);
393:   PetscViewerBinaryGetDescriptor(viewer,&fdes);

395:   /* determine maximum message to arrive */
396:   MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
397:   MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);

399:   tr[0] = IS_FILE_CLASSID;
400:   tr[1] = N;
401:   PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_FALSE);
402:   MPI_Reduce(&n,&len,1,MPIU_INT,MPI_SUM,0,PetscObjectComm((PetscObject)is));

404:   PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);
405:   if (!rank) {
406:     PetscBinaryWrite(fdes,isa->idx,n,PETSC_INT,PETSC_FALSE);

408:     PetscMalloc1(len,&values);
409:     PetscMPIIntCast(len,&mesgsize);
410:     /* receive and save messages */
411:     for (j=1; j<size; j++) {
412:       PetscViewerFlowControlStepMaster(viewer,j,&message_count,flowcontrolcount);
413:       MPI_Recv(values,mesgsize,MPIU_INT,j,tag,PetscObjectComm((PetscObject)is),&status);
414:       MPI_Get_count(&status,MPIU_INT,&mesglen);
415:       PetscBinaryWrite(fdes,values,(PetscInt)mesglen,PETSC_INT,PETSC_TRUE);
416:     }
417:     PetscViewerFlowControlEndMaster(viewer,&message_count);
418:     PetscFree(values);
419:   } else {
420:     PetscViewerFlowControlStepWorker(viewer,rank,&message_count);
421:     PetscMPIIntCast(n,&mesgsize);
422:     MPI_Send(isa->idx,mesgsize,MPIU_INT,0,tag,PetscObjectComm((PetscObject)is));
423:     PetscViewerFlowControlEndWorker(viewer,&message_count);
424:   }
425:   return(0);
426: }

428: static PetscErrorCode ISView_General(IS is,PetscViewer viewer)
429: {
430:   IS_General     *sub = (IS_General*)is->data;
432:   PetscInt       i,n,*idx = sub->idx;
433:   PetscBool      iascii,isbinary,ishdf5;

436:   PetscLayoutGetLocalSize(is->map, &n);
437:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
438:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
439:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
440:   if (iascii) {
441:     MPI_Comm    comm;
442:     PetscMPIInt rank,size;

444:     PetscObjectGetComm((PetscObject)viewer,&comm);
445:     MPI_Comm_rank(comm,&rank);
446:     MPI_Comm_size(comm,&size);

448:     PetscViewerASCIIPushSynchronized(viewer);
449:     if (size > 1) {
450:       if (is->isperm) {
451:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutation\n",rank);
452:       }
453:       PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
454:       for (i=0; i<n; i++) {
455:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,idx[i]);
456:       }
457:     } else {
458:       if (is->isperm) {
459:         PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutation\n");
460:       }
461:       PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
462:       for (i=0; i<n; i++) {
463:         PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i,idx[i]);
464:       }
465:     }
466:     PetscViewerFlush(viewer);
467:     PetscViewerASCIIPopSynchronized(viewer);
468:   } else if (isbinary) {
469:     ISView_General_Binary(is,viewer);
470:   } else if (ishdf5) {
471: #if defined(PETSC_HAVE_HDF5)
472:     ISView_General_HDF5(is,viewer);
473: #endif
474:   }
475:   return(0);
476: }

478: static PetscErrorCode ISSort_General(IS is)
479: {
480:   IS_General     *sub = (IS_General*)is->data;
481:   PetscInt       n;

485:   if (sub->sorted) return(0);
486:   PetscLayoutGetLocalSize(is->map, &n);
487:   PetscSortInt(n,sub->idx);
488:   sub->sorted = PETSC_TRUE;
489:   return(0);
490: }

492: static PetscErrorCode ISSortRemoveDups_General(IS is)
493: {
494:   IS_General     *sub = (IS_General*)is->data;
495:   PetscInt       n;

499:   PetscLayoutGetLocalSize(is->map, &n);
500:   if (sub->sorted) {
501:     PetscSortedRemoveDupsInt(&n,sub->idx);
502:   } else {
503:     PetscSortRemoveDupsInt(&n,sub->idx);
504:   }
505:   PetscLayoutSetLocalSize(is->map, n);
506:   PetscLayoutSetSize(is->map, PETSC_DECIDE);
507:   PetscLayoutSetUp(is->map);
508:   sub->sorted = PETSC_TRUE;
509:   return(0);
510: }

512: static PetscErrorCode ISSorted_General(IS is,PetscBool  *flg)
513: {
514:   IS_General *sub = (IS_General*)is->data;

517:   *flg = sub->sorted;
518:   return(0);
519: }

521: PetscErrorCode  ISToGeneral_General(IS is)
522: {
524:   return(0);
525: }

527: static struct _ISOps myops = { ISGetSize_General,
528:                                ISGetLocalSize_General,
529:                                ISGetIndices_General,
530:                                ISRestoreIndices_General,
531:                                ISInvertPermutation_General,
532:                                ISSort_General,
533:                                ISSortRemoveDups_General,
534:                                ISSorted_General,
535:                                ISDuplicate_General,
536:                                ISDestroy_General,
537:                                ISView_General,
538:                                ISLoad_Default,
539:                                ISIdentity_General,
540:                                ISCopy_General,
541:                                ISToGeneral_General,
542:                                ISOnComm_General,
543:                                ISSetBlockSize_General,
544:                                ISContiguousLocal_General,
545:                                ISLocate_General};

547: PETSC_INTERN PetscErrorCode ISSetUp_General(IS);

549: PetscErrorCode ISSetUp_General(IS is)
550: {
552:   IS_General     *sub = (IS_General*)is->data;
553:   const PetscInt *idx = sub->idx;
554:   PetscInt       n,i,min,max;

557:   PetscLayoutGetLocalSize(is->map, &n);

559:   sub->sorted = PETSC_TRUE;
560:   for (i=1; i<n; i++) {
561:     if (idx[i] < idx[i-1]) {sub->sorted = PETSC_FALSE; break;}
562:   }
563:   if (n) {
564:     min = max = idx[0];
565:     for (i=1; i<n; i++) {
566:       if (idx[i] < min) min = idx[i];
567:       if (idx[i] > max) max = idx[i];
568:     }
569:     is->min = min;
570:     is->max = max;
571:   } else {
572:     is->min = PETSC_MAX_INT;
573:     is->max = PETSC_MIN_INT;
574:   }
575:   is->isperm     = PETSC_FALSE;
576:   is->isidentity = PETSC_FALSE;
577:   return(0);
578: }

580: /*@
581:    ISCreateGeneral - Creates a data structure for an index set
582:    containing a list of integers.

584:    Collective on MPI_Comm

586:    Input Parameters:
587: +  comm - the MPI communicator
588: .  n - the length of the index set
589: .  idx - the list of integers
590: -  mode - PETSC_COPY_VALUES, PETSC_OWN_POINTER, or PETSC_USE_POINTER; see PetscCopyMode for meaning of this flag.

592:    Output Parameter:
593: .  is - the new index set

595:    Notes:
596:    When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
597:    conceptually the same as MPI_Group operations. The IS are then
598:    distributed sets of indices and thus certain operations on them are
599:    collective.


602:    Level: beginner

604:   Concepts: index sets^creating
605:   Concepts: IS^creating

607: .seealso: ISCreateStride(), ISCreateBlock(), ISAllGather(), PETSC_COPY_VALUES, PETSC_OWN_POINTER, PETSC_USE_POINTER, PetscCopyMode
608: @*/
609: PetscErrorCode  ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
610: {

614:   ISCreate(comm,is);
615:   ISSetType(*is,ISGENERAL);
616:   ISGeneralSetIndices(*is,n,idx,mode);
617:   return(0);
618: }

620: /*@
621:    ISGeneralSetIndices - Sets the indices for an ISGENERAL index set

623:    Collective on IS

625:    Input Parameters:
626: +  is - the index set
627: .  n - the length of the index set
628: .  idx - the list of integers
629: -  mode - see PetscCopyMode for meaning of this flag.

631:    Level: beginner

633:   Concepts: index sets^creating
634:   Concepts: IS^creating

636: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather()
637: @*/
638: PetscErrorCode  ISGeneralSetIndices(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
639: {

643:   PetscUseMethod(is,"ISGeneralSetIndices_C",(IS,PetscInt,const PetscInt[],PetscCopyMode),(is,n,idx,mode));
644:   return(0);
645: }

647: PetscErrorCode  ISGeneralSetIndices_General(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
648: {
650:   IS_General     *sub = (IS_General*)is->data;

653:   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");

656:   PetscLayoutSetLocalSize(is->map, n);
657:   PetscLayoutSetUp(is->map);

659:   if (sub->allocated) {PetscFree(sub->idx);}
660:   if (mode == PETSC_COPY_VALUES) {
661:     PetscMalloc1(n,&sub->idx);
662:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
663:     PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));
664:     sub->allocated = PETSC_TRUE;
665:   } else if (mode == PETSC_OWN_POINTER) {
666:     sub->idx = (PetscInt*)idx;
667:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
668:     sub->allocated = PETSC_TRUE;
669:   } else {
670:     sub->idx = (PetscInt*)idx;
671:     sub->allocated = PETSC_FALSE;
672:   }

674:   ISSetUp_General(is);
675:   ISViewFromOptions(is,NULL,"-is_view");
676:   return(0);
677: }

679: PETSC_EXTERN PetscErrorCode ISCreate_General(IS is)
680: {
682:   IS_General     *sub;

685:   PetscNewLog(is,&sub);
686:   is->data = (void *) sub;
687:   PetscMemcpy(is->ops,&myops,sizeof(myops));
688:   PetscObjectComposeFunction((PetscObject)is,"ISGeneralSetIndices_C",ISGeneralSetIndices_General);
689:   return(0);
690: }