Actual source code: general.c
petsc-3.9.2 2018-05-20
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, ×tep);
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: ISRestoreIndices(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: PetscBool skipHeader,useMPIIO;
384: IS_General *isa = (IS_General*) is->data;
385: PetscMPIInt rank,size,mesgsize,tag = ((PetscObject)viewer)->tag, mesglen;
386: PetscInt n,N,len,j,tr[2];
387: int fdes;
388: MPI_Status status;
389: PetscInt message_count,flowcontrolcount,*values;
392: /* ISGetLayout(is,&map); */
393: PetscLayoutGetLocalSize(is->map, &n);
394: PetscLayoutGetSize(is->map, &N);
396: tr[0] = IS_FILE_CLASSID;
397: tr[1] = N;
399: PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);
400: if (!skipHeader) {
401: PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_FALSE);
402: }
404: PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);
405: #if defined(PETSC_HAVE_MPIIO)
406: if (useMPIIO) {
407: MPI_File mfdes;
408: MPI_Offset off;
409: PetscMPIInt lsize;
410: PetscInt rstart;
411: const PetscInt *iarray;
413: PetscMPIIntCast(n,&lsize);
414: PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
415: PetscViewerBinaryGetMPIIOOffset(viewer,&off);
416: PetscLayoutGetRange(is->map,&rstart,NULL);
417: off += rstart*(MPI_Offset)sizeof(PetscInt); /* off is MPI_Offset, not PetscMPIInt */
418: MPI_File_set_view(mfdes,off,MPIU_INT,MPIU_INT,(char*)"native",MPI_INFO_NULL);
419: ISGetIndices(is,&iarray);
420: MPIU_File_write_all(mfdes,(void*)iarray,lsize,MPIU_INT,MPI_STATUS_IGNORE);
421: ISRestoreIndices(is,&iarray);
422: PetscViewerBinaryAddMPIIOOffset(viewer,N*(MPI_Offset)sizeof(PetscInt));
423: return(0);
424: }
425: #endif
427: PetscViewerBinaryGetDescriptor(viewer,&fdes);
428: MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
429: MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);
431: /* determine maximum message to arrive */
432: MPI_Reduce(&n,&len,1,MPIU_INT,MPI_MAX,0,PetscObjectComm((PetscObject)is));
434: PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);
435: if (!rank) {
436: PetscBinaryWrite(fdes,isa->idx,n,PETSC_INT,PETSC_FALSE);
438: PetscMalloc1(len,&values);
439: PetscMPIIntCast(len,&mesgsize);
440: /* receive and save messages */
441: for (j=1; j<size; j++) {
442: PetscViewerFlowControlStepMaster(viewer,j,&message_count,flowcontrolcount);
443: MPI_Recv(values,mesgsize,MPIU_INT,j,tag,PetscObjectComm((PetscObject)is),&status);
444: MPI_Get_count(&status,MPIU_INT,&mesglen);
445: PetscBinaryWrite(fdes,values,(PetscInt)mesglen,PETSC_INT,PETSC_TRUE);
446: }
447: PetscViewerFlowControlEndMaster(viewer,&message_count);
448: PetscFree(values);
449: } else {
450: PetscViewerFlowControlStepWorker(viewer,rank,&message_count);
451: PetscMPIIntCast(n,&mesgsize);
452: MPI_Send(isa->idx,mesgsize,MPIU_INT,0,tag,PetscObjectComm((PetscObject)is));
453: PetscViewerFlowControlEndWorker(viewer,&message_count);
454: }
455: return(0);
456: }
458: static PetscErrorCode ISView_General(IS is,PetscViewer viewer)
459: {
460: IS_General *sub = (IS_General*)is->data;
462: PetscInt i,n,*idx = sub->idx;
463: PetscBool iascii,isbinary,ishdf5,matl;
466: PetscLayoutGetLocalSize(is->map, &n);
467: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
468: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
469: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
470: if (iascii) {
471: MPI_Comm comm;
472: PetscMPIInt rank,size;
473: PetscViewerFormat fmt;
475: PetscObjectGetComm((PetscObject)viewer,&comm);
476: MPI_Comm_rank(comm,&rank);
477: MPI_Comm_size(comm,&size);
479: PetscViewerGetFormat(viewer,&fmt);
480: matl = (PetscBool)(fmt == PETSC_VIEWER_ASCII_MATLAB);
481: PetscViewerASCIIPushSynchronized(viewer);
482: if (size > 1) {
483: if (matl) {
484: const char* name;
486: PetscObjectGetName((PetscObject)is,&name);
487: PetscViewerASCIISynchronizedPrintf(viewer,"%s_%d = [...\n",name,rank);
488: for (i=0; i<n; i++) {
489: PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
490: }
491: PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
492: } else {
493: if (is->isperm) {
494: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutation\n",rank);
495: }
496: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
497: for (i=0; i<n; i++) {
498: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,idx[i]);
499: }
500: }
501: } else {
502: if (matl) {
503: const char* name;
505: PetscObjectGetName((PetscObject)is,&name);
506: PetscViewerASCIISynchronizedPrintf(viewer,"%s = [...\n",name);
507: for (i=0; i<n; i++) {
508: PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
509: }
510: PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
511: } else {
512: if (is->isperm) {
513: PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutation\n");
514: }
515: PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
516: for (i=0; i<n; i++) {
517: PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i,idx[i]);
518: }
519: }
520: }
521: PetscViewerFlush(viewer);
522: PetscViewerASCIIPopSynchronized(viewer);
523: } else if (isbinary) {
524: ISView_General_Binary(is,viewer);
525: } else if (ishdf5) {
526: #if defined(PETSC_HAVE_HDF5)
527: ISView_General_HDF5(is,viewer);
528: #endif
529: }
530: return(0);
531: }
533: static PetscErrorCode ISSort_General(IS is)
534: {
535: IS_General *sub = (IS_General*)is->data;
536: PetscInt n;
540: if (sub->sorted) return(0);
541: PetscLayoutGetLocalSize(is->map, &n);
542: PetscSortInt(n,sub->idx);
543: sub->sorted = PETSC_TRUE;
544: return(0);
545: }
547: static PetscErrorCode ISSortRemoveDups_General(IS is)
548: {
549: IS_General *sub = (IS_General*)is->data;
550: PetscInt n;
554: PetscLayoutGetLocalSize(is->map, &n);
555: if (sub->sorted) {
556: PetscSortedRemoveDupsInt(&n,sub->idx);
557: } else {
558: PetscSortRemoveDupsInt(&n,sub->idx);
559: }
560: PetscLayoutSetLocalSize(is->map, n);
561: PetscLayoutSetSize(is->map, PETSC_DECIDE);
562: PetscLayoutSetUp(is->map);
563: sub->sorted = PETSC_TRUE;
564: return(0);
565: }
567: static PetscErrorCode ISSorted_General(IS is,PetscBool *flg)
568: {
569: IS_General *sub = (IS_General*)is->data;
572: *flg = sub->sorted;
573: return(0);
574: }
576: PetscErrorCode ISToGeneral_General(IS is)
577: {
579: return(0);
580: }
582: static struct _ISOps myops = { ISGetSize_General,
583: ISGetLocalSize_General,
584: ISGetIndices_General,
585: ISRestoreIndices_General,
586: ISInvertPermutation_General,
587: ISSort_General,
588: ISSortRemoveDups_General,
589: ISSorted_General,
590: ISDuplicate_General,
591: ISDestroy_General,
592: ISView_General,
593: ISLoad_Default,
594: ISIdentity_General,
595: ISCopy_General,
596: ISToGeneral_General,
597: ISOnComm_General,
598: ISSetBlockSize_General,
599: ISContiguousLocal_General,
600: ISLocate_General};
602: PETSC_INTERN PetscErrorCode ISSetUp_General(IS);
604: PetscErrorCode ISSetUp_General(IS is)
605: {
607: IS_General *sub = (IS_General*)is->data;
608: const PetscInt *idx = sub->idx;
609: PetscInt n,i,min,max;
612: PetscLayoutGetLocalSize(is->map, &n);
614: sub->sorted = PETSC_TRUE;
615: for (i=1; i<n; i++) {
616: if (idx[i] < idx[i-1]) {sub->sorted = PETSC_FALSE; break;}
617: }
618: if (n) {
619: min = max = idx[0];
620: for (i=1; i<n; i++) {
621: if (idx[i] < min) min = idx[i];
622: if (idx[i] > max) max = idx[i];
623: }
624: is->min = min;
625: is->max = max;
626: } else {
627: is->min = PETSC_MAX_INT;
628: is->max = PETSC_MIN_INT;
629: }
630: is->isperm = PETSC_FALSE;
631: is->isidentity = PETSC_FALSE;
632: return(0);
633: }
635: /*@
636: ISCreateGeneral - Creates a data structure for an index set
637: containing a list of integers.
639: Collective on MPI_Comm
641: Input Parameters:
642: + comm - the MPI communicator
643: . n - the length of the index set
644: . idx - the list of integers
645: - mode - PETSC_COPY_VALUES, PETSC_OWN_POINTER, or PETSC_USE_POINTER; see PetscCopyMode for meaning of this flag.
647: Output Parameter:
648: . is - the new index set
650: Notes:
651: When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
652: conceptually the same as MPI_Group operations. The IS are then
653: distributed sets of indices and thus certain operations on them are
654: collective.
657: Level: beginner
659: Concepts: index sets^creating
660: Concepts: IS^creating
662: .seealso: ISCreateStride(), ISCreateBlock(), ISAllGather(), PETSC_COPY_VALUES, PETSC_OWN_POINTER, PETSC_USE_POINTER, PetscCopyMode
663: @*/
664: PetscErrorCode ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
665: {
669: ISCreate(comm,is);
670: ISSetType(*is,ISGENERAL);
671: ISGeneralSetIndices(*is,n,idx,mode);
672: return(0);
673: }
675: /*@
676: ISGeneralSetIndices - Sets the indices for an ISGENERAL index set
678: Collective on IS
680: Input Parameters:
681: + is - the index set
682: . n - the length of the index set
683: . idx - the list of integers
684: - mode - see PetscCopyMode for meaning of this flag.
686: Level: beginner
688: Concepts: index sets^creating
689: Concepts: IS^creating
691: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather()
692: @*/
693: PetscErrorCode ISGeneralSetIndices(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
694: {
698: PetscUseMethod(is,"ISGeneralSetIndices_C",(IS,PetscInt,const PetscInt[],PetscCopyMode),(is,n,idx,mode));
699: return(0);
700: }
702: PetscErrorCode ISGeneralSetIndices_General(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
703: {
705: IS_General *sub = (IS_General*)is->data;
708: if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
711: PetscLayoutSetLocalSize(is->map, n);
712: PetscLayoutSetUp(is->map);
714: if (sub->allocated) {PetscFree(sub->idx);}
715: if (mode == PETSC_COPY_VALUES) {
716: PetscMalloc1(n,&sub->idx);
717: PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
718: PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));
719: sub->allocated = PETSC_TRUE;
720: } else if (mode == PETSC_OWN_POINTER) {
721: sub->idx = (PetscInt*)idx;
722: PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
723: sub->allocated = PETSC_TRUE;
724: } else {
725: sub->idx = (PetscInt*)idx;
726: sub->allocated = PETSC_FALSE;
727: }
729: ISSetUp_General(is);
730: ISViewFromOptions(is,NULL,"-is_view");
731: return(0);
732: }
734: PETSC_EXTERN PetscErrorCode ISCreate_General(IS is)
735: {
737: IS_General *sub;
740: PetscNewLog(is,&sub);
741: is->data = (void *) sub;
742: PetscMemcpy(is->ops,&myops,sizeof(myops));
743: PetscObjectComposeFunction((PetscObject)is,"ISGeneralSetIndices_C",ISGeneralSetIndices_General);
744: return(0);
745: }