Actual source code: general.c

petsc-3.10.5 2019-03-28
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: {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

240:   ISGetBlockSize(is,&bs);
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] = 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: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
291:     PetscStackCallHDF5Return(dset_id,H5Dcreate2,(group, isname, inttype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT));
292: #else
293:     PetscStackCallHDF5Return(dset_id,H5Dcreate,(group, isname, inttype, filespace, H5P_DEFAULT));
294: #endif
295:     PetscStackCallHDF5(H5Pclose,(chunkspace));
296:   } else {
297:     PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, isname, H5P_DEFAULT));
298:     PetscStackCallHDF5(H5Dset_extent,(dset_id, dims));
299:   }
300:   PetscStackCallHDF5(H5Sclose,(filespace));

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

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

342:   /* Create property list for collective dataset write */
343:   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER));
344: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
345:   PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE));
346: #endif
347:   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */

349:   ISGetIndices(is, &ind);
350:   PetscStackCallHDF5(H5Dwrite,(dset_id, inttype, memspace, filespace, plist_id, ind));
351:   PetscStackCallHDF5(H5Fflush,(file_id, H5F_SCOPE_GLOBAL));
352:   ISRestoreIndices(is, &ind);

354:   /* Close/release resources */
355:   if (group != file_id) PetscStackCallHDF5(H5Gclose,(group));
356:   PetscStackCallHDF5(H5Pclose,(plist_id));
357:   PetscStackCallHDF5(H5Sclose,(filespace));
358:   PetscStackCallHDF5(H5Sclose,(memspace));
359:   PetscStackCallHDF5(H5Dclose,(dset_id));
360:   PetscInfo1(is, "Wrote IS object with name %s\n", isname);
361:   return(0);
362: }
363: #endif

365: static PetscErrorCode ISView_General_Binary(IS is,PetscViewer viewer)
366: {
368:   PetscBool      skipHeader,useMPIIO;
369:   IS_General     *isa = (IS_General*) is->data;
370:   PetscMPIInt    rank,size,mesgsize,tag = ((PetscObject)viewer)->tag, mesglen;
371:   PetscInt       n,N,len,j,tr[2];
372:   int            fdes;
373:   MPI_Status     status;
374:   PetscInt       message_count,flowcontrolcount,*values;

377:   /* ISGetLayout(is,&map); */
378:   PetscLayoutGetLocalSize(is->map, &n);
379:   PetscLayoutGetSize(is->map, &N);

381:   tr[0] = IS_FILE_CLASSID;
382:   tr[1] = N;

384:   PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);
385:   if (!skipHeader) {
386:     PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_FALSE);
387:   }

389:   PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);
390: #if defined(PETSC_HAVE_MPIIO)
391:   if (useMPIIO) {
392:     MPI_File       mfdes;
393:     MPI_Offset     off;
394:     PetscMPIInt    lsize;
395:     PetscInt       rstart;
396:     const PetscInt *iarray;

398:     PetscMPIIntCast(n,&lsize);
399:     PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
400:     PetscViewerBinaryGetMPIIOOffset(viewer,&off);
401:     PetscLayoutGetRange(is->map,&rstart,NULL);
402:     off += rstart*(MPI_Offset)sizeof(PetscInt); /* off is MPI_Offset, not PetscMPIInt */
403:     MPI_File_set_view(mfdes,off,MPIU_INT,MPIU_INT,(char*)"native",MPI_INFO_NULL);
404:     ISGetIndices(is,&iarray);
405:     MPIU_File_write_all(mfdes,(void*)iarray,lsize,MPIU_INT,MPI_STATUS_IGNORE);
406:     ISRestoreIndices(is,&iarray);
407:     PetscViewerBinaryAddMPIIOOffset(viewer,N*(MPI_Offset)sizeof(PetscInt));
408:     return(0);
409:   }
410: #endif

412:   PetscViewerBinaryGetDescriptor(viewer,&fdes);
413:   MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
414:   MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);

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

419:   PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);
420:   if (!rank) {
421:     PetscBinaryWrite(fdes,isa->idx,n,PETSC_INT,PETSC_FALSE);

423:     PetscMalloc1(len,&values);
424:     PetscMPIIntCast(len,&mesgsize);
425:     /* receive and save messages */
426:     for (j=1; j<size; j++) {
427:       PetscViewerFlowControlStepMaster(viewer,j,&message_count,flowcontrolcount);
428:       MPI_Recv(values,mesgsize,MPIU_INT,j,tag,PetscObjectComm((PetscObject)is),&status);
429:       MPI_Get_count(&status,MPIU_INT,&mesglen);
430:       PetscBinaryWrite(fdes,values,(PetscInt)mesglen,PETSC_INT,PETSC_TRUE);
431:     }
432:     PetscViewerFlowControlEndMaster(viewer,&message_count);
433:     PetscFree(values);
434:   } else {
435:     PetscViewerFlowControlStepWorker(viewer,rank,&message_count);
436:     PetscMPIIntCast(n,&mesgsize);
437:     MPI_Send(isa->idx,mesgsize,MPIU_INT,0,tag,PetscObjectComm((PetscObject)is));
438:     PetscViewerFlowControlEndWorker(viewer,&message_count);
439:   }
440:   return(0);
441: }

