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: */
 22: int AOView_Basic(AO ao,PetscViewer viewer)
 23: {
 24:   int        rank,ierr,i;
 25:   AO_Basic   *aodebug = (AO_Basic*)ao->data;
 26:   PetscTruth isascii;

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

 48: int AODestroy_Basic(AO ao)
 49: {
 50:   AO_Basic *aodebug = (AO_Basic*)ao->data;
 51:   int      ierr;

 54:   PetscFree(aodebug->app);
 55:   PetscFree(ao->data);
 56:   return(0);
 57: }

 61: int AOBasicGetIndices_Private(AO ao,int **app,int **petsc)
 62: {
 63:   AO_Basic *basic = (AO_Basic*)ao->data;

 66:   if (app)   *app   = basic->app;
 67:   if (petsc) *petsc = basic->petsc;
 68:   return(0);
 69: }

 73: int AOPetscToApplication_Basic(AO ao,int n,int *ia)
 74: {
 75:   int      i;
 76:   AO_Basic *aodebug = (AO_Basic*)ao->data;

 79:   for (i=0; i<n; i++) {
 80:     if (ia[i] >= 0) {ia[i] = aodebug->app[ia[i]];}
 81:   }
 82:   return(0);
 83: }

 87: int AOApplicationToPetsc_Basic(AO ao,int n,int *ia)
 88: {
 89:   int      i;
 90:   AO_Basic *aodebug = (AO_Basic*)ao->data;

 93:   for (i=0; i<n; i++) {
 94:     if (ia[i] >= 0) {ia[i] = aodebug->petsc[ia[i]];}
 95:   }
 96:   return(0);
 97: }

101: int AOPetscToApplicationPermuteInt_Basic(AO ao, int block, int *array)
102: {
103:   AO_Basic *aodebug = (AO_Basic *) ao->data;
104:   int      *temp;
105:   int       i, j;
106:   int       ierr;

109:   PetscMalloc(aodebug->N*block * sizeof(int), &temp);
110:   for(i = 0; i < aodebug->N; i++) {
111:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->petsc[i]*block+j];
112:   }
113:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(int));
114:   PetscFree(temp);
115:   return(0);
116: }

120: int AOApplicationToPetscPermuteInt_Basic(AO ao, int block, int *array)
121: {
122:   AO_Basic *aodebug = (AO_Basic *) ao->data;
123:   int      *temp;
124:   int       i, j;
125:   int       ierr;

128:   PetscMalloc(aodebug->N*block * sizeof(int), &temp);
129:   for(i = 0; i < aodebug->N; i++) {
130:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->app[i]*block+j];
131:   }
132:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(int));
133:   PetscFree(temp);
134:   return(0);
135: }

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

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

158: int AOApplicationToPetscPermuteReal_Basic(AO ao, int block, double *array)
159: {
160:   AO_Basic *aodebug = (AO_Basic *) ao->data;
161:   double   *temp;
162:   int       i, j;
163:   int       ierr;

166:   PetscMalloc(aodebug->N*block * sizeof(double), &temp);
167:   for(i = 0; i < aodebug->N; i++) {
168:     for(j = 0; j < block; j++) temp[i*block+j] = array[aodebug->app[i]*block+j];
169:   }
170:   PetscMemcpy(array, temp, aodebug->N*block * sizeof(double));
171:   PetscFree(temp);
172:   return(0);
173: }

175: static struct _AOOps AOops = {AOView_Basic,
176:                               AODestroy_Basic,
177:                               AOPetscToApplication_Basic,
178:                               AOApplicationToPetsc_Basic,
179:                               AOPetscToApplicationPermuteInt_Basic,
180:                               AOApplicationToPetscPermuteInt_Basic,
181:                               AOPetscToApplicationPermuteReal_Basic,
182:                               AOApplicationToPetscPermuteReal_Basic};

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

189:    Collective on MPI_Comm

191:    Input Parameters:
192: +  comm - MPI communicator that is to share AO
193: .  napp - size of integer arrays
194: .  myapp - integer array that defines an ordering
195: -  mypetsc - integer array that defines another ordering (may be PETSC_NULL to 
196:              indicate the natural ordering)

198:    Output Parameter:
199: .  aoout - the new application ordering

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

204:    Level: beginner

206: .keywords: AO, create

