Actual source code: aomapping.c
2: /*
3: These AO application ordering routines do not require that the input
4: be a permutation, but merely a 1-1 mapping. This implementation still
5: keeps the entire ordering on each processor.
6: */
8: #include <../src/vec/is/ao/aoimpl.h>
10: typedef struct {
11: PetscInt N;
12: PetscInt *app; /* app[i] is the partner for petsc[appPerm[i]] */
13: PetscInt *appPerm;
14: PetscInt *petsc; /* petsc[j] is the partner for app[petscPerm[j]] */
15: PetscInt *petscPerm;
16: } AO_Mapping;
18: PetscErrorCode AODestroy_Mapping(AO ao)
19: {
20: AO_Mapping *aomap = (AO_Mapping *)ao->data;
22: PetscFree4(aomap->app, aomap->appPerm, aomap->petsc, aomap->petscPerm);
23: PetscFree(aomap);
24: return 0;
25: }
27: PetscErrorCode AOView_Mapping(AO ao, PetscViewer viewer)
28: {
29: AO_Mapping *aomap = (AO_Mapping *)ao->data;
30: PetscMPIInt rank;
31: PetscInt i;
32: PetscBool iascii;
34: MPI_Comm_rank(PetscObjectComm((PetscObject)ao), &rank);
35: if (rank) return 0;
36: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
37: if (iascii) {
38: PetscViewerASCIIPrintf(viewer, "Number of elements in ordering %" PetscInt_FMT "\n", aomap->N);
39: PetscViewerASCIIPrintf(viewer, " App. PETSc\n");
40: for (i = 0; i < aomap->N; i++) PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", i, aomap->app[i], aomap->petsc[aomap->appPerm[i]]);
41: }
42: return 0;
43: }
45: PetscErrorCode AOPetscToApplication_Mapping(AO ao, PetscInt n, PetscInt *ia)
46: {
47: AO_Mapping *aomap = (AO_Mapping *)ao->data;
48: PetscInt *app = aomap->app;
49: PetscInt *petsc = aomap->petsc;
50: PetscInt *perm = aomap->petscPerm;
51: PetscInt N = aomap->N;
52: PetscInt low, high, mid = 0;
53: PetscInt idex;
54: PetscInt i;
56: /* It would be possible to use a single bisection search, which
57: recursively divided the indices to be converted, and searched
58: partitions which contained an index. This would result in
59: better running times if indices are clustered.
60: */
61: for (i = 0; i < n; i++) {
62: idex = ia[i];
63: if (idex < 0) continue;
64: /* Use bisection since the array is sorted */
65: low = 0;
66: high = N - 1;
67: while (low <= high) {
68: mid = (low + high) / 2;
69: if (idex == petsc[mid]) break;
70: else if (idex < petsc[mid]) high = mid - 1;
71: else low = mid + 1;
72: }
73: if (low > high) ia[i] = -1;
74: else ia[i] = app[perm[mid]];
75: }
76: return 0;
77: }
79: PetscErrorCode AOApplicationToPetsc_Mapping(AO ao, PetscInt n, PetscInt *ia)
80: {
81: AO_Mapping *aomap = (AO_Mapping *)ao->data;
82: PetscInt *app = aomap->app;
83: PetscInt *petsc = aomap->petsc;
84: PetscInt *perm = aomap->appPerm;
85: PetscInt N = aomap->N;
86: PetscInt low, high, mid = 0;
87: PetscInt idex;
88: PetscInt i;
90: /* It would be possible to use a single bisection search, which
91: recursively divided the indices to be converted, and searched
92: partitions which contained an index. This would result in
93: better running times if indices are clustered.
94: */
95: for (i = 0; i < n; i++) {
96: idex = ia[i];
97: if (idex < 0) continue;
98: /* Use bisection since the array is sorted */
99: low = 0;
100: high = N - 1;
101: while (low <= high) {
102: mid = (low + high) / 2;
103: if (idex == app[mid]) break;
104: else if (idex < app[mid]) high = mid - 1;
105: else low = mid + 1;
106: }
107: if (low > high) ia[i] = -1;
108: else ia[i] = petsc[perm[mid]];
109: }
110: return 0;
111: }
113: static struct _AOOps AOps = {
114: PetscDesignatedInitializer(view, AOView_Mapping),
115: PetscDesignatedInitializer(destroy, AODestroy_Mapping),
116: PetscDesignatedInitializer(petsctoapplication, AOPetscToApplication_Mapping),
117: PetscDesignatedInitializer(applicationtopetsc, AOApplicationToPetsc_Mapping),
118: };
120: /*@C
121: AOMappingHasApplicationIndex - Searches for the supplied application index.
123: Input Parameters:
124: + ao - The AOMapping
125: - index - The application index
127: Output Parameter:
128: . hasIndex - Flag is PETSC_TRUE if the index exists
130: Level: intermediate
132: .seealso: `AOMappingHasPetscIndex()`, `AOCreateMapping()`
133: @*/
134: PetscErrorCode AOMappingHasApplicationIndex(AO ao, PetscInt idex, PetscBool *hasIndex)
135: {
136: AO_Mapping *aomap;
137: PetscInt *app;
138: PetscInt low, high, mid;
142: aomap = (AO_Mapping *)ao->data;
143: app = aomap->app;
144: /* Use bisection since the array is sorted */
145: low = 0;
146: high = aomap->N - 1;
147: while (low <= high) {
148: mid = (low + high) / 2;
149: if (idex == app[mid]) break;
150: else if (idex < app[mid]) high = mid - 1;
151: else low = mid + 1;
152: }
153: if (low > high) *hasIndex = PETSC_FALSE;
154: else *hasIndex = PETSC_TRUE;
155: return 0;
156: }
158: /*@
159: AOMappingHasPetscIndex - Searches for the supplied petsc index.
161: Input Parameters:
162: + ao - The AOMapping
163: - index - The petsc index
165: Output Parameter:
166: . hasIndex - Flag is PETSC_TRUE if the index exists
168: Level: intermediate
170: .seealso: `AOMappingHasApplicationIndex()`, `AOCreateMapping()`
171: @*/
172: PetscErrorCode AOMappingHasPetscIndex(AO ao, PetscInt idex, PetscBool *hasIndex)
173: {
174: AO_Mapping *aomap;
175: PetscInt *petsc;
176: PetscInt low, high, mid;
180: aomap = (AO_Mapping *)ao->data;
181: petsc = aomap->petsc;
182: /* Use bisection since the array is sorted */
183: low = 0;
184: high = aomap->N - 1;
185: while (low <= high) {
186: mid = (low + high) / 2;
187: if (idex == petsc[mid]) break;
188: else if (idex < petsc[mid]) high = mid - 1;
189: else low = mid + 1;
190: }
191: if (low > high) *hasIndex = PETSC_FALSE;
192: else *hasIndex = PETSC_TRUE;
193: return 0;
194: }
196: /*@C
197: AOCreateMapping - Creates a basic application mapping using two integer arrays.
199: Input Parameters:
200: + comm - MPI communicator that is to share AO
201: . napp - size of integer arrays
202: . myapp - integer array that defines an ordering
203: - mypetsc - integer array that defines another ordering (may be NULL to indicate the identity ordering)
205: Output Parameter:
206: . aoout - the new application mapping
208: Options Database Key:
209: . -ao_view - call AOView() at the conclusion of AOCreateMapping()
211: Level: beginner
213: Notes:
214: the arrays myapp and mypetsc need NOT contain the all the integers 0 to napp-1, that is there CAN be "holes" in the indices.
215: Use AOCreateBasic() or AOCreateBasicIS() if they do not have holes for better performance.
217: .seealso: `AOCreateBasic()`, `AOCreateBasic()`, `AOCreateMappingIS()`, `AODestroy()`
218: @*/
219: PetscErrorCode AOCreateMapping(MPI_Comm comm, PetscInt napp, const PetscInt myapp[], const PetscInt mypetsc[], AO *aoout)
220: {
221: AO ao;
222: AO_Mapping *aomap;
223: PetscInt *allpetsc, *allapp;
224: PetscInt *petscPerm, *appPerm;
225: PetscInt *petsc;
226: PetscMPIInt size, rank, *lens, *disp, nnapp;
227: PetscInt N, start;
228: PetscInt i;
231: *aoout = NULL;
232: AOInitializePackage();
234: PetscHeaderCreate(ao, AO_CLASSID, "AO", "Application Ordering", "AO", comm, AODestroy, AOView);
235: PetscNew(&aomap);
236: PetscMemcpy(ao->ops, &AOps, sizeof(AOps));
237: ao->data = (void *)aomap;
239: /* transmit all lengths to all processors */
240: MPI_Comm_size(comm, &size);
241: MPI_Comm_rank(comm, &rank);
242: PetscMalloc2(size, &lens, size, &disp);
243: nnapp = napp;
244: MPI_Allgather(&nnapp, 1, MPI_INT, lens, 1, MPI_INT, comm);
245: N = 0;
246: for (i = 0; i < size; i++) {
247: disp[i] = N;
248: N += lens[i];
249: }
250: aomap->N = N;
251: ao->N = N;
252: ao->n = N;
254: /* If mypetsc is 0 then use "natural" numbering */
255: if (!mypetsc) {
256: start = disp[rank];
257: PetscMalloc1(napp + 1, &petsc);
258: for (i = 0; i < napp; i++) petsc[i] = start + i;
259: } else {
260: petsc = (PetscInt *)mypetsc;
261: }
263: /* get all indices on all processors */
264: PetscMalloc4(N, &allapp, N, &appPerm, N, &allpetsc, N, &petscPerm);
265: MPI_Allgatherv((void *)myapp, napp, MPIU_INT, allapp, lens, disp, MPIU_INT, comm);
266: MPI_Allgatherv((void *)petsc, napp, MPIU_INT, allpetsc, lens, disp, MPIU_INT, comm);
267: PetscFree2(lens, disp);
269: /* generate a list of application and PETSc node numbers */
270: PetscMalloc4(N, &aomap->app, N, &aomap->appPerm, N, &aomap->petsc, N, &aomap->petscPerm);
271: for (i = 0; i < N; i++) {
272: appPerm[i] = i;
273: petscPerm[i] = i;
274: }
275: PetscSortIntWithPermutation(N, allpetsc, petscPerm);
276: PetscSortIntWithPermutation(N, allapp, appPerm);
277: /* Form sorted arrays of indices */
278: for (i = 0; i < N; i++) {
279: aomap->app[i] = allapp[appPerm[i]];
280: aomap->petsc[i] = allpetsc[petscPerm[i]];
281: }
282: /* Invert petscPerm[] into aomap->petscPerm[] */
283: for (i = 0; i < N; i++) aomap->petscPerm[petscPerm[i]] = i;
285: /* Form map between aomap->app[] and aomap->petsc[] */
286: for (i = 0; i < N; i++) aomap->appPerm[i] = aomap->petscPerm[appPerm[i]];
288: /* Invert appPerm[] into allapp[] */
289: for (i = 0; i < N; i++) allapp[appPerm[i]] = i;
291: /* Form map between aomap->petsc[] and aomap->app[] */
292: for (i = 0; i < N; i++) aomap->petscPerm[i] = allapp[petscPerm[i]];
294: if (PetscDefined(USE_DEBUG)) {
295: /* Check that the permutations are complementary */
297: }
298: /* Cleanup */
299: if (!mypetsc) PetscFree(petsc);
300: PetscFree4(allapp, appPerm, allpetsc, petscPerm);
302: AOViewFromOptions(ao, NULL, "-ao_view");
304: *aoout = ao;
305: return 0;
306: }
308: /*@
309: AOCreateMappingIS - Creates a basic application ordering using two index sets.
311: Input Parameters:
312: + comm - MPI communicator that is to share AO
313: . isapp - index set that defines an ordering
314: - ispetsc - index set that defines another ordering, maybe NULL for identity IS
316: Output Parameter:
317: . aoout - the new application ordering
319: Options Database Key:
320: . -ao_view - call AOView() at the conclusion of AOCreateMappingIS()
322: Level: beginner
324: Notes:
325: the index sets isapp and ispetsc need NOT contain the all the integers 0 to N-1, that is there CAN be "holes" in the indices.
326: Use AOCreateBasic() or AOCreateBasicIS() if they do not have holes for better performance.
328: .seealso: `AOCreateBasic()`, `AOCreateMapping()`, `AODestroy()`
329: @*/
330: PetscErrorCode AOCreateMappingIS(IS isapp, IS ispetsc, AO *aoout)
331: {
332: MPI_Comm comm;
333: const PetscInt *mypetsc, *myapp;
334: PetscInt napp, npetsc;
336: PetscObjectGetComm((PetscObject)isapp, &comm);
337: ISGetLocalSize(isapp, &napp);
338: if (ispetsc) {
339: ISGetLocalSize(ispetsc, &npetsc);
341: ISGetIndices(ispetsc, &mypetsc);
342: } else {
343: mypetsc = NULL;
344: }
345: ISGetIndices(isapp, &myapp);
347: AOCreateMapping(comm, napp, myapp, mypetsc, aoout);
349: ISRestoreIndices(isapp, &myapp);
350: if (ispetsc) ISRestoreIndices(ispetsc, &mypetsc);
351: return 0;
352: }