443: static PetscErrorCode ISView_General(IS is,PetscViewer viewer)
444: {
445:   IS_General     *sub = (IS_General*)is->data;
447:   PetscInt       i,n,*idx = sub->idx;
448:   PetscBool      iascii,isbinary,ishdf5;

451:   PetscLayoutGetLocalSize(is->map, &n);
452:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
453:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
454:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
455:   if (iascii) {
456:     MPI_Comm          comm;
457:     PetscMPIInt       rank,size;
458:     PetscViewerFormat fmt;

460:     PetscObjectGetComm((PetscObject)viewer,&comm);
461:     MPI_Comm_rank(comm,&rank);
462:     MPI_Comm_size(comm,&size);

464:     PetscViewerGetFormat(viewer,&fmt);
465:     PetscViewerASCIIPushSynchronized(viewer);
466:     if (size > 1) {
467:       if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
468:         const char* name;

470:         PetscObjectGetName((PetscObject)is,&name);
471:         PetscViewerASCIISynchronizedPrintf(viewer,"%s_%d = [...\n",name,rank);
472:         for (i=0; i<n; i++) {
473:           PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
474:         }
475:         PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
476:       } else {
477:         PetscInt st = 0;

479:         if (fmt == PETSC_VIEWER_ASCII_INDEX) st = is->map->rstart;
480:         if (is->isperm) {
481:           PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutation\n",rank);
482:         }
483:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
484:         for (i=0; i<n; i++) {
485:           PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i + st,idx[i]);
486:         }
487:       }
488:     } else {
489:       if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
490:         const char* name;

492:         PetscObjectGetName((PetscObject)is,&name);
493:         PetscViewerASCIISynchronizedPrintf(viewer,"%s = [...\n",name);
494:         for (i=0; i<n; i++) {
495:           PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
496:         }
497:         PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
498:       } else {
499:         PetscInt st = 0;

501:         if (fmt == PETSC_VIEWER_ASCII_INDEX) st = is->map->rstart;
502:         if (is->isperm) {
503:           PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutation\n");
504:         }
505:         PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
506:         for (i=0; i<n; i++) {
507:           PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i + st,idx[i]);
508:         }
509:       }
510:     }
511:     PetscViewerFlush(viewer);
512:     PetscViewerASCIIPopSynchronized(viewer);
513:   } else if (isbinary) {
514:     ISView_General_Binary(is,viewer);
515:   } else if (ishdf5) {
516: #if defined(PETSC_HAVE_HDF5)
517:     ISView_General_HDF5(is,viewer);
518: #endif
519:   }
520:   return(0);
521: }

523: static PetscErrorCode ISSort_General(IS is)
524: {
525:   IS_General     *sub = (IS_General*)is->data;
526:   PetscInt       n;

530:   if (sub->sorted) return(0);
531:   PetscLayoutGetLocalSize(is->map, &n);
532:   PetscSortInt(n,sub->idx);
533:   sub->sorted = PETSC_TRUE;
534:   return(0);
535: }

537: static PetscErrorCode ISSortRemoveDups_General(IS is)
538: {
539:   IS_General     *sub = (IS_General*)is->data;
540:   PetscInt       n;

544:   PetscLayoutGetLocalSize(is->map, &n);
545:   if (sub->sorted) {
546:     PetscSortedRemoveDupsInt(&n,sub->idx);
547:   } else {
548:     PetscSortRemoveDupsInt(&n,sub->idx);
549:   }
550:   PetscLayoutSetLocalSize(is->map, n);
551:   PetscLayoutSetSize(is->map, PETSC_DECIDE);
552:   PetscLayoutSetUp(is->map);
553:   sub->sorted = PETSC_TRUE;
554:   return(0);
555: }

557: static PetscErrorCode ISSorted_General(IS is,PetscBool  *flg)
558: {
559:   IS_General *sub = (IS_General*)is->data;

562:   *flg = sub->sorted;
563:   return(0);
564: }

566: PetscErrorCode  ISToGeneral_General(IS is)
567: {
569:   return(0);
570: }

