Actual source code: general.c

  1: /*$Id: general.c,v 1.103 2001/03/23 23:21:08 balay Exp $*/
  2: /*
  3:      Provides the functions for index sets (IS) defined by a list of integers.
  4: */
 5:  #include src/vec/is/impls/general/general.h

  7: EXTERN int VecInitializePackage(char *);

  9: int ISDuplicate_General(IS is,IS *newIS)
 10: {
 11:   int        ierr;
 12:   IS_General *sub = (IS_General *)is->data;

 15:   ISCreateGeneral(is->comm,sub->n,sub->idx,newIS);
 16:   return(0);
 17: }

 19: int ISDestroy_General(IS is)
 20: {
 21:   IS_General *is_general = (IS_General*)is->data;
 22:   int        ierr;

 25:   PetscFree(is_general->idx);
 26:   PetscFree(is_general);
 27:   PetscLogObjectDestroy(is);
 28:   PetscHeaderDestroy(is);
 29:   return(0);
 30: }

 32: int ISIdentity_General(IS is,PetscTruth *ident)
 33: {
 34:   IS_General *is_general = (IS_General*)is->data;
 35:   int        i,n = is_general->n,*idx = is_general->idx;

 38:   is->isidentity = PETSC_TRUE;
 39:   *ident         = PETSC_TRUE;
 40:   for (i=0; i<n; i++) {
 41:     if (idx[i] != i) {
 42:       is->isidentity = PETSC_FALSE;
 43:       *ident         = PETSC_FALSE;
 44:       break;
 45:     }
 46:   }
 47:   return(0);
 48: }

 50: int ISGetIndices_General(IS in,int **idx)
 51: {
 52:   IS_General *sub = (IS_General*)in->data;

 55:   *idx = sub->idx;
 56:   return(0);
 57: }

 59: int ISRestoreIndices_General(IS in,int **idx)
 60: {
 61:   IS_General *sub = (IS_General*)in->data;

 64:   if (*idx != sub->idx) {
 65:     SETERRQ(PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
 66:   }
 67:   return(0);
 68: }

 70: int ISGetSize_General(IS is,int *size)
 71: {
 72:   IS_General *sub = (IS_General *)is->data;

 75:   *size = sub->N;
 76:   return(0);
 77: }

 79: int ISGetLocalSize_General(IS is,int *size)
 80: {
 81:   IS_General *sub = (IS_General *)is->data;

 84:   *size = sub->n;
 85:   return(0);
 86: }

 88: int ISInvertPermutation_General(IS is,int nlocal,IS *isout)
 89: {
 90:   IS_General *sub = (IS_General *)is->data;
 91:   int        i,ierr,*ii,n = sub->n,*idx = sub->idx,size,nstart;
 92:   IS         istmp,nistmp;

 95:   MPI_Comm_size(is->comm,&size);
 96:   if (size == 1) {
 97:     PetscMalloc(n*sizeof(int),&ii);
 98:     for (i=0; i<n; i++) {
 99:       ii[idx[i]] = i;
100:     }
101:     ISCreateGeneral(PETSC_COMM_SELF,n,ii,isout);
102:     ISSetPermutation(*isout);
103:     PetscFree(ii);
104:   } else {
105:     /* crude, nonscalable get entire IS on each processor */
106:     ISAllGather(is,&istmp);
107:     ISSetPermutation(istmp);
108:     ISInvertPermutation(istmp,PETSC_DECIDE,&nistmp);
109:     ISDestroy(istmp);
110:     /* get the part we need */
111:     ierr    = MPI_Scan(&nlocal,&nstart,1,MPI_INT,MPI_SUM,is->comm);
112:     nstart -= nlocal;
113:     ierr    = ISGetIndices(nistmp,&idx);
114:     ierr    = ISCreateGeneral(is->comm,nlocal,idx+nstart,isout);
115:     ierr    = ISRestoreIndices(nistmp,&idx);
116:     ierr    = ISDestroy(nistmp);
117:   }
118:   return(0);
119: }

121: int ISView_General(IS is,PetscViewer viewer)
122: {
123:   IS_General  *sub = (IS_General *)is->data;
124:   int         i,n = sub->n,*idx = sub->idx,ierr;
125:   PetscTruth  isascii;

128:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
129:   if (isascii) {
130:     MPI_Comm comm;
131:     int      rank,size;

133:     PetscObjectGetComm((PetscObject)viewer,&comm);
134:     MPI_Comm_rank(comm,&rank);
135:     MPI_Comm_size(comm,&size);

137:     if (size > 1) {
138:       if (is->isperm) {
139:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Index set is permutationn",rank);
140:       }
141:       PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of indices in set %dn",rank,n);
142:       for (i=0; i<n; i++) {
143:         PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d %dn",rank,i,idx[i]);
144:       }
145:     } else {
146:       if (is->isperm) {
147:         PetscViewerASCIISynchronizedPrintf(viewer,"Index set is permutationn");
148:       }
149:       PetscViewerASCIISynchronizedPrintf(viewer,"Number of indices in set %dn",n);
150:       for (i=0; i<n; i++) {
151:         PetscViewerASCIISynchronizedPrintf(viewer,"%d %dn",i,idx[i]);
152:       }
153:     }
154:     PetscViewerFlush(viewer);
155:   } else {
156:     SETERRQ1(1,"Viewer type %s not supported for this object",((PetscObject)viewer)->type_name);
157:   }
158:   return(0);
159: }

161: int ISSort_General(IS is)
162: {
163:   IS_General *sub = (IS_General *)is->data;
164:   int        ierr;

167:   if (sub->sorted) return(0);
168:   PetscSortInt(sub->n,sub->idx);
169:   sub->sorted = PETSC_TRUE;
170:   return(0);
171: }

173: int ISSorted_General(IS is,PetscTruth *flg)
174: {
175:   IS_General *sub = (IS_General *)is->data;

178:   *flg = sub->sorted;
179:   return(0);
180: }

182: static struct _ISOps myops = { ISGetSize_General,
183:                                ISGetLocalSize_General,
184:                                ISGetIndices_General,
185:                                ISRestoreIndices_General,
186:                                ISInvertPermutation_General,
187:                                ISSort_General,
188:                                ISSorted_General,
189:                                ISDuplicate_General,
190:                                ISDestroy_General,
191:                                ISView_General,
192:                                ISIdentity_General };

194: /*@C
195:    ISCreateGeneral - Creates a data structure for an index set 
196:    containing a list of integers.

198:    Collective on MPI_Comm

200:    Input Parameters:
201: +  comm - the MPI communicator
202: .  n - the length of the index set
203: -  idx - the list of integers

205:    Output Parameter:
206: .  is - the new index set

208:    Notes:
209:    When the communicator is not MPI_COMM_SELF, the operations on IS are NOT
210:    conceptually the same as MPI_Group operations. The IS are then
211:    distributed sets of indices and thus certain operations on them are collective.

213:    Level: beginner

215:   Concepts: index sets^creating
216:   Concepts: IS^creating

218: .seealso: ISCreateStride(), ISCreateBlock(), ISAllGather()
219: @*/
220: int ISCreateGeneral(MPI_Comm comm,int n,const int idx[],IS *is)
221: {
222:   int        i,min,max,ierr;
223:   PetscTruth sorted = PETSC_TRUE;
224:   IS         Nindex;
225:   IS_General *sub;
226:   PetscTruth flg;

230:   if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
232:   *is = PETSC_NULL;
233: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
234:   VecInitializePackage(PETSC_NULL);
235: #endif

237:   PetscHeaderCreate(Nindex,_p_IS,struct _ISOps,IS_COOKIE,IS_GENERAL,"IS",comm,ISDestroy,ISView);
238:   PetscLogObjectCreate(Nindex);
239:   ierr           = PetscNew(IS_General,&sub);
240:   PetscLogObjectMemory(Nindex,sizeof(IS_General)+n*sizeof(int)+sizeof(struct _p_IS));
241:   ierr           = PetscMalloc((n+1)*sizeof(int),&sub->idx);
242:   sub->n         = n;

244:   MPI_Allreduce(&n,&sub->N,1,MPI_INT,MPI_SUM,comm);
245:   for (i=1; i<n; i++) {
246:     if (idx[i] < idx[i-1]) {sorted = PETSC_FALSE; break;}
247:   }
248:   if (n) {min = max = idx[0];} else {min = max = 0;}
249:   for (i=1; i<n; i++) {
250:     if (idx[i] < min) min = idx[i];
251:     if (idx[i] > max) max = idx[i];
252:   }
253:   PetscMemcpy(sub->idx,idx,n*sizeof(int));
254:   sub->sorted     = sorted;
255:   Nindex->min     = min;
256:   Nindex->max     = max;
257:   Nindex->data    = (void*)sub;
258:   PetscMemcpy(Nindex->ops,&myops,sizeof(myops));
259:   Nindex->isperm     = PETSC_FALSE;
260:   Nindex->isidentity = PETSC_FALSE;
261:   PetscOptionsHasName(PETSC_NULL,"-is_view",&flg);
262:   if (flg) {
263:     ISView(Nindex,PETSC_VIEWER_STDOUT_(Nindex->comm));
264:   }
265:   *is = Nindex;
266:   return(0);
267: }