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: }