Actual source code: general.c
petsc-3.14.6 2021-03-30
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: PetscObjectComposeFunction((PetscObject)is,"ISGeneralFilter_C",NULL);
30: PetscFree(is->data);
31: return(0);
32: }
34: static PetscErrorCode ISCopy_General(IS is,IS isy)
35: {
36: IS_General *is_general = (IS_General*)is->data,*isy_general = (IS_General*)isy->data;
37: PetscInt n, N, ny, Ny;
41: PetscLayoutGetLocalSize(is->map, &n);
42: PetscLayoutGetSize(is->map, &N);
43: PetscLayoutGetLocalSize(isy->map, &ny);
44: PetscLayoutGetSize(isy->map, &Ny);
45: if (n != ny || N != Ny) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Index sets incompatible");
46: PetscArraycpy(isy_general->idx,is_general->idx,n);
47: return(0);
48: }
50: static PetscErrorCode ISOnComm_General(IS is,MPI_Comm comm,PetscCopyMode mode,IS *newis)
51: {
53: IS_General *sub = (IS_General*)is->data;
54: PetscInt n;
57: if (mode == PETSC_OWN_POINTER) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Cannot use PETSC_OWN_POINTER");
58: PetscLayoutGetLocalSize(is->map, &n);
59: ISCreateGeneral(comm,n,sub->idx,mode,newis);
60: return(0);
61: }
63: static PetscErrorCode ISSetBlockSize_General(IS is,PetscInt bs)
64: {
68: PetscLayoutSetBlockSize(is->map, bs);
69: return(0);
70: }
72: static PetscErrorCode ISContiguousLocal_General(IS is,PetscInt gstart,PetscInt gend,PetscInt *start,PetscBool *contig)
73: {
74: IS_General *sub = (IS_General*)is->data;
75: PetscInt n,i,p;
79: *start = 0;
80: *contig = PETSC_TRUE;
81: PetscLayoutGetLocalSize(is->map, &n);
82: if (!n) return(0);
83: p = sub->idx[0];
84: if (p < gstart) goto nomatch;
85: *start = p - gstart;
86: if (n > gend-p) goto nomatch;
87: for (i=1; i<n; i++,p++) {
88: if (sub->idx[i] != p+1) goto nomatch;
89: }
90: return(0);
91: nomatch:
92: *start = -1;
93: *contig = PETSC_FALSE;
94: return(0);
95: }
97: static PetscErrorCode ISLocate_General(IS is,PetscInt key,PetscInt *location)
98: {
99: IS_General *sub = (IS_General*)is->data;
100: PetscInt numIdx, i;
101: PetscBool sorted;
105: PetscLayoutGetLocalSize(is->map,&numIdx);
106: ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,&sorted);
107: if (sorted) {PetscFindInt(key,numIdx,sub->idx,location);}
108: else {
109: const PetscInt *idx = sub->idx;
111: *location = -1;
112: for (i = 0; i < numIdx; i++) {
113: if (idx[i] == key) {
114: *location = i;
115: return(0);
116: }
117: }
118: }
119: return(0);
120: }
122: static PetscErrorCode ISGetIndices_General(IS in,const PetscInt *idx[])
123: {
124: IS_General *sub = (IS_General*)in->data;
127: *idx = sub->idx;
128: return(0);
129: }
131: static PetscErrorCode ISRestoreIndices_General(IS in,const PetscInt *idx[])
132: {
133: IS_General *sub = (IS_General*)in->data;
136: /* F90Array1dCreate() inside ISRestoreArrayF90() does not keep array when zero length array */
137: if (in->map->n > 0 && *idx != sub->idx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
138: return(0);
139: }
141: static PetscErrorCode ISInvertPermutation_General(IS is,PetscInt nlocal,IS *isout)
142: {
143: IS_General *sub = (IS_General*)is->data;
144: PetscInt i,*ii,n,nstart;
145: const PetscInt *idx = sub->idx;
146: PetscMPIInt size;
147: IS istmp,nistmp;
151: PetscLayoutGetLocalSize(is->map, &n);
152: MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);
153: if (size == 1) {
154: PetscMalloc1(n,&ii);
155: for (i=0; i<n; i++) ii[idx[i]] = i;
156: ISCreateGeneral(PETSC_COMM_SELF,n,ii,PETSC_OWN_POINTER,isout);
157: ISSetPermutation(*isout);
158: } else {
159: /* crude, nonscalable get entire IS on each processor */
160: ISAllGather(is,&istmp);
161: ISSetPermutation(istmp);
162: ISInvertPermutation(istmp,PETSC_DECIDE,&nistmp);
163: ISDestroy(&istmp);
164: /* get the part we need */
165: if (nlocal == PETSC_DECIDE) nlocal = n;
166: MPI_Scan(&nlocal,&nstart,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)is));
167: if (PetscDefined(USE_DEBUG)) {
168: PetscInt N;
169: PetscMPIInt rank;
170: MPI_Comm_rank(PetscObjectComm((PetscObject)is),&rank);
171: PetscLayoutGetSize(is->map, &N);
172: if (rank == size-1) {
173: if (nstart != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of nlocal lengths %d != total IS length %d",nstart,N);
174: }
175: }
176: nstart -= nlocal;
177: ISGetIndices(nistmp,&idx);
178: ISCreateGeneral(PetscObjectComm((PetscObject)is),nlocal,idx+nstart,PETSC_COPY_VALUES,isout);
179: ISRestoreIndices(nistmp,&idx);
180: ISDestroy(&nistmp);
181: }
182: return(0);
183: }
185: #if defined(PETSC_HAVE_HDF5)
186: static PetscErrorCode ISView_General_HDF5(IS is, PetscViewer viewer)
187: {
188: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
189: hid_t filespace; /* file dataspace identifier */
190: hid_t chunkspace; /* chunk dataset property identifier */
191: hid_t dset_id; /* dataset identifier */
192: hid_t memspace; /* memory dataspace identifier */
193: hid_t inttype; /* int type (H5T_NATIVE_INT or H5T_NATIVE_LLONG) */
194: hid_t file_id, group;
195: hsize_t dim, maxDims[3], dims[3], chunkDims[3], count[3],offset[3];
196: PetscInt bs, N, n, timestep, low;
197: const PetscInt *ind;
198: const char *isname;
199: PetscErrorCode ierr;
202: ISGetBlockSize(is,&bs);
203: bs = PetscMax(bs, 1); /* If N = 0, bs = 0 as well */
204: PetscViewerHDF5OpenGroup(viewer, &file_id, &group);
205: PetscViewerHDF5GetTimestep(viewer, ×tep);
207: /* Create the dataspace for the dataset.
208: *
209: * dims - holds the current dimensions of the dataset
210: *
211: * maxDims - holds the maximum dimensions of the dataset (unlimited
212: * for the number of time steps with the current dimensions for the
213: * other dimensions; so only additional time steps can be added).
214: *
215: * chunkDims - holds the size of a single time step (required to
216: * permit extending dataset).
217: */
218: dim = 0;
219: if (timestep >= 0) {
220: dims[dim] = timestep+1;
221: maxDims[dim] = H5S_UNLIMITED;
222: chunkDims[dim] = 1;
223: ++dim;
224: }
225: ISGetSize(is, &N);
226: ISGetLocalSize(is, &n);
227: PetscHDF5IntCast(N/bs,dims + dim);
229: maxDims[dim] = dims[dim];
230: chunkDims[dim] = PetscMax(1,dims[dim]);
231: ++dim;
232: if (bs >= 1) {
233: dims[dim] = bs;
234: maxDims[dim] = dims[dim];
235: chunkDims[dim] = dims[dim];
236: ++dim;
237: }
238: PetscStackCallHDF5Return(filespace,H5Screate_simple,(dim, dims, maxDims));
240: #if defined(PETSC_USE_64BIT_INDICES)
241: inttype = H5T_NATIVE_LLONG;
242: #else
243: inttype = H5T_NATIVE_INT;
244: #endif
246: /* Create the dataset with default properties and close filespace */
247: PetscObjectGetName((PetscObject) is, &isname);
248: if (!H5Lexists(group, isname, H5P_DEFAULT)) {
249: /* Create chunk */
250: PetscStackCallHDF5Return(chunkspace,H5Pcreate,(H5P_DATASET_CREATE));
251: PetscStackCallHDF5(H5Pset_chunk,(chunkspace, dim, chunkDims));
253: PetscStackCallHDF5Return(dset_id,H5Dcreate2,(group, isname, inttype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT));
254: PetscStackCallHDF5(H5Pclose,(chunkspace));
255: } else {
256: PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, isname, H5P_DEFAULT));
257: PetscStackCallHDF5(H5Dset_extent,(dset_id, dims));
258: }
259: PetscStackCallHDF5(H5Sclose,(filespace));
261: /* Each process defines a dataset and writes it to the hyperslab in the file */
262: dim = 0;
263: if (timestep >= 0) {
264: count[dim] = 1;
265: ++dim;
266: }
267: PetscHDF5IntCast(n/bs,count + dim);
268: ++dim;
269: if (bs >= 1) {
270: count[dim] = bs;
271: ++dim;
272: }
273: if (n > 0 || H5_VERSION_GE(1,10,0)) {
274: PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL));
275: } else {
276: /* Can't create dataspace with zero for any dimension, so create null dataspace. */
277: PetscStackCallHDF5Return(memspace,H5Screate,(H5S_NULL));
278: }
280: /* Select hyperslab in the file */
281: PetscLayoutGetRange(is->map, &low, NULL);
282: dim = 0;
283: if (timestep >= 0) {
284: offset[dim] = timestep;
285: ++dim;
286: }
287: PetscHDF5IntCast(low/bs,offset + dim);
288: ++dim;
289: if (bs >= 1) {
290: offset[dim] = 0;
291: ++dim;
292: }
293: if (n > 0 || H5_VERSION_GE(1,10,0)) {
294: PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id));
295: PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL));
296: } else {
297: /* Create null filespace to match null memspace. */
298: PetscStackCallHDF5Return(filespace,H5Screate,(H5S_NULL));
299: }
301: ISGetIndices(is, &ind);
302: PetscStackCallHDF5(H5Dwrite,(dset_id, inttype, memspace, filespace, hdf5->dxpl_id, ind));
303: PetscStackCallHDF5(H5Fflush,(file_id, H5F_SCOPE_GLOBAL));
304: ISRestoreIndices(is, &ind);
306: /* Close/release resources */
307: PetscStackCallHDF5(H5Gclose,(group));
308: PetscStackCallHDF5(H5Sclose,(filespace));
309: PetscStackCallHDF5(H5Sclose,(memspace));
310: PetscStackCallHDF5(H5Dclose,(dset_id));
311: PetscInfo1(is, "Wrote IS object with name %s\n", isname);
312: return(0);
313: }
314: #endif
316: static PetscErrorCode ISView_General(IS is,PetscViewer viewer)
317: {
318: IS_General *sub = (IS_General*)is->data;
320: PetscInt i,n,*idx = sub->idx;
321: PetscBool iascii,isbinary,ishdf5;
324: PetscLayoutGetLocalSize(is->map, &n);
325: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
326: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
327: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
328: if (iascii) {
329: MPI_Comm comm;
330: PetscMPIInt rank,size;
331: PetscViewerFormat fmt;
332: PetscBool isperm;
334: PetscObjectGetComm((PetscObject)viewer,&comm);
335: MPI_Comm_rank(comm,&rank);
336: MPI_Comm_size(comm,&size);
338: PetscViewerGetFormat(viewer,&fmt);
339: ISGetInfo(is,IS_PERMUTATION,IS_LOCAL,PETSC_FALSE,&isperm);
340: if (isperm && fmt != PETSC_VIEWER_ASCII_MATLAB) {PetscViewerASCIIPrintf(viewer,"Index set is permutation\n");}
341: PetscViewerASCIIPushSynchronized(viewer);
342: if (size > 1) {
343: if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
344: const char* name;
346: PetscObjectGetName((PetscObject)is,&name);
347: PetscViewerASCIISynchronizedPrintf(viewer,"%s_%d = [...\n",name,rank);
348: for (i=0; i<n; i++) {
349: PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
350: }
351: PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
352: } else {
353: PetscInt st = 0;
355: if (fmt == PETSC_VIEWER_ASCII_INDEX) st = is->map->rstart;
356: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
357: for (i=0; i<n; i++) {
358: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i + st,idx[i]);
359: }
360: }
361: } else {
362: if (fmt == PETSC_VIEWER_ASCII_MATLAB) {
363: const char* name;
365: PetscObjectGetName((PetscObject)is,&name);
366: PetscViewerASCIISynchronizedPrintf(viewer,"%s = [...\n",name);
367: for (i=0; i<n; i++) {
368: PetscViewerASCIISynchronizedPrintf(viewer,"%D\n",idx[i]+1);
369: }
370: PetscViewerASCIISynchronizedPrintf(viewer,"];\n");
371: } else {
372: PetscInt st = 0;
374: if (fmt == PETSC_VIEWER_ASCII_INDEX) st = is->map->rstart;
375: PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
376: for (i=0; i<n; i++) {
377: PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i + st,idx[i]);
378: }
379: }
380: }
381: PetscViewerFlush(viewer);
382: PetscViewerASCIIPopSynchronized(viewer);
383: } else if (isbinary) {
384: ISView_Binary(is,viewer);
385: } else if (ishdf5) {
386: #if defined(PETSC_HAVE_HDF5)
387: ISView_General_HDF5(is,viewer);
388: #endif
389: }
390: return(0);
391: }
393: static PetscErrorCode ISSort_General(IS is)
394: {
395: IS_General *sub = (IS_General*)is->data;
396: PetscInt n;
400: PetscLayoutGetLocalSize(is->map, &n);
401: PetscIntSortSemiOrdered(n,sub->idx);
402: return(0);
403: }
405: static PetscErrorCode ISSortRemoveDups_General(IS is)
406: {
407: IS_General *sub = (IS_General*)is->data;
408: PetscLayout map;
409: PetscInt n;
410: PetscBool sorted;
414: PetscLayoutGetLocalSize(is->map, &n);
415: ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,&sorted);
416: if (sorted) {
417: PetscSortedRemoveDupsInt(&n,sub->idx);
418: } else {
419: PetscSortRemoveDupsInt(&n,sub->idx);
420: }
421: PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is), n, PETSC_DECIDE, is->map->bs, &map);
422: PetscLayoutDestroy(&is->map);
423: is->map = map;
424: return(0);
425: }
427: static PetscErrorCode ISSorted_General(IS is,PetscBool *flg)
428: {
432: ISGetInfo(is,IS_SORTED,IS_LOCAL,PETSC_TRUE,flg);
433: return(0);
434: }
436: PetscErrorCode ISToGeneral_General(IS is)
437: {
439: return(0);
440: }
442: static struct _ISOps myops = { ISGetIndices_General,
443: ISRestoreIndices_General,
444: ISInvertPermutation_General,
445: ISSort_General,
446: ISSortRemoveDups_General,
447: ISSorted_General,
448: ISDuplicate_General,
449: ISDestroy_General,
450: ISView_General,
451: ISLoad_Default,
452: ISCopy_General,
453: ISToGeneral_General,
454: ISOnComm_General,
455: ISSetBlockSize_General,
456: ISContiguousLocal_General,
457: ISLocate_General,
458: /* no specializations of {sorted,unique,perm,interval}{local,global}
459: * because the default checks in ISGetInfo_XXX in index.c are exactly
460: * what we would do for ISGeneral */
461: NULL,
462: NULL,
463: NULL,
464: NULL,
465: NULL,
466: NULL,
467: NULL,
468: NULL};
470: PETSC_INTERN PetscErrorCode ISSetUp_General(IS);
472: PetscErrorCode ISSetUp_General(IS is)
473: {
475: IS_General *sub = (IS_General*)is->data;
476: const PetscInt *idx = sub->idx;
477: PetscInt n,i,min,max;
480: PetscLayoutGetLocalSize(is->map, &n);
482: if (n) {
483: min = max = idx[0];
484: for (i=1; i<n; i++) {
485: if (idx[i] < min) min = idx[i];
486: if (idx[i] > max) max = idx[i];
487: }
488: is->min = min;
489: is->max = max;
490: } else {
491: is->min = PETSC_MAX_INT;
492: is->max = PETSC_MIN_INT;
493: }
494: return(0);
495: }
497: /*@
498: ISCreateGeneral - Creates a data structure for an index set
499: containing a list of integers.
501: Collective
503: Input Parameters:
504: + comm - the MPI communicator
505: . n - the length of the index set
506: . idx - the list of integers
507: - mode - PETSC_COPY_VALUES, PETSC_OWN_POINTER, or PETSC_USE_POINTER; see PetscCopyMode for meaning of this flag.
509: Output Parameter:
510: . is - the new index set
512: Notes:
513: When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
514: conceptually the same as MPI_Group operations. The IS are then
515: distributed sets of indices and thus certain operations on them are
516: collective.
518: Level: beginner
520: .seealso: ISCreateStride(), ISCreateBlock(), ISAllGather(), PETSC_COPY_VALUES, PETSC_OWN_POINTER, PETSC_USE_POINTER, PetscCopyMode
521: @*/
522: PetscErrorCode ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
523: {
527: ISCreate(comm,is);
528: ISSetType(*is,ISGENERAL);
529: ISGeneralSetIndices(*is,n,idx,mode);
530: return(0);
531: }
533: /*@
534: ISGeneralSetIndices - Sets the indices for an ISGENERAL index set
536: Collective on IS
538: Input Parameters:
539: + is - the index set
540: . n - the length of the index set
541: . idx - the list of integers
542: - mode - see PetscCopyMode for meaning of this flag.
544: Level: beginner
546: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather(), ISBlockSetIndices(), ISGENERAL, PetscCopyMode
547: @*/
548: PetscErrorCode ISGeneralSetIndices(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
549: {
553: ISClearInfoCache(is,PETSC_FALSE);
554: PetscUseMethod(is,"ISGeneralSetIndices_C",(IS,PetscInt,const PetscInt[],PetscCopyMode),(is,n,idx,mode));
555: return(0);
556: }
558: PetscErrorCode ISGeneralSetIndices_General(IS is,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
559: {
560: PetscLayout map;
562: IS_General *sub = (IS_General*)is->data;
565: if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
568: PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)is),n,PETSC_DECIDE,is->map->bs,&map);
569: PetscLayoutDestroy(&is->map);
570: is->map = map;
572: if (sub->allocated) {PetscFree(sub->idx);}
573: if (mode == PETSC_COPY_VALUES) {
574: PetscMalloc1(n,&sub->idx);
575: PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
576: PetscArraycpy(sub->idx,idx,n);
577: sub->allocated = PETSC_TRUE;
578: } else if (mode == PETSC_OWN_POINTER) {
579: sub->idx = (PetscInt*)idx;
580: PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));
581: sub->allocated = PETSC_TRUE;
582: } else {
583: sub->idx = (PetscInt*)idx;
584: sub->allocated = PETSC_FALSE;
585: }
587: ISSetUp_General(is);
588: ISViewFromOptions(is,NULL,"-is_view");
589: return(0);
590: }
592: static PetscErrorCode ISGeneralFilter_General(IS is, PetscInt start, PetscInt end)
593: {
594: IS_General *sub = (IS_General*)is->data;
595: PetscInt *idx = sub->idx,*idxnew;
596: PetscInt i,n = is->map->n,nnew = 0,o;
600: for (i=0; i<n; ++i)
601: if (idx[i] >= start && idx[i] < end)
602: nnew++;
603: PetscMalloc1(nnew, &idxnew);
604: for (o=0, i=0; i<n; i++) {
605: if (idx[i] >= start && idx[i] < end)
606: idxnew[o++] = idx[i];
607: }
608: ISGeneralSetIndices_General(is,nnew,idxnew,PETSC_OWN_POINTER);
609: return(0);
610: }
612: /*@
613: ISGeneralFilter - Remove all indices outside of [start, end)
615: Collective on IS
617: Input Parameters:
618: + is - the index set
619: . start - the lowest index kept
620: - end - one more than the highest index kept
622: Level: beginner
624: .seealso: ISCreateGeneral(), ISGeneralSetIndices()
625: @*/
626: PetscErrorCode ISGeneralFilter(IS is, PetscInt start, PetscInt end)
627: {
632: ISClearInfoCache(is,PETSC_FALSE);
633: PetscUseMethod(is,"ISGeneralFilter_C",(IS,PetscInt,PetscInt),(is,start,end));
634: return(0);
635: }
637: PETSC_EXTERN PetscErrorCode ISCreate_General(IS is)
638: {
640: IS_General *sub;
643: PetscNewLog(is,&sub);
644: is->data = (void *) sub;
645: PetscMemcpy(is->ops,&myops,sizeof(myops));
646: PetscObjectComposeFunction((PetscObject)is,"ISGeneralSetIndices_C",ISGeneralSetIndices_General);
647: PetscObjectComposeFunction((PetscObject)is,"ISGeneralFilter_C",ISGeneralFilter_General);
648: return(0);
649: }