Actual source code: aobasic.c

  1: /*$Id: aobasic.c,v 1.60 2001/03/23 23:24:52 balay Exp $*/

  3: /*
  4:     The most basic AO application ordering routines. These store the 
  5:   entire orderings on each processor.
  6: */

 8:  #include src/dm/ao/aoimpl.h
 9:  #include petscsys.h

 11: typedef struct {
 12:   int N;
 13:   int *app,*petsc;  /* app[i] is the partner for the ith PETSc slot */
 14:                     /* petsc[j] is the partner for the jth app slot */
 15: } AO_Basic;

 17: /*
 18:        All processors have the same data so processor 1 prints it
 19: */
 20: int AOView_Basic(AO ao,PetscViewer viewer)
 21: {
 22:   int        rank,ierr,i;
 23:   AO_Basic   *aodebug = (AO_Basic*)ao->data;
 24:   PetscTruth isascii;

 27:   MPI_Comm_rank(ao->comm,&rank);
 28:   if (!rank){
 29:     PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
 30:     if (isascii) {
 31:       PetscViewerASCIIPrintf(viewer,"Number of elements in ordering %dn",aodebug->N);
 32:       PetscViewerASCIIPrintf(viewer,  "PETSc->App  App->PETScn");
 33:       for (i=0; i<aodebug->N; i++) {
 34:         PetscViewerASCIIPrintf(viewer,"%3d  %3d    %3d  %3dn",i,aodebug->app[i],i,aodebug->petsc[i]);
 35:       }
 36:     } else {
 37:       SETERRQ1(1,"Viewer type %s not supported for AOData basic",((PetscObject)viewer)->type_name);
 38:     }
 39:   }
 40:   PetscViewerFlush(viewer);
 41:   return(0);
 42: }

 44: int AODestroy_Basic(AO ao)
 45: {
 46:   AO_Basic *aodebug = (AO_Basic*)ao->data;
 47:   int      ierr;

 50:   PetscFree(aodebug->app);
 51:   PetscFree(ao->data);
 52:   return(0);
 53: }

 55: int AOBasicGetIndices_Private(AO ao,int **app,int **petsc)
 56: {
 57:   AO_Basic *basic = (AO_Basic*)ao->data;

 60:   if (app)   *app   = basic->app;
 61:   if (petsc) *petsc = basic->petsc;
 62:   return(0);
 63: }

 65: int AOPetscToApplication_Basic(AO ao,int n,int *ia)
 66: {
 67:   int      i;
 68:   AO_Basic *aodebug = (AO_Basic*)ao->data;

 71:   for (i=0; i<n; i++) {
 72:     if (ia[i] >= 0) {ia[i] = aodebug->app[ia[i]];}
 73:   }
 74:   return(0);
 75: }

 77: int AOApplicationToPetsc_Basic(AO ao,int n,int *ia)
 78: {
 79:   int      i;
 80:   AO_Basic *aodebug = (AO_Basic*)ao->data;

 83:   for (i=0; i<n; i++) {
 84:     if (ia[i] >= 0) {ia[i] = aodebug->petsc[ia[i]];}
 85:   }
 86:   return(0);
 87: }

 89: int AOPetscToApplicationPermuteInt_Basic(AO ao, int block, int *array)
 90: {
 91:   AO_Basic *aodebug = (AO_Basic *) ao->data;
 92:   int      *temp;
 93:   int       i, j;
 94:   int       ierr;

 97:   PetscMalloc(aodebug->N*block * sizeof(int), &temp);
 98:   for(i = 0; i < aodebug->N; i++) {
 99:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->petsc[i]*block+j];
100:   }
101:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(int));
102:   PetscFree(temp);
103:   return(0);
104: }

106: int AOApplicationToPetscPermuteInt_Basic(AO ao, int block, int *array)
107: {
108:   AO_Basic *aodebug = (AO_Basic *) ao->data;
109:   int      *temp;
110:   int       i, j;
111:   int       ierr;

114:   PetscMalloc(aodebug->N*block * sizeof(int), &temp);
115:   for(i = 0; i < aodebug->N; i++) {
116:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->app[i]*block+j];
117:   }
118:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(int));
119:   PetscFree(temp);
120:   return(0);
121: }

123: int AOPetscToApplicationPermuteReal_Basic(AO ao, int block, double *array)
124: {
125:   AO_Basic *aodebug = (AO_Basic *) ao->data;
126:   double   *temp;
127:   int       i, j;
128:   int       ierr;

131:   PetscMalloc(aodebug->N*block * sizeof(double), &temp);
132:   for(i = 0; i < aodebug->N; i++) {
133:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->petsc[i]*block+j];
134:   }
135:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(double));
136:   PetscFree(temp);
137:   return(0);
138: }