572: static struct _ISOps myops = { ISGetSize_General,
573:                                ISGetLocalSize_General,
574:                                ISGetIndices_General,
575:                                ISRestoreIndices_General,
576:                                ISInvertPermutation_General,
577:                                ISSort_General,
578:                                ISSortRemoveDups_General,
579:                                ISSorted_General,
580:                                ISDuplicate_General,
581:                                ISDestroy_General,
582:                                ISView_General,
583:                                ISLoad_Default,
584:                                ISIdentity_General,
585:                                ISCopy_General,
586:                                ISToGeneral_General,
587:                                ISOnComm_General,
588:                                ISSetBlockSize_General,
589:                                ISContiguousLocal_General,
590:                                ISLocate_General};

592: PETSC_INTERN PetscErrorCode ISSetUp_General(IS);

594: PetscErrorCode ISSetUp_General(IS is)
595: {
597:   IS_General     *sub = (IS_General*)is->data;
598:   const PetscInt *idx = sub->idx;
599:   PetscInt       n,i,min,max;

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

604:   sub->sorted = PETSC_TRUE;
605:   for (i=1; i<n; i++) {
606:     if (idx[i] < idx[i-1]) {sub->sorted = PETSC_FALSE; break;}
607:   }
608:   if (n) {
609:     min = max = idx[0];
610:     for (i=1; i<n; i++) {
611:       if (idx[i] < min) min = idx[i];
612:       if (idx[i] > max) max = idx[i];
613:     }
614:     is->min = min;
615:     is->max = max;
616:   } else {
617:     is->min = PETSC_MAX_INT;
618:     is->max = PETSC_MIN_INT;
619:   }
620:   is->isperm     = PETSC_FALSE;
621:   is->isidentity = PETSC_FALSE;
622:   return(0);
623: }

625: /*@
626:    ISCreateGeneral - Creates a data structure for an index set
627:    containing a list of integers.

629:    Collective on MPI_Comm

631:    Input Parameters:
632: +  comm - the MPI communicator
633: .  n - the length of the index set
634: .  idx - the list of integers
635: -  mode - PETSC_COPY_VALUES, PETSC_OWN_POINTER, or PETSC_USE_POINTER; see PetscCopyMode for meaning of this flag.

637:    Output Parameter:
638: .  is - the new index set

640:    Notes:
641:    When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
642:    conceptually the same as MPI_Group operations. The IS are then
643:    distributed sets of indices and thus certain operations on them are
644:    collective.


647:    Level: beginner

649:   Concepts: index sets^creating
650:   Concepts: IS^creating

652: .seealso: ISCreateStride(), ISCreateBlock(), ISAllGather(), PETSC_COPY_VALUES, PETSC_OWN_POINTER, PETSC_USE_POINTER, PetscCopyMode
653: @*/
654: PetscErrorCode  ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
655: {

659:   ISCreate(comm,is);
660:   ISSetType(*is,ISGENERAL);
661:   ISGeneralSetIndices(*is,n,idx,mode);
662:   return(0);
663: }

665: /*@
666:    ISGeneralSetIndices - Sets the indices for an ISGENERAL index set

668:    Collective on IS

670:    Input Parameters:
671: +  is - the index set
672: .  n - the length of the index set
673: .  idx - the list of integers
674: -  mode - see PetscCopyMode for meaning of this flag.

676:    Level: beginner

678:   Concepts: index sets^creating
679:   Concepts: IS^creating

681: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather()
682: @*/
683: PetscErrorCode  ISGeneralSetIndices(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
684: {

688:   PetscUseMethod(is,"ISGeneralSetIndices_C",(IS,PetscInt,const PetscInt[],PetscCopyMode),(is,n,idx,mode));
689:   return(0);
690: }

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

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

701:   PetscLayoutSetLocalSize(is->map,n);
702:   PetscLayoutSetUp(is->map);

704:   if (sub->allocated) {PetscFree(sub->idx);}
705:   if (mode == PETSC_COPY_VALUES) {
706:     PetscMalloc1(n,&sub->idx);
707:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
708:     PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));
709:     sub->allocated = PETSC_TRUE;
710:   } else if (mode == PETSC_OWN_POINTER) {
711:     sub->idx = (PetscInt*)idx;
712:     PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
713:     sub->allocated = PETSC_TRUE;
714:   } else {
715:     sub->idx = (PetscInt*)idx;
716:     sub->allocated = PETSC_FALSE;
717:   }

719:   ISSetUp_General(is);
720:   ISViewFromOptions(is,NULL,"-is_view");
721:   return(0);
722: }

724: PETSC_EXTERN PetscErrorCode ISCreate_General(IS is)
725: {
727:   IS_General     *sub;

730:   PetscNewLog(is,&sub);
731:   is->data = (void *) sub;
732:   PetscMemcpy(is->ops,&myops,sizeof(myops));
733:   PetscObjectComposeFunction((PetscObject)is,"ISGeneralSetIndices_C",ISGeneralSetIndices_General);
734:   return(0);
735: }