Actual source code: general.c

petsc-master 2019-07-21
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 <petsc/private/viewerimpl.h>
  7: #include <petsc/private/viewerhdf5impl.h>

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

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

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

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

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

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

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

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

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

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

 83: static PetscErrorCode ISSetBlockSize_General(IS is,PetscInt bs)
 84: {

 88:   PetscLayoutSetBlockSize(is->map, bs);
 89:   return(0);
 90: }

 92: static PetscErrorCode ISContiguousLocal_General(IS is,PetscInt gstart,PetscInt gend,PetscInt *start,PetscBool *contig)
 93: {
 94:   IS_General *sub = (IS_General*)is->data;
 95:   PetscInt   n,i,p;

 99:   *start  = 0;
100:   *contig = PETSC_TRUE;
101:   PetscLayoutGetLocalSize(is->map, &n);
102:   if (!n) return(0);
103:   p = sub->idx[0];
104:   if (p < gstart) goto nomatch;
105:   *start = p - gstart;
106:   if (n > gend-p) goto nomatch;
107:   for (i=1; i<n; i++,p++) {
108:     if (sub->idx[i] != p+1) goto nomatch;
109:   }
110:   return(0);
111: nomatch:
112:   *start  = -1;
113:   *contig = PETSC_FALSE;
114:   return(0);
115: }

117: static PetscErrorCode ISLocate_General(IS is,PetscInt key,PetscInt *location)
118: {
119:   IS_General     *sub = (IS_General*)is->data;
120:   PetscInt       numIdx, i;

124:   PetscLayoutGetLocalSize(is->map,&numIdx);
125:   if (sub->sorted) { PetscFindInt(key,numIdx,sub->idx,location);}
126:   else {
127:     const PetscInt *idx = sub->idx;

129:     *location = -1;
130:     for (i = 0; i < numIdx; i++) {
131:       if (idx[i] == key) {
132:         *location = i;
133:         return(0);
134:       }
135:     }
136:   }
137:   return(0);
138: }

140: static PetscErrorCode ISGetIndices_General(IS in,const PetscInt *idx[])
141: {
142:   IS_General *sub = (IS_General*)in->data;

145:   *idx = sub->idx;
146:   return(0);
147: }

149: static PetscErrorCode ISRestoreIndices_General(IS in,const PetscInt *idx[])
150: {
151:   IS_General *sub = (IS_General*)in->data;

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

158: static PetscErrorCode ISGetSize_General(IS is,PetscInt *size)
159: {

163:   PetscLayoutGetSize(is->map, size);
164:   return(0);
165: }

167: static PetscErrorCode ISGetLocalSize_General(IS is,PetscInt *size)
168: {

172:   PetscLayoutGetLocalSize(is->map, size);
173:   return(0);
174: }

176: static PetscErrorCode ISInvertPermutation_General(IS is,PetscInt nlocal,IS *isout)
177: {
178:   IS_General     *sub = (IS_General*)is->data;
179:   PetscInt       i,*ii,n,nstart;
180:   const PetscInt *idx = sub->idx;
181:   PetscMPIInt    size;
182:   IS             istmp,nistmp;

186:   PetscLayoutGetLocalSize(is->map, &n);
187:   MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);
188:   if (size == 1) {
189:     PetscMalloc1(n,&ii);
190:     for (i=0; i<n; i++) ii[idx[i]] = i;
191:     ISCreateGeneral(PETSC_COMM_SELF,n,ii,PETSC_OWN_POINTER,isout);
192:     ISSetPermutation(*isout);
193:   } else {
194:     /* crude, nonscalable get entire IS on each processor */
195:     ISAllGather(is,&istmp);
196:     ISSetPermutation(istmp);
197:     ISInvertPermutation(istmp,PETSC_DECIDE,&nistmp);
198:     ISDestroy(&istmp);
199:     /* get the part we need */
200:     if (nlocal == PETSC_DECIDE) nlocal = n;
201:     MPI_Scan(&nlocal,&nstart,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)is));
202: #if defined(PETSC_USE_DEBUG)
203:     {
204:       PetscInt    N;
205:       PetscMPIInt rank;
206:       MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
207:       PetscLayoutGetSize(is->map, &N);
208:       if (rank == size-1) {
209:         if (nstart != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of nlocal lengths %d != total IS length %d",nstart,N);
210:       }
211:     }
212: #endif
213:     nstart -= nlocal;
214:     ISGetIndices(nistmp,&idx);
215:     ISCreateGeneral(PetscObjectComm((PetscObject)is),nlocal,idx+nstart,PETSC_COPY_VALUES,isout);
216:     ISRestoreIndices(nistmp,&idx);
217:     ISDestroy(&nistmp);
218:   }
219:   return(0);
220: }