140: int AOApplicationToPetscPermuteReal_Basic(AO ao, int block, double *array)
141: {
142:   AO_Basic *aodebug = (AO_Basic *) ao->data;
143:   double   *temp;
144:   int       i, j;
145:   int       ierr;

148:   PetscMalloc(aodebug->N*block * sizeof(double), &temp);
149:   for(i = 0; i < aodebug->N; i++) {
150:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->app[i]*block+j];
151:   }
152:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(double));
153:   PetscFree(temp);
154:   return(0);
155: }

157: static struct _AOOps AOops = {AOView_Basic,
158:                               AODestroy_Basic,
159:                               AOPetscToApplication_Basic,
160:                               AOApplicationToPetsc_Basic,
161:                               AOPetscToApplicationPermuteInt_Basic,
162:                               AOApplicationToPetscPermuteInt_Basic,
163:                               AOPetscToApplicationPermuteReal_Basic,
164:                               AOApplicationToPetscPermuteReal_Basic};

166: EXTERN_C_BEGIN
167: int AOSerialize_Basic(MPI_Comm comm, AO *ao, PetscViewer viewer, PetscTruth store)
168: {
169:   AO        a;
170:   AO_Basic *d;
171:   int       fd;
172:   int       ierr;

175:   PetscViewerBinaryGetDescriptor(viewer, &fd);
176:   if (store) {
177:     a = *ao;
178:     d = (AO_Basic *) a->data;
179:     PetscBinaryWrite(fd, &a->N,     1,    PETSC_INT, 0);
180:     PetscBinaryWrite(fd, &a->n,     1,    PETSC_INT, 0);
181:     PetscBinaryWrite(fd, &d->N,     1,    PETSC_INT, 0);
182:     PetscBinaryWrite(fd,  d->app,   d->N, PETSC_INT, 0);
183:     PetscBinaryWrite(fd,  d->petsc, d->N, PETSC_INT, 0);
184:   } else {
185:     PetscHeaderCreate(a, _p_AO, struct _AOOps, AO_COOKIE, AO_BASIC, "AO", comm, AODestroy, AOView);
186:     PetscLogObjectCreate(a);
187:     PetscLogObjectMemory(a, sizeof(AO_Basic) + sizeof(struct _p_AO));
188:     PetscNew(AO_Basic, &d);
189:     a->data = (void *) d;
190:     PetscMemcpy(a->ops, &AOops, sizeof(AOops));

192:     PetscBinaryRead(fd, &a->N,     1,    PETSC_INT);
193:     PetscBinaryRead(fd, &a->n,     1,    PETSC_INT);
194:     PetscBinaryRead(fd, &d->N,     1,    PETSC_INT);
195:     PetscMalloc(d->N*2 * sizeof(int), &d->app);
196:     d->petsc = d->app + d->N;
197:     PetscLogObjectMemory(a, d->N*2 * sizeof(int));
198:     PetscBinaryRead(fd,  d->app,   d->N, PETSC_INT);
199:     PetscBinaryRead(fd,  d->petsc, d->N, PETSC_INT);
200:     *ao = a;
201:   }

203:   return(0);
204: }
205: EXTERN_C_END

