Actual source code: general.c
1: /*
2: Provides the functions for index sets (IS) defined by a list of integers.
3: */
4: #include src/vec/is/impls/general/general.h
6: EXTERN PetscErrorCode VecInitializePackage(char *);
10: PetscErrorCode ISDuplicate_General(IS is,IS *newIS)
11: {
13: IS_General *sub = (IS_General *)is->data;
16: ISCreateGeneral(is->comm,sub->n,sub->idx,newIS);
17: return(0);
18: }
22: PetscErrorCode ISDestroy_General(IS is)
23: {
24: IS_General *is_general = (IS_General*)is->data;
28: if (is_general->allocated) {
29: PetscFree(is_general->idx);
30: }
31: PetscFree(is_general);
32: PetscLogObjectDestroy(is);
33: PetscHeaderDestroy(is);
34: return(0);
35: }
39: PetscErrorCode ISIdentity_General(IS is,PetscTruth *ident)
40: {
41: IS_General *is_general = (IS_General*)is->data;
42: PetscInt i,n = is_general->n,*idx = is_general->idx;
45: is->isidentity = PETSC_TRUE;
46: *ident = PETSC_TRUE;
47: for (i=0; i<n; i++) {
48: if (idx[i] != i) {
49: is->isidentity = PETSC_FALSE;
50: *ident = PETSC_FALSE;
51: break;
52: }
53: }
54: return(0);
55: }
59: PetscErrorCode ISGetIndices_General(IS in,PetscInt **idx)
60: {
61: IS_General *sub = (IS_General*)in->data;
64: *idx = sub->idx;
65: return(0);
66: }
70: PetscErrorCode ISRestoreIndices_General(IS in,PetscInt **idx)
71: {
72: IS_General *sub = (IS_General*)in->data;
75: if (*idx != sub->idx) {
76: SETERRQ(PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
77: }
78: return(0);
79: }
83: PetscErrorCode ISGetSize_General(IS is,PetscInt *size)
84: {
85: IS_General *sub = (IS_General *)is->data;
88: *size = sub->N;
89: return(0);
90: }
94: PetscErrorCode ISGetLocalSize_General(IS is,PetscInt *size)
95: {
96: IS_General *sub = (IS_General *)is->data;
99: *size = sub->n;
100: return(0);
101: }
105: PetscErrorCode ISInvertPermutation_General(IS is,PetscInt nlocal,IS *isout)
106: {
107: IS_General *sub = (IS_General *)is->data;
108: PetscInt i,*ii,n = sub->n,*idx = sub->idx,nstart;
109: PetscMPIInt size;
110: IS istmp,nistmp;
114: MPI_Comm_size(is->comm,&size);
115: if (size == 1) {
116: PetscMalloc(n*sizeof(PetscInt),&ii);
117: for (i=0; i<n; i++) {
118: ii[idx[i]] = i;
119: }
120: ISCreateGeneral(PETSC_COMM_SELF,n,ii,isout);
121: ISSetPermutation(*isout);
122: PetscFree(ii);
123: } else {
124: /* crude, nonscalable get entire IS on each processor */
125: ISAllGather(is,&istmp);
126: ISSetPermutation(istmp);
127: ISInvertPermutation(istmp,PETSC_DECIDE,&nistmp);
128: ISDestroy(istmp);
129: /* get the part we need */
130: MPI_Scan(&nlocal,&nstart,1,MPIU_INT,MPI_SUM,is->comm);
131: nstart -= nlocal;
132: ISGetIndices(nistmp,&idx);
133: ISCreateGeneral(is->comm,nlocal,idx+nstart,isout);
134: ISRestoreIndices(nistmp,&idx);
135: ISDestroy(nistmp);
136: }
137: return(0);
138: }
142: PetscErrorCode ISView_General(IS is,PetscViewer viewer)
143: {
144: IS_General *sub = (IS_General *)is->data;
146: PetscInt i,n = sub->n,*idx = sub->idx;
147: PetscTruth iascii;
150: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
151: if (iascii) {
152: MPI_Comm comm;
153: PetscMPIInt rank,size;
155: PetscObjectGetComm((PetscObject)viewer,&comm);
156: MPI_Comm_rank(comm,&rank);
157: MPI_Comm_size(comm,&size);
159: if (size > 1) {
160: if (is->isperm) {
161: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutation\n",rank);
162: }
163: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %D\n",rank,n);
164: for (i=0; i<n; i++) {
165: PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,idx[i]);
166: }
167: } else {
168: if (is->isperm) {
169: PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutation\n");
170: }
171: PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %D\n",n);
172: for (i=0; i<n; i++) {
173: PetscViewerASCIISynchronizedPrintf(viewer,"%D %D\n",i,idx[i]);
174: }
175: }
176: PetscViewerFlush(viewer);
177: } else {
178: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for this object",((PetscObject)viewer)->type_name);
179: }
180: return(0);
181: }
185: PetscErrorCode ISSort_General(IS is)
186: {
187: IS_General *sub = (IS_General *)is->data;
191: if (sub->sorted) return(0);
192: PetscSortInt(sub->n,sub->idx);
193: sub->sorted = PETSC_TRUE;
194: return(0);
195: }
199: PetscErrorCode ISSorted_General(IS is,PetscTruth *flg)
200: {
201: IS_General *sub = (IS_General *)is->data;
204: *flg = sub->sorted;
205: return(0);
206: }
208: static struct _ISOps myops = { ISGetSize_General,
209: ISGetLocalSize_General,
210: ISGetIndices_General,
211: ISRestoreIndices_General,
212: ISInvertPermutation_General,
213: ISSort_General,
214: ISSorted_General,
215: ISDuplicate_General,
216: ISDestroy_General,
217: ISView_General,
218: ISIdentity_General };
222: PetscErrorCode ISCreateGeneral_Private(MPI_Comm comm,IS *is)
223: {
225: IS Nindex = *is;
226: IS_General *sub = (IS_General*)Nindex->data;
227: PetscInt n = sub->n,i,min,max;
228: const PetscInt *idx = sub->idx;
229: PetscTruth sorted = PETSC_TRUE;
230: PetscTruth flg;
234: if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
236: *is = PETSC_NULL;
237: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
238: VecInitializePackage(PETSC_NULL);
239: #endif
241: MPI_Allreduce(&n,&sub->N,1,MPIU_INT,MPI_SUM,comm);
242: for (i=1; i<n; i++) {
243: if (idx[i] < idx[i-1]) {sorted = PETSC_FALSE; break;}
244: }
245: if (n) {min = max = idx[0];} else {min = max = 0;}
246: for (i=1; i<n; i++) {
247: if (idx[i] < min) min = idx[i];
248: if (idx[i] > max) max = idx[i];
249: }
250: sub->sorted = sorted;
251: Nindex->min = min;
252: Nindex->max = max;
253: PetscMemcpy(Nindex->ops,&myops,sizeof(myops));
254: Nindex->isperm = PETSC_FALSE;
255: Nindex->isidentity = PETSC_FALSE;
256: PetscOptionsHasName(PETSC_NULL,"-is_view",&flg);
257: if (flg) {
258: ISView(Nindex,PETSC_VIEWER_STDOUT_(Nindex->comm));
259: }
260: *is = Nindex;
261: return(0);
262: }
264: /*@C
265: ISCreateGeneral - Creates a data structure for an index set
266: containing a list of integers.
268: Collective on MPI_Comm
270: Input Parameters:
271: + comm - the MPI communicator
272: . n - the length of the index set
273: - idx - the list of integers
275: Output Parameter:
276: . is - the new index set
278: Notes:
279: The index array is copied to internally allocated storage. After the call,
280: the user can free the index array.
282: When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
283: conceptually the same as MPI_Group operations. The IS are then
284: distributed sets of indices and thus certain operations on them are
285: collective.
287: Level: beginner
289: Concepts: index sets^creating
290: Concepts: IS^creating
292: .seealso: ISCreateGeneralWithArray(), ISCreateStride(), ISCreateBlock(), ISAllGather()
293: @*/
294: PetscErrorCode ISCreateGeneral(MPI_Comm comm,PetscInt n,const PetscInt idx[],IS *is)
295: {
297: IS Nindex;
298: IS_General *sub;
302: if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
304: *is = PETSC_NULL;
305: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
306: VecInitializePackage(PETSC_NULL);
307: #endif
309: PetscHeaderCreate(Nindex,_p_IS,struct _ISOps,IS_COOKIE,IS_GENERAL,"IS",comm,ISDestroy,ISView);
310: PetscLogObjectCreate(Nindex);
311: PetscNew(IS_General,&sub);
312: PetscLogObjectMemory(Nindex,sizeof(IS_General)+n*sizeof(PetscInt)+sizeof(struct _p_IS));
313: PetscMalloc(n*sizeof(PetscInt),&sub->idx);
314: PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));
315: sub->n = n;
316: sub->allocated = PETSC_TRUE;
317: Nindex->data = (void*)sub;
319: *is = Nindex;
320: ISCreateGeneral_Private(comm,is);
322: return(0);
323: }
325: /*@C
326: ISCreateGeneralWithArray - Creates a data structure for an index set
327: containing a list of integers.
329: Collective on MPI_Comm
331: Input Parameters:
332: + comm - the MPI communicator
333: . n - the length of the index set
334: - idx - the list of integers
336: Output Parameter:
337: . is - the new index set
339: Notes:
340: Unlike with ISCreateGeneral, the indices are not copied to internally
341: allocated storage. The user array is not freed by ISDestroy.
343: When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
344: conceptually the same as MPI_Group operations. The IS are then
345: distributed sets of indices and thus certain operations on them are collective.
347: Level: beginner
349: Concepts: index sets^creating
350: Concepts: IS^creating
352: .seealso: ISCreateGeneral(), ISCreateStride(), ISCreateBlock(), ISAllGather()
353: @*/
354: PetscErrorCode ISCreateGeneralWithArray(MPI_Comm comm,PetscInt n,PetscInt idx[],IS *is)
355: {
357: IS Nindex;
358: IS_General *sub;
362: if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
364: *is = PETSC_NULL;
365: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
366: VecInitializePackage(PETSC_NULL);
367: #endif
369: PetscHeaderCreate(Nindex,_p_IS,struct _ISOps,IS_COOKIE,IS_GENERAL,"IS",comm,ISDestroy,ISView);
370: PetscLogObjectCreate(Nindex);
371: PetscNew(IS_General,&sub);
372: PetscLogObjectMemory(Nindex,sizeof(IS_General)+n*sizeof(PetscInt)+sizeof(struct _p_IS));
373: sub->idx = idx;
374: sub->n = n;
375: sub->allocated = PETSC_FALSE;
376: Nindex->data = (void*)sub;
378: *is = Nindex;
379: ISCreateGeneral_Private(comm,is);
381: return(0);
382: }