222: #if defined(PETSC_HAVE_HDF5)
223: static PetscErrorCode ISView_General_HDF5(IS is, PetscViewer viewer)
224: {
225:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
226:   hid_t           filespace;  /* file dataspace identifier */
227:   hid_t           chunkspace; /* chunk dataset property identifier */
228:   hid_t           dset_id;    /* dataset identifier */
229:   hid_t           memspace;   /* memory dataspace identifier */
230:   hid_t           inttype;    /* int type (H5T_NATIVE_INT or H5T_NATIVE_LLONG) */
231:   hid_t           file_id, group;
232:   hsize_t         dim, maxDims[3], dims[3], chunkDims[3], count[3],offset[3];
233:   PetscInt        bs, N, n, timestep, low;
234:   const PetscInt *ind;
235:   const char     *isname;
236:   PetscErrorCode  ierr;

239:   ISGetBlockSize(is,&bs);
240:   bs   = PetscMax(bs, 1); /* If N = 0, bs  = 0 as well */
241:   PetscViewerHDF5OpenGroup(viewer, &file_id, &group);
242:   PetscViewerHDF5GetTimestep(viewer, &timestep);

244:   /* Create the dataspace for the dataset.
245:    *
246:    * dims - holds the current dimensions of the dataset
247:    *
248:    * maxDims - holds the maximum dimensions of the dataset (unlimited
249:    * for the number of time steps with the current dimensions for the
250:    * other dimensions; so only additional time steps can be added).
251:    *
252:    * chunkDims - holds the size of a single time step (required to
253:    * permit extending dataset).
254:    */
255:   dim = 0;
256:   if (timestep >= 0) {
257:     dims[dim]      = timestep+1;
258:     maxDims[dim]   = H5S_UNLIMITED;
259:     chunkDims[dim] = 1;
260:     ++dim;
261:   }
262:   ISGetSize(is, &N);
263:   ISGetLocalSize(is, &n);
264:   PetscHDF5IntCast(N/bs,dims + dim);

266:   maxDims[dim]   = dims[dim];
267:   chunkDims[dim] = PetscMax(1,dims[dim]);
268:   ++dim;
269:   if (bs >= 1) {
270:     dims[dim]      = bs;
271:     maxDims[dim]   = dims[dim];
272:     chunkDims[dim] = dims[dim];
273:     ++dim;
274:   }
275:   PetscStackCallHDF5Return(filespace,H5Screate_simple,(dim, dims, maxDims));

277: #if defined(PETSC_USE_64BIT_INDICES)
278:   inttype = H5T_NATIVE_LLONG;
279: #else
280:   inttype = H5T_NATIVE_INT;
281: #endif

283:   /* Create the dataset with default properties and close filespace */
284:   PetscObjectGetName((PetscObject) is, &isname);
285:   if (!H5Lexists(group, isname, H5P_DEFAULT)) {
286:     /* Create chunk */
287:     PetscStackCallHDF5Return(chunkspace,H5Pcreate,(H5P_DATASET_CREATE));
288:     PetscStackCallHDF5(H5Pset_chunk,(chunkspace, dim, chunkDims));

290:     PetscStackCallHDF5Return(dset_id,H5Dcreate2,(group, isname, inttype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT));
291:     PetscStackCallHDF5(H5Pclose,(chunkspace));
292:   } else {
293:     PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, isname, H5P_DEFAULT));
294:     PetscStackCallHDF5(H5Dset_extent,(dset_id, dims));
295:   }
296:   PetscStackCallHDF5(H5Sclose,(filespace));

298:   /* Each process defines a dataset and writes it to the hyperslab in the file */
299:   dim = 0;
300:   if (timestep >= 0) {
301:     count[dim] = 1;
302:     ++dim;
303:   }
304:   PetscHDF5IntCast(n/bs,count + dim);
305:   ++dim;
306:   if (bs >= 1) {
307:     count[dim] = bs;
308:     ++dim;
309:   }
310:   if (n > 0) {
311:     PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL));
312:   } else {
313:     /* Can't create dataspace with zero for any dimension, so create null dataspace. */
314:     PetscStackCallHDF5Return(memspace,H5Screate,(H5S_NULL));
315:   }