207: /*@C
208:    AOCreateBasic - Creates a basic application ordering using two integer arrays.

210:    Collective on MPI_Comm

212:    Input Parameters:
213: +  comm - MPI communicator that is to share AO
214: .  napp - size of integer arrays
215: .  myapp - integer array that defines an ordering
216: -  mypetsc - integer array that defines another ordering (may be PETSC_NULL to 
217:              indicate the natural ordering)

219:    Output Parameter:
220: .  aoout - the new application ordering

222:    Options Database Key:
223: .   -ao_view - call AOView() at the conclusion of AOCreateBasic()

225:    Level: beginner

227: .keywords: AO, create

229: .seealso: AOCreateBasicIS(), AODestroy()
230: @*/
231: int AOCreateBasic(MPI_Comm comm,int napp,int *myapp,int *mypetsc,AO *aoout)
232: {
233:   AO_Basic   *aobasic;
234:   AO         ao;
235:   int        *lens,size,rank,N,i,*petsc,start;
236:   int        *allpetsc,*allapp,*disp,ip,ia;
237:   PetscTruth opt;
238:   int        ierr;

242:   *aoout = 0;
243: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
244:   DMInitializePackage(PETSC_NULL);
245: #endif

247:   PetscHeaderCreate(ao, _p_AO, struct _AOOps, AO_COOKIE, AO_BASIC, "AO", comm, AODestroy, AOView);
248:   PetscLogObjectCreate(ao);
249:   PetscNew(AO_Basic, &aobasic);
250:   PetscLogObjectMemory(ao, sizeof(struct _p_AO) + sizeof(AO_Basic));

252:   PetscMemcpy(ao->ops, &AOops, sizeof(AOops));
253:   PetscStrallocpy(AO_SER_BASIC_BINARY, &ao->serialize_name);
254:   ao->data = (void *) aobasic;

256:   /* transmit all lengths to all processors */
257:   MPI_Comm_size(comm, &size);
258:   MPI_Comm_rank(comm, &rank);
259:   PetscMalloc(2*size * sizeof(int), &lens);
260:   disp = lens + size;
261:   MPI_Allgather(&napp, 1, MPI_INT, lens, 1, MPI_INT, comm);
262:   N    =  0;
263:   for(i = 0; i < size; i++) {
264:     disp[i] = N;
265:     N += lens[i];
266:   }
267:   aobasic->N = N;

269:   /*
270:      If mypetsc is 0 then use "natural" numbering 
271:   */
272:   if (!mypetsc) {
273:     start = disp[rank];
274:     ierr  = PetscMalloc((napp+1) * sizeof(int), &petsc);
275:     for (i=0; i<napp; i++) {
276:       petsc[i] = start + i;
277:     }
278:   } else {
279:     petsc = mypetsc;
280:   }

282:   /* get all indices on all processors */
283:   ierr   = PetscMalloc(2*N * sizeof(int), &allpetsc);
284:   allapp = allpetsc + N;
285:   ierr   = MPI_Allgatherv(petsc, napp, MPI_INT, allpetsc, lens, disp, MPI_INT, comm);
286:   ierr   = MPI_Allgatherv(myapp, napp, MPI_INT, allapp, lens, disp, MPI_INT, comm);
287:   ierr   = PetscFree(lens);

289:   /* generate a list of application and PETSc node numbers */
290:   PetscMalloc(2*N * sizeof(int), &aobasic->app);
291:   PetscLogObjectMemory(ao,2*N*sizeof(int));
292:   aobasic->petsc = aobasic->app + N;
293:   PetscMemzero(aobasic->app, 2*N*sizeof(int));
294:   for(i = 0; i < N; i++) {
295:     ip = allpetsc[i];
296:     ia = allapp[i];
297:     /* check there are no duplicates */
298:     if (aobasic->app[ip]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Duplicate in PETSc ordering");
299:     aobasic->app[ip] = ia + 1;
300:     if (aobasic->petsc[ia]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Duplicate in Application ordering");
301:     aobasic->petsc[ia] = ip + 1;
302:   }
303:   if (!mypetsc) {
304:     PetscFree(petsc);
305:   }
306:   PetscFree(allpetsc);
307:   /* shift indices down by one */
308:   for(i = 0; i < N; i++) {
309:     aobasic->app[i]--;
310:     aobasic->petsc[i]--;
311:   }

313:   PetscOptionsHasName(PETSC_NULL, "-ao_view", &opt);
314:   if (opt) {
315:     AOView(ao, PETSC_VIEWER_STDOUT_SELF);
316:   }

318:   *aoout = ao;
319:   return(0);
320: }

322: /*@C
323:    AOCreateBasicIS - Creates a basic application ordering using two index sets.

325:    Collective on IS

327:    Input Parameters:
328: +  isapp - index set that defines an ordering
329: -  ispetsc - index set that defines another ordering (may be PETSC_NULL to use the
330:              natural ordering)

332:    Output Parameter:
333: .  aoout - the new application ordering

335:    Options Database Key:
336: -   -ao_view - call AOView() at the conclusion of AOCreateBasicIS()

338:    Level: beginner

340: .keywords: AO, create

342: .seealso: AOCreateBasic(),  AODestroy()
343: @*/
344: int AOCreateBasicIS(IS isapp,IS ispetsc,AO *aoout)
345: {
346:   int       *mypetsc = 0,*myapp,ierr,napp,npetsc;
347:   MPI_Comm  comm;

350:   PetscObjectGetComm((PetscObject)isapp,&comm);
351:   ISGetLocalSize(isapp,&napp);
352:   if (ispetsc) {
353:     ISGetLocalSize(ispetsc,&npetsc);
354:     if (napp != npetsc) SETERRQ(PETSC_ERR_ARG_SIZ,"Local IS lengths must match");
355:     ISGetIndices(ispetsc,&mypetsc);
356:   }
357:   ISGetIndices(isapp,&myapp);

359:   AOCreateBasic(comm,napp,myapp,mypetsc,aoout);

361:   ISRestoreIndices(isapp,&myapp);
362:   if (ispetsc) {
363:     ISRestoreIndices(ispetsc,&mypetsc);
364:   }
365:   return(0);
366: }