xref: /petsc/src/vec/is/ao/impls/basic/aobasic.c (revision d06005cbea37256e14b0a9210dc34c4ed1410bfe)
1 
2 /*
3     The most basic AO application ordering routines. These store the
4   entire orderings on each processor.
5 */
6 
7 #include <../src/vec/is/ao/aoimpl.h>          /*I  "petscao.h"   I*/
8 
9 typedef struct {
10   PetscInt *app;     /* app[i] is the partner for the ith PETSc slot */
11   PetscInt *petsc;   /* petsc[j] is the partner for the jth app slot */
12 } AO_Basic;
13 
14 /*
15        All processors have the same data so processor 1 prints it
16 */
17 PetscErrorCode AOView_Basic(AO ao,PetscViewer viewer)
18 {
19   PetscErrorCode ierr;
20   PetscMPIInt    rank;
21   PetscInt       i;
22   AO_Basic       *aobasic = (AO_Basic*)ao->data;
23   PetscBool      iascii;
24 
25   PetscFunctionBegin;
26   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)ao),&rank);CHKERRMPI(ierr);
27   if (!rank) {
28     ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
29     if (iascii) {
30       ierr = PetscViewerASCIIPrintf(viewer,"Number of elements in ordering %D\n",ao->N);CHKERRQ(ierr);
31       ierr = PetscViewerASCIIPrintf(viewer,  "PETSc->App  App->PETSc\n");CHKERRQ(ierr);
32       for (i=0; i<ao->N; i++) {
33         ierr = PetscViewerASCIIPrintf(viewer,"%3D  %3D    %3D  %3D\n",i,aobasic->app[i],i,aobasic->petsc[i]);CHKERRQ(ierr);
34       }
35     }
36   }
37   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
38   PetscFunctionReturn(0);
39 }
40 
41 PetscErrorCode AODestroy_Basic(AO ao)
42 {
43   AO_Basic       *aobasic = (AO_Basic*)ao->data;
44   PetscErrorCode ierr;
45 
46   PetscFunctionBegin;
47   ierr = PetscFree2(aobasic->app,aobasic->petsc);CHKERRQ(ierr);
48   ierr = PetscFree(aobasic);CHKERRQ(ierr);
49   PetscFunctionReturn(0);
50 }
51 
52 PetscErrorCode AOBasicGetIndices_Private(AO ao,PetscInt **app,PetscInt **petsc)
53 {
54   AO_Basic *basic = (AO_Basic*)ao->data;
55 
56   PetscFunctionBegin;
57   if (app)   *app   = basic->app;
58   if (petsc) *petsc = basic->petsc;
59   PetscFunctionReturn(0);
60 }
61 
62 PetscErrorCode AOPetscToApplication_Basic(AO ao,PetscInt n,PetscInt *ia)
63 {
64   PetscInt i,N=ao->N;
65   AO_Basic *aobasic = (AO_Basic*)ao->data;
66 
67   PetscFunctionBegin;
68   for (i=0; i<n; i++) {
69     if (ia[i] >= 0 && ia[i] < N) {
70       ia[i] = aobasic->app[ia[i]];
71     } else {
72       ia[i] = -1;
73     }
74   }
75   PetscFunctionReturn(0);
76 }
77 
78 PetscErrorCode AOApplicationToPetsc_Basic(AO ao,PetscInt n,PetscInt *ia)
79 {
80   PetscInt i,N=ao->N;
81   AO_Basic *aobasic = (AO_Basic*)ao->data;
82 
83   PetscFunctionBegin;
84   for (i=0; i<n; i++) {
85     if (ia[i] >= 0 && ia[i] < N) {
86       ia[i] = aobasic->petsc[ia[i]];
87     } else {
88       ia[i] = -1;
89     }
90   }
91   PetscFunctionReturn(0);
92 }
93 
94 PetscErrorCode AOPetscToApplicationPermuteInt_Basic(AO ao, PetscInt block, PetscInt *array)
95 {
96   AO_Basic       *aobasic = (AO_Basic*) ao->data;
97   PetscInt       *temp;
98   PetscInt       i, j;
99   PetscErrorCode ierr;
100 
101   PetscFunctionBegin;
102   ierr = PetscMalloc1(ao->N*block, &temp);CHKERRQ(ierr);
103   for (i = 0; i < ao->N; i++) {
104     for (j = 0; j < block; j++) temp[i*block+j] = array[aobasic->petsc[i]*block+j];
105   }
106   ierr = PetscArraycpy(array, temp, ao->N*block);CHKERRQ(ierr);
107   ierr = PetscFree(temp);CHKERRQ(ierr);
108   PetscFunctionReturn(0);
109 }
110 
111 PetscErrorCode AOApplicationToPetscPermuteInt_Basic(AO ao, PetscInt block, PetscInt *array)
112 {
113   AO_Basic       *aobasic = (AO_Basic*) ao->data;
114   PetscInt       *temp;
115   PetscInt       i, j;
116   PetscErrorCode ierr;
117 
118   PetscFunctionBegin;
119   ierr = PetscMalloc1(ao->N*block, &temp);CHKERRQ(ierr);
120   for (i = 0; i < ao->N; i++) {
121     for (j = 0; j < block; j++) temp[i*block+j] = array[aobasic->app[i]*block+j];
122   }
123   ierr = PetscArraycpy(array, temp, ao->N*block);CHKERRQ(ierr);
124   ierr = PetscFree(temp);CHKERRQ(ierr);
125   PetscFunctionReturn(0);
126 }
127 
128 PetscErrorCode AOPetscToApplicationPermuteReal_Basic(AO ao, PetscInt block, PetscReal *array)
129 {
130   AO_Basic       *aobasic = (AO_Basic*) ao->data;
131   PetscReal      *temp;
132   PetscInt       i, j;
133   PetscErrorCode ierr;
134 
135   PetscFunctionBegin;
136   ierr = PetscMalloc1(ao->N*block, &temp);CHKERRQ(ierr);
137   for (i = 0; i < ao->N; i++) {
138     for (j = 0; j < block; j++) temp[i*block+j] = array[aobasic->petsc[i]*block+j];
139   }
140   ierr = PetscArraycpy(array, temp, ao->N*block);CHKERRQ(ierr);
141   ierr = PetscFree(temp);CHKERRQ(ierr);
142   PetscFunctionReturn(0);
143 }
144 
145 PetscErrorCode AOApplicationToPetscPermuteReal_Basic(AO ao, PetscInt block, PetscReal *array)
146 {
147   AO_Basic       *aobasic = (AO_Basic*) ao->data;
148   PetscReal      *temp;
149   PetscInt       i, j;
150   PetscErrorCode ierr;
151 
152   PetscFunctionBegin;
153   ierr = PetscMalloc1(ao->N*block, &temp);CHKERRQ(ierr);
154   for (i = 0; i < ao->N; i++) {
155     for (j = 0; j < block; j++) temp[i*block+j] = array[aobasic->app[i]*block+j];
156   }
157   ierr = PetscArraycpy(array, temp, ao->N*block);CHKERRQ(ierr);
158   ierr = PetscFree(temp);CHKERRQ(ierr);
159   PetscFunctionReturn(0);
160 }
161 
162 static struct _AOOps AOOps_Basic = {
163   AOView_Basic,
164   AODestroy_Basic,
165   AOPetscToApplication_Basic,
166   AOApplicationToPetsc_Basic,
167   AOPetscToApplicationPermuteInt_Basic,
168   AOApplicationToPetscPermuteInt_Basic,
169   AOPetscToApplicationPermuteReal_Basic,
170   AOApplicationToPetscPermuteReal_Basic
171 };
172 
173 PETSC_EXTERN PetscErrorCode AOCreate_Basic(AO ao)
174 {
175   AO_Basic       *aobasic;
176   PetscMPIInt    size,rank,count,*lens,*disp;
177   PetscInt       napp,*allpetsc,*allapp,ip,ia,N,i,*petsc=NULL,start;
178   PetscErrorCode ierr;
179   IS             isapp=ao->isapp,ispetsc=ao->ispetsc;
180   MPI_Comm       comm;
181   const PetscInt *myapp,*mypetsc=NULL;
182 
183   PetscFunctionBegin;
184   /* create special struct aobasic */
185   ierr     = PetscNewLog(ao,&aobasic);CHKERRQ(ierr);
186   ao->data = (void*) aobasic;
187   ierr     = PetscMemcpy(ao->ops,&AOOps_Basic,sizeof(struct _AOOps));CHKERRQ(ierr);
188   ierr     = PetscObjectChangeTypeName((PetscObject)ao,AOBASIC);CHKERRQ(ierr);
189 
190   ierr = ISGetLocalSize(isapp,&napp);CHKERRQ(ierr);
191   ierr = ISGetIndices(isapp,&myapp);CHKERRQ(ierr);
192 
193   ierr = PetscMPIIntCast(napp,&count);CHKERRQ(ierr);
194 
195   /* transmit all lengths to all processors */
196   ierr = PetscObjectGetComm((PetscObject)isapp,&comm);CHKERRQ(ierr);
197   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
198   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
199   ierr = PetscMalloc2(size, &lens,size,&disp);CHKERRQ(ierr);
200   ierr = MPI_Allgather(&count, 1, MPI_INT, lens, 1, MPI_INT, comm);CHKERRMPI(ierr);
201   N    =  0;
202   for (i = 0; i < size; i++) {
203     ierr = PetscMPIIntCast(N,disp+i);CHKERRQ(ierr); /* = sum(lens[j]), j< i */
204     N   += lens[i];
205   }
206   ao->N = N;
207   ao->n = N;
208 
209   /* If mypetsc is 0 then use "natural" numbering */
210   if (napp) {
211     if (!ispetsc) {
212       start = disp[rank];
213       ierr  = PetscMalloc1(napp+1, &petsc);CHKERRQ(ierr);
214       for (i=0; i<napp; i++) petsc[i] = start + i;
215     } else {
216       ierr  = ISGetIndices(ispetsc,&mypetsc);CHKERRQ(ierr);
217       petsc = (PetscInt*)mypetsc;
218     }
219   }
220 
221   /* get all indices on all processors */
222   ierr = PetscMalloc2(N,&allpetsc,N,&allapp);CHKERRQ(ierr);
223   ierr = MPI_Allgatherv(petsc, count, MPIU_INT, allpetsc, lens, disp, MPIU_INT, comm);CHKERRMPI(ierr);
224   ierr = MPI_Allgatherv((void*)myapp, count, MPIU_INT, allapp, lens, disp, MPIU_INT, comm);CHKERRMPI(ierr);
225   ierr = PetscFree2(lens,disp);CHKERRQ(ierr);
226 
227   if (PetscDefined(USE_DEBUG)) {
228     PetscInt *sorted;
229     ierr = PetscMalloc1(N,&sorted);CHKERRQ(ierr);
230 
231     ierr = PetscArraycpy(sorted,allpetsc,N);CHKERRQ(ierr);
232     ierr = PetscSortInt(N,sorted);CHKERRQ(ierr);
233     for (i=0; i<N; i++) {
234       if (sorted[i] != i) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PETSc ordering requires a permutation of numbers 0 to N-1\n it is missing %D has %D",i,sorted[i]);
235     }
236 
237     ierr = PetscArraycpy(sorted,allapp,N);CHKERRQ(ierr);
238     ierr = PetscSortInt(N,sorted);CHKERRQ(ierr);
239     for (i=0; i<N; i++) {
240       if (sorted[i] != i) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Application ordering requires a permutation of numbers 0 to N-1\n it is missing %D has %D",i,sorted[i]);
241     }
242 
243     ierr = PetscFree(sorted);CHKERRQ(ierr);
244   }
245 
246   /* generate a list of application and PETSc node numbers */
247   ierr = PetscCalloc2(N, &aobasic->app,N,&aobasic->petsc);CHKERRQ(ierr);
248   ierr = PetscLogObjectMemory((PetscObject)ao,2*N*sizeof(PetscInt));CHKERRQ(ierr);
249   for (i = 0; i < N; i++) {
250     ip = allpetsc[i];
251     ia = allapp[i];
252     /* check there are no duplicates */
253     if (aobasic->app[ip]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Duplicate in PETSc ordering at position %d. Already mapped to %d, not %d.", i, aobasic->app[ip]-1, ia);
254     aobasic->app[ip] = ia + 1;
255     if (aobasic->petsc[ia]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Duplicate in Application ordering at position %d. Already mapped to %d, not %d.", i, aobasic->petsc[ia]-1, ip);
256     aobasic->petsc[ia] = ip + 1;
257   }
258   if (napp && !mypetsc) {
259     ierr = PetscFree(petsc);CHKERRQ(ierr);
260   }
261   ierr = PetscFree2(allpetsc,allapp);CHKERRQ(ierr);
262   /* shift indices down by one */
263   for (i = 0; i < N; i++) {
264     aobasic->app[i]--;
265     aobasic->petsc[i]--;
266   }
267 
268   ierr = ISRestoreIndices(isapp,&myapp);CHKERRQ(ierr);
269   if (napp) {
270     if (ispetsc) {
271       ierr = ISRestoreIndices(ispetsc,&mypetsc);CHKERRQ(ierr);
272     } else {
273       ierr = PetscFree(petsc);CHKERRQ(ierr);
274     }
275   }
276   PetscFunctionReturn(0);
277 }
278 
279 /*@C
280    AOCreateBasic - Creates a basic application ordering using two integer arrays.
281 
282    Collective
283 
284    Input Parameters:
285 +  comm - MPI communicator that is to share AO
286 .  napp - size of integer arrays
287 .  myapp - integer array that defines an ordering
288 -  mypetsc - integer array that defines another ordering (may be NULL to
289              indicate the natural ordering, that is 0,1,2,3,...)
290 
291    Output Parameter:
292 .  aoout - the new application ordering
293 
294    Level: beginner
295 
296     Notes:
297     the arrays myapp and mypetsc must contain the all the integers 0 to napp-1 with no duplicates; that is there cannot be any "holes"
298            in the indices. Use AOCreateMapping() or AOCreateMappingIS() if you wish to have "holes" in the indices.
299 
300 .seealso: AOCreateBasicIS(), AODestroy(), AOPetscToApplication(), AOApplicationToPetsc()
301 @*/
302 PetscErrorCode  AOCreateBasic(MPI_Comm comm,PetscInt napp,const PetscInt myapp[],const PetscInt mypetsc[],AO *aoout)
303 {
304   PetscErrorCode ierr;
305   IS             isapp,ispetsc;
306   const PetscInt *app=myapp,*petsc=mypetsc;
307 
308   PetscFunctionBegin;
309   ierr = ISCreateGeneral(comm,napp,app,PETSC_USE_POINTER,&isapp);CHKERRQ(ierr);
310   if (mypetsc) {
311     ierr = ISCreateGeneral(comm,napp,petsc,PETSC_USE_POINTER,&ispetsc);CHKERRQ(ierr);
312   } else {
313     ispetsc = NULL;
314   }
315   ierr = AOCreateBasicIS(isapp,ispetsc,aoout);CHKERRQ(ierr);
316   ierr = ISDestroy(&isapp);CHKERRQ(ierr);
317   if (mypetsc) {
318     ierr = ISDestroy(&ispetsc);CHKERRQ(ierr);
319   }
320   PetscFunctionReturn(0);
321 }
322 
323 /*@C
324    AOCreateBasicIS - Creates a basic application ordering using two index sets.
325 
326    Collective on IS
327 
328    Input Parameters:
329 +  isapp - index set that defines an ordering
330 -  ispetsc - index set that defines another ordering (may be NULL to use the
331              natural ordering)
332 
333    Output Parameter:
334 .  aoout - the new application ordering
335 
336    Level: beginner
337 
338     Notes:
339     the index sets isapp and ispetsc must contain the all the integers 0 to napp-1 (where napp is the length of the index sets) with no duplicates;
340            that is there cannot be any "holes"
341 
342 .seealso: AOCreateBasic(),  AODestroy()
343 @*/
344 PetscErrorCode AOCreateBasicIS(IS isapp,IS ispetsc,AO *aoout)
345 {
346   PetscErrorCode ierr;
347   MPI_Comm       comm;
348   AO             ao;
349 
350   PetscFunctionBegin;
351   ierr   = PetscObjectGetComm((PetscObject)isapp,&comm);CHKERRQ(ierr);
352   ierr   = AOCreate(comm,&ao);CHKERRQ(ierr);
353   ierr   = AOSetIS(ao,isapp,ispetsc);CHKERRQ(ierr);
354   ierr   = AOSetType(ao,AOBASIC);CHKERRQ(ierr);
355   ierr   = AOViewFromOptions(ao,NULL,"-ao_view");CHKERRQ(ierr);
356   *aoout = ao;
357   PetscFunctionReturn(0);
358 }
359 
360