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