208: .seealso: AOCreateBasicIS(), AODestroy()
209: @*/
210: int AOCreateBasic(MPI_Comm comm,int napp,const int myapp[],const int mypetsc[],AO *aoout)
211: {
212:   AO_Basic   *aobasic;
213:   AO         ao;
214:   int        *lens,size,rank,N,i,*petsc,start;
215:   int        *allpetsc,*allapp,*disp,ip,ia;
216:   PetscTruth opt;
217:   int        ierr;

221:   *aoout = 0;
222: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
223:   DMInitializePackage(PETSC_NULL);
224: #endif

226:   PetscHeaderCreate(ao, _p_AO, struct _AOOps, AO_COOKIE, AO_BASIC, "AO", comm, AODestroy, AOView);
227:   PetscLogObjectCreate(ao);
228:   PetscNew(AO_Basic, &aobasic);
229:   PetscLogObjectMemory(ao, sizeof(struct _p_AO) + sizeof(AO_Basic));

231:   PetscMemcpy(ao->ops, &AOops, sizeof(AOops));
232:   ao->data = (void *) aobasic;

234:   /* transmit all lengths to all processors */
235:   MPI_Comm_size(comm, &size);
236:   MPI_Comm_rank(comm, &rank);
237:   PetscMalloc(2*size * sizeof(int), &lens);
238:   disp = lens + size;
239:   MPI_Allgather(&napp, 1, MPI_INT, lens, 1, MPI_INT, comm);
240:   N    =  0;
241:   for(i = 0; i < size; i++) {
242:     disp[i] = N;
243:     N += lens[i];
244:   }
245:   aobasic->N = N;

247:   /*
248:      If mypetsc is 0 then use "natural" numbering 
249:   */
250:   if (!mypetsc) {
251:     start = disp[rank];
252:     PetscMalloc((napp+1) * sizeof(int), &petsc);
253:     for (i=0; i<napp; i++) {
254:       petsc[i] = start + i;
255:     }
256:   } else {
257:     petsc = (int *)mypetsc;
258:   }

260:   /* get all indices on all processors */
261:   PetscMalloc(2*N * sizeof(int), &allpetsc);
262:   allapp = allpetsc + N;
263:   MPI_Allgatherv(petsc, napp, MPI_INT, allpetsc, lens, disp, MPI_INT, comm);
264:   MPI_Allgatherv((void*)myapp, napp, MPI_INT, allapp, lens, disp, MPI_INT, comm);
265:   PetscFree(lens);

267:   /* generate a list of application and PETSc node numbers */
268:   PetscMalloc(2*N * sizeof(int), &aobasic->app);
269:   PetscLogObjectMemory(ao,2*N*sizeof(int));
270:   aobasic->petsc = aobasic->app + N;
271:   PetscMemzero(aobasic->app, 2*N*sizeof(int));
272:   for(i = 0; i < N; i++) {
273:     ip = allpetsc[i];
274:     ia = allapp[i];
275:     /* check there are no duplicates */
276:     if (aobasic->app[ip]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Duplicate in PETSc ordering");
277:     aobasic->app[ip] = ia + 1;
278:     if (aobasic->petsc[ia]) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Duplicate in Application ordering");
279:     aobasic->petsc[ia] = ip + 1;
280:   }
281:   if (!mypetsc) {
282:     PetscFree(petsc);
283:   }
284:   PetscFree(allpetsc);
285:   /* shift indices down by one */
286:   for(i = 0; i < N; i++) {
287:     aobasic->app[i]--;
288:     aobasic->petsc[i]--;
289:   }

291:   PetscOptionsHasName(PETSC_NULL, "-ao_view", &opt);
292:   if (opt) {
293:     AOView(ao, PETSC_VIEWER_STDOUT_SELF);
294:   }

296:   *aoout = ao;
297:   return(0);
298: }

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

305:    Collective on IS

307:    Input Parameters:
308: +  isapp - index set that defines an ordering
309: -  ispetsc - index set that defines another ordering (may be PETSC_NULL to use the
310:              natural ordering)

312:    Output Parameter:
313: .  aoout - the new application ordering

315:    Options Database Key:
316: -   -ao_view - call AOView() at the conclusion of AOCreateBasicIS()

318:    Level: beginner

320: .keywords: AO, create

322: .seealso: AOCreateBasic(),  AODestroy()
323: @*/
324: int AOCreateBasicIS(IS isapp,IS ispetsc,AO *aoout)
325: {
326:   int       *mypetsc = 0,*myapp,ierr,napp,npetsc;
327:   MPI_Comm  comm;

330:   PetscObjectGetComm((PetscObject)isapp,&comm);
331:   ISGetLocalSize(isapp,&napp);
332:   if (ispetsc) {
333:     ISGetLocalSize(ispetsc,&npetsc);
334:     if (napp != npetsc) SETERRQ(PETSC_ERR_ARG_SIZ,"Local IS lengths must match");
335:     ISGetIndices(ispetsc,&mypetsc);
336:   }
337:   ISGetIndices(isapp,&myapp);

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

341:   ISRestoreIndices(isapp,&myapp);
342:   if (ispetsc) {
343:     ISRestoreIndices(ispetsc,&mypetsc);
344:   }
345:   return(0);
346: }