317:   /* Select hyperslab in the file */
318:   PetscLayoutGetRange(is->map, &low, NULL);
319:   dim  = 0;
320:   if (timestep >= 0) {
321:     offset[dim] = timestep;
322:     ++dim;
323:   }
324:   PetscHDF5IntCast(low/bs,offset + dim);
325:   ++dim;
326:   if (bs >= 1) {
327:     offset[dim] = 0;
328:     ++dim;
329:   }
330:   if (n > 0) {
331:     PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id));
332:     PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL));
333:   } else {
334:     /* Create null filespace to match null memspace. */
335:     PetscStackCallHDF5Return(filespace,H5Screate,(H5S_NULL));
336:   }

338:   ISGetIndices(is, &ind);
339:   PetscStackCallHDF5(H5Dwrite,(dset_id, inttype, memspace, filespace, hdf5->dxpl_id, ind));
340:   PetscStackCallHDF5(H5Fflush,(file_id, H5F_SCOPE_GLOBAL));
341:   ISRestoreIndices(is, &ind);

343:   /* Close/release resources */
344:   PetscStackCallHDF5(H5Gclose,(group));
345:   PetscStackCallHDF5(H5Sclose,(filespace));
346:   PetscStackCallHDF5(H5Sclose,(memspace));
347:   PetscStackCallHDF5(H5Dclose,(dset_id));
348:   PetscInfo1(is, "Wrote IS object with name %s\n", isname);
349:   return(0);
350: }
351: #endif

353: static PetscErrorCode ISView_General_Binary(IS is,PetscViewer viewer)
354: {
356:   PetscBool      skipHeader,useMPIIO;
357:   IS_General     *isa = (IS_General*) is->data;
358:   PetscMPIInt    rank,size,mesgsize,tag = ((PetscObject)viewer)->tag, mesglen;
359:   PetscInt       n,N,len,j,tr[2];
360:   int            fdes;
361:   MPI_Status     status;
362:   PetscInt       message_count,flowcontrolcount,*values;

365:   /* ISGetLayout(is,&map); */
366:   PetscLayoutGetLocalSize(is->map, &n);
367:   PetscLayoutGetSize(is->map, &N);

369:   tr[0] = IS_FILE_CLASSID;
370:   tr[1] = N;

372:   PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);
373:   if (!skipHeader) {
374:     PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_FALSE);
375:   }

377:   PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);
378: #if defined(PETSC_HAVE_MPIIO)
379:   if (useMPIIO) {
380:     MPI_File       mfdes;
381:     MPI_Offset     off;
382:     PetscMPIInt    lsize;
383:     PetscInt       rstart;
384:     const PetscInt *iarray;

386:     PetscMPIIntCast(n,&lsize);
387:     PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
388:     PetscViewerBinaryGetMPIIOOffset(viewer,&off);
389:     PetscLayoutGetRange(is->map,&rstart,NULL);
390:     off += rstart*(MPI_Offset)sizeof(PetscInt); /* off is MPI_Offset, not PetscMPIInt */
391:     MPI_File_set_view(mfdes,off,MPIU_INT,MPIU_INT,(char*)"native",MPI_INFO_NULL);
392:     ISGetIndices(is,&iarray);
393:     MPIU_File_write_all(mfdes,(void*)iarray,lsize,MPIU_INT,MPI_STATUS_IGNORE);
394:     ISRestoreIndices(is,&iarray);
395:     PetscViewerBinaryAddMPIIOOffset(viewer,N*(MPI_Offset)sizeof(PetscInt));
396:     return(0);
397:   }
398: #endif

400:   PetscViewerBinaryGetDescriptor(viewer,&fdes);
401:   MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
402:   MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);

404:   /* determine maximum message to arrive */
405:   MPI_Reduce(&n,&len,1,MPIU_INT,MPI_MAX,0,PetscObjectComm((PetscObject)is));

407:   PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);
408:   if (!rank) {
409:     PetscBinaryWrite(fdes,isa->idx,n,PETSC_INT,PETSC_FALSE);

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

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

439:   PetscLayoutGetLocalSize(is->map, &n);
440:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
441:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
442:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
443:   if (iascii) {
444:     MPI_Comm          comm;
445:     PetscMPIInt       rank,size;
446:     PetscViewerFormat fmt;

448:     PetscObjectGetComm((PetscObject)viewer,&comm);
449:     MPI_Comm_rank(comm,&rank);
450:     MPI_Comm_size(comm,&size);

452:     PetscViewerGetFormat(viewer,&fmt);
453:     PetscViewerASCIIPushSynchronized(viewer);
454:     if (size > 1) {
455:       if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
456:         const char* name;

458:         PetscObjectGetName((PetscObject)is,&name);
459:         PetscViewerASCIISynchronizedPrintf(viewer,"%s_%d = [...\n",name,rank);
460:         for (i=0; i<n; i++) {
461:           PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
462:         }
463:         PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
464:       } else {
465:         PetscInt st = 0;

467:         if (fmt == PETSC_VIEWER_ASCII_INDEX) st = is->map->rstart;
468:         if (is->isperm) {
469:           PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutation\n",rank);
470:         }
471:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
472:         for (i=0; i<n; i++) {
473:           PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i + st,idx[i]);
474:         }
475:       }
476:     } else {
477:       if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
478:         const char* name;

480:         PetscObjectGetName((PetscObject)is,&name);
481:         PetscViewerASCIISynchronizedPrintf(viewer,"%s = [...\n",name);
482:         for (i=0; i<n; i++) {
483:           PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
484:         }
485:         PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
486:       } else {
487:         PetscInt st = 0;

489:         if (fmt == PETSC_VIEWER_ASCII_INDEX) st = is->map->rstart;
490:         if (is->isperm) {
491:           PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutation\n");
492:         }
493:         PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
494:         for (i=0; i<n; i++) {
495:           PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i + st,idx[i]);
496:         }
497:       }
498:     }
499:     PetscViewerFlush(viewer);
500:     PetscViewerASCIIPopSynchronized(viewer);
501:   } else if (isbinary) {
502:     ISView_General_Binary(is,viewer);
503:   } else if (ishdf5) {
504: #if defined(PETSC_HAVE_HDF5)
505:     ISView_General_HDF5(is,viewer);
506: #endif
507:   }
508:   return(0);
509: }

511: static PetscErrorCode ISSort_General(IS is)
512: {
513:   IS_General     *sub = (IS_General*)is->data;
514:   PetscInt       n;

518:   if (sub->sorted) return(0);
519:   PetscLayoutGetLocalSize(is->map, &n);
520:   PetscSortInt(n,sub->idx);
521:   sub->sorted = PETSC_TRUE;
522:   return(0);
523: }

525: static PetscErrorCode ISSortRemoveDups_General(IS is)
526: {
527:   IS_General     *sub = (IS_General*)is->data;
528:   PetscInt       n;

532:   PetscLayoutGetLocalSize(is->map, &n);
533:   if (sub->sorted) {
534:     PetscSortedRemoveDupsInt(&n,sub->idx);
535:   } else {
536:     PetscSortRemoveDupsInt(&n,sub->idx);
537:   }
538:   PetscLayoutSetLocalSize(is->map, n);
539:   PetscLayoutSetSize(is->map, PETSC_DECIDE);
540:   PetscLayoutSetUp(is->map);
541:   sub->sorted = PETSC_TRUE;
542:   return(0);
543: }

545: static PetscErrorCode ISSorted_General(IS is,PetscBool  *flg)
546: {
547:   IS_General *sub = (IS_General*)is->data;

550:   *flg = sub->sorted;
551:   return(0);
552: }

554: PetscErrorCode  ISToGeneral_General(IS is)
555: {
557:   return(0);
558: }

560: static struct _ISOps myops = { ISGetSize_General,
561:                                ISGetLocalSize_General,
562:                                ISGetIndices_General,
563:                                ISRestoreIndices_General,
564:                                ISInvertPermutation_General,
565:                                ISSort_General,
566:                                ISSortRemoveDups_General,
567:                                ISSorted_General,
568:                                ISDuplicate_General,
569:                                ISDestroy_General,
570:                                ISView_General,
571:                                ISLoad_Default,
572:                                ISIdentity_General,
573:                                ISCopy_General,
574:                                ISToGeneral_General,
575:                                ISOnComm_General,
576:                                ISSetBlockSize_General,
577:                                ISContiguousLocal_General,
578:                                ISLocate_General};

580: PETSC_INTERN PetscErrorCode ISSetUp_General(IS);

582: PetscErrorCode ISSetUp_General(IS is)
583: {
585:   IS_General     *sub = (IS_General*)is->data;
586:   const PetscInt *idx = sub->idx;
587:   PetscInt       n,i,min,max;

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

592:   sub->sorted = PETSC_TRUE;
593:   for (i=1; i<n; i++) {
594:     if (idx[i] < idx[i-1]) {sub->sorted = PETSC_FALSE; break;}
595:   }
596:   if (n) {
597:     min = max = idx[0];
598:     for (i=1; i<n; i++) {
599:       if (idx[i] < min) min = idx[i];
600:       if (idx[i] > max) max = idx[i];
601:     }
602:     is->min = min;
603:     is->max = max;
604:   } else {
605:     is->min = PETSC_MAX_INT;
606:     is->max = PETSC_MIN_INT;
607:   }
608:   is->isperm     = PETSC_FALSE;
609:   is->isidentity = PETSC_FALSE;
610:   return(0);
611: }

613: /*@
614:    ISCreateGeneral - Creates a data structure for an index set
615:    containing a list of integers.

617:    Collective

619:    Input Parameters:
620: +  comm - the MPI communicator
621: .  n - the length of the index set
622: .  idx - the list of integers
623: -  mode - PETSC_COPY_VALUES, PETSC_OWN_POINTER, or PETSC_USE_POINTER; see PetscCopyMode for meaning of this flag.

625:    Output Parameter:
626: .  is - the new index set

628:    Notes:
629:    When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
630:    conceptually the same as MPI_Group operations. The IS are then
631:    distributed sets of indices and thus certain operations on them are
632:    collective.


635:    Level: beginner


638: .seealso: ISCreateStride(), ISCreateBlock(), ISAllGather(), PETSC_COPY_VALUES, PETSC_OWN_POINTER, PETSC_USE_POINTER, PetscCopyMode
639: @*/
640: PetscErrorCode  ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
641: {

645:   ISCreate(comm,is);
646:   ISSetType(*is,ISGENERAL);
647:   ISGeneralSetIndices(*is,n,idx,mode);
648:   return(0);
649: }

651: /*@
652:    ISGeneralSetIndices - Sets the indices for an ISGENERAL index set

654:    Collective on IS

656:    Input Parameters:
657: +  is - the index set
658: .  n - the length of the index set
659: .  idx - the list of integers
660: -  mode - see PetscCopyMode for meaning of this flag.

662:    Level: beginner


665: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather()
666: @*/
667: PetscErrorCode  ISGeneralSetIndices(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
668: {

672:   PetscUseMethod(is,"ISGeneralSetIndices_C",(IS,PetscInt,const PetscInt[],PetscCopyMode),(is,n,idx,mode));
673:   return(0);
674: }

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

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

685:   PetscLayoutSetLocalSize(is->map,n);
686:   PetscLayoutSetUp(is->map);

688:   if (sub->allocated) {PetscFree(sub->idx);}
689:   if (mode == PETSC_COPY_VALUES) {
690:     PetscMalloc1(n,&sub->idx);
691:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
692:     PetscArraycpy(sub->idx,idx,n);
693:     sub->allocated = PETSC_TRUE;
694:   } else if (mode == PETSC_OWN_POINTER) {
695:     sub->idx = (PetscInt*)idx;
696:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
697:     sub->allocated = PETSC_TRUE;
698:   } else {
699:     sub->idx = (PetscInt*)idx;
700:     sub->allocated = PETSC_FALSE;
701:   }

703:   ISSetUp_General(is);
704:   ISViewFromOptions(is,NULL,"-is_view");
705:   return(0);
706: }

708: PETSC_EXTERN PetscErrorCode ISCreate_General(IS is)
709: {
711:   IS_General     *sub;

714:   PetscNewLog(is,&sub);
715:   is->data = (void *) sub;
716:   PetscMemcpy(is->ops,&myops,sizeof(myops));
717:   PetscObjectComposeFunction((PetscObject)is,"ISGeneralSetIndices_C",ISGeneralSetIndices_General);
718:   return(0);
719: }