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: int ISDuplicate_General(IS is,IS *newIS)
  8: {
  9:   int        ierr;
 10:   IS_General *sub = (IS_General *)is->data;

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

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

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

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

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

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

 53:   *idx = sub->idx;
 54:   return(0);
 55: }

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

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

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

 73:   *size = sub->N;
 74:   return(0);
 75: }

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

 82:   *size = sub->n;
 83:   return(0);
 84: }

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

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

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

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

131:     PetscObjectGetComm((PetscObject)viewer,&comm);
132:     MPI_Comm_rank(comm,&rank);
133:     MPI_Comm_size(comm,&size);

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

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

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

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

176:   *flg = sub->sorted;
177:   return(0);
178: }

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

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

196:    Collective on MPI_Comm

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

203:    Output Parameter:
204: .  is - the new index set

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

211:    Level: beginner

213:   Concepts: index sets^creating
214:   Concepts: IS^creating

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

228:   if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"length < 0");

231:   *is = 0;
232:   PetscHeaderCreate(Nindex,_p_IS,struct _ISOps,IS_COOKIE,IS_GENERAL,"IS",comm,ISDestroy,ISView);
233:   PetscLogObjectCreate(Nindex);
234:   ierr           = PetscNew(IS_General,&sub);
235:   PetscLogObjectMemory(Nindex,sizeof(IS_General)+n*sizeof(int)+sizeof(struct _p_IS));
236:   ierr           = PetscMalloc((n+1)*sizeof(int),&sub->idx);
237:   sub->n         = n;

239:   MPI_Allreduce(&n,&sub->N,1,MPI_INT,MPI_SUM,comm);
240:   for (i=1; i<n; i++) {
241:     if (idx[i] < idx[i-1]) {sorted = PETSC_FALSE; break;}
242:   }
243:   if (n) {min = max = idx[0];} else {min = max = 0;}
244:   for (i=1; i<n; i++) {
245:     if (idx[i] < min) min = idx[i];
246:     if (idx[i] > max) max = idx[i];
247:   }
248:   PetscMemcpy(sub->idx,idx,n*sizeof(int));
249:   sub->sorted     = sorted;
250:   Nindex->min     = min;
251:   Nindex->max     = max;
252:   Nindex->data    = (void*)sub;
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: }