YAC 3.20.0
Yet Another Coupler
Loading...
Searching...
No Matches
collection_selection.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <string.h>
7#include <limits.h>
8
9#include <mpi.h>
10
11#include "utils_core.h"
13#include "yac_mpi_internal.h"
14
16 size_t collection_size; //< Number of elements selected
17 int is_contiguous; //< 1 if indices are exactly 0..collection_size−1,
18 //< 0 otherwise
19 size_t selection_indices[]; //< Explicit indices if non-contiguous
20};
21
23 size_t collection_size, size_t const * selection_indices) {
24
25 // if empty collection selection
26 if (collection_size == 0) return NULL;
27
28 int is_contiguous = 1;
29
30 // if the user provided selection indices
31 if (selection_indices != NULL) {
32
33 // check if the provided selection indices are actually contiguous
34 for (size_t i = 0; (i < collection_size) && is_contiguous; ++i) {
36 }
37 }
38
39 struct yac_collection_selection * collection_selection =
40 xmalloc(
41 sizeof(*collection_selection) +
42 (is_contiguous?0:(collection_size * sizeof(*selection_indices))));
43
44 collection_selection->collection_size = collection_size;
45 collection_selection->is_contiguous = is_contiguous;
46 if (!is_contiguous) {
47 memcpy(
48 collection_selection->selection_indices, selection_indices,
50 }
51
52 return collection_selection;
53}
54
56 const struct yac_collection_selection * collection_selection) {
57
58 if (!collection_selection) return NULL;
59
60 size_t mem_size =
61 sizeof(*collection_selection) +
62 (collection_selection->is_contiguous ? 0 :
63 (collection_selection->collection_size *
64 sizeof(*collection_selection->selection_indices)));
65
66 struct yac_collection_selection * copy = xmalloc(mem_size);
67
68 memcpy(copy, collection_selection, mem_size);
69
70 return copy;
71}
72
74 struct yac_collection_selection * collection_selection) {
75
76 free(collection_selection);
77}
78
80 struct yac_collection_selection const * collection_selection) {
81
82 return (collection_selection == NULL)?1:collection_selection->is_contiguous;
83}
84
86 struct yac_collection_selection const *collection_selection) {
87
88 return (collection_selection == NULL)?0:collection_selection->collection_size;
89}
90
92 struct yac_collection_selection const * collection_selection) {
93
94 if (!collection_selection) return NULL;
95 return
96 collection_selection->is_contiguous ?
97 NULL : collection_selection->selection_indices;
98}
99
100
102 struct yac_collection_selection const * selection) {
103
104 size_t collection_size =
106
107 size_t max_index;
108
109 // if the collection size is empty
110 if (collection_size == 0) {
111
112 // dummy value
113 max_index = SIZE_MAX;
114
115 // if non-empty contiguous indices
116 } else if (yac_collection_selection_is_contiguous(selection)) {
117
118 // contiguous indices: 0 .. n-1
119 return collection_size - 1;
120
121 // if non-empty non-contiguous indices
122 } else {
123
124 size_t const * indices = yac_collection_selection_get_indices(selection);
125
126 YAC_ASSERT(indices != NULL, "internal error");
127
128 max_index = indices[0];
129 for (size_t i = 1; i < collection_size; ++i) {
130 if (indices[i] > max_index) {
131 max_index = indices[i];
132 }
133 }
134 }
135
136 return max_index;
137}
138
140 struct yac_collection_selection const * a,
141 struct yac_collection_selection const * b) {
142
143 // Same pointer or both NULL
144 int ret = (a == b);
145 if (ret) return 0;
146
147 // One is NULL, the other is not
148 ret = (a == NULL) - (b == NULL);
149 if (ret) return ret;
150
153
154 // Different collection sizes
155 ret = (size_a > size_b) - (size_a < size_b);
156 if (ret) return ret;
157
160
161 // Both are contiguous and same size
162 if (contig_a && contig_b) return 0;
163
164 // One is contiguous, the other is not
165 ret = contig_a - contig_b;
166 if (ret) return ret;
167
168 // Both are non-contiguous, compare indices
169 size_t const * indices_a = yac_collection_selection_get_indices(a);
170 size_t const * indices_b = yac_collection_selection_get_indices(b);
171
172 for (size_t i = 0; i < size_a; ++i) {
173 ret = (indices_a[i] > indices_b[i]) - (indices_a[i] < indices_b[i]);
174 if (ret) return ret;
175 }
176
177 return 0; // Equal
178}
179
181 struct yac_collection_selection const * sel, MPI_Comm comm) {
182
183 // set to dummy value if sel == NULL
184 struct yac_collection_selection const empty_sel =
185 {.collection_size = 0, .is_contiguous = 1};
186 if (sel == NULL) sel = &empty_sel;
187
188 int size_t_pack_size, int_pack_size, indices_pack_size = 0;
189
190 // base fields
191 yac_mpi_call(MPI_Pack_size(1, YAC_MPI_SIZE_T, comm, &size_t_pack_size), comm);
192 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
193
194 // if the collection is non-empty and non-contiguous
195 if (!sel->is_contiguous && sel->collection_size > 0) {
196
197 YAC_ASSERT(sel->collection_size <= INT_MAX, "collection too large");
198
200 MPI_Pack_size(
201 (int)sel->collection_size, YAC_MPI_SIZE_T, comm, &indices_pack_size),
202 comm);
203 }
204
205 return (size_t)size_t_pack_size + // collection size
206 (size_t)int_pack_size + // is contiguous
207 (size_t)indices_pack_size; // indices, if applicable
208}
209
211 struct yac_collection_selection const * sel,
212 void * buffer, int buffer_size, int * position, MPI_Comm comm) {
213
214 // set to dummy value if sel == NULL
215 struct yac_collection_selection const empty_sel =
216 {.collection_size = 0, .is_contiguous = 1};
217 if (sel == NULL) sel = &empty_sel;
218
220 MPI_Pack(
222 buffer, buffer_size, position, comm), comm);
223
225 MPI_Pack(
226 &sel->is_contiguous, 1, MPI_INT,
227 buffer, buffer_size, position, comm), comm);
228
229 // if the collection is non-empty and non-contiguous
230 if (!sel->is_contiguous && sel->collection_size > 0) {
231
232 YAC_ASSERT(sel->collection_size <= INT_MAX, "collection too large");
233
235 MPI_Pack(
236 sel->selection_indices, (int)sel->collection_size,
237 YAC_MPI_SIZE_T, buffer, buffer_size, position, comm), comm);
238 }
239}
240
242 void const * buffer, int buffer_size, int * position, MPI_Comm comm) {
243
244 size_t collection_size;
246 MPI_Unpack(buffer, buffer_size, position,
247 &collection_size, 1, YAC_MPI_SIZE_T, comm), comm);
248
249 int is_contiguous;
251 MPI_Unpack(buffer, buffer_size, position,
252 &is_contiguous, 1, MPI_INT, comm), comm);
253
254 struct yac_collection_selection * sel = NULL;
255
256 if (collection_size > 0) {
257
258 sel = xmalloc(
259 sizeof(*sel) +
260 (is_contiguous?0:(collection_size * sizeof(sel->selection_indices[0]))));
261
264
265 if (!is_contiguous && collection_size > 0) {
266
267 YAC_ASSERT(collection_size <= INT_MAX, "collection too large");
268
270 MPI_Unpack(
271 buffer, buffer_size, position, sel->selection_indices,
272 (int)collection_size, YAC_MPI_SIZE_T, comm), comm);
273 }
274 }
275
276 return sel;
277}
#define YAC_ASSERT(exp, msg)
int yac_collection_selection_is_contiguous(struct yac_collection_selection const *collection_selection)
Query whether a selection is contiguous.
size_t yac_collection_selection_get_collection_size(struct yac_collection_selection const *collection_selection)
Get the size of the collection selection.
struct yac_collection_selection * yac_collection_selection_unpack(void const *buffer, int buffer_size, int *position, MPI_Comm comm)
Unpack a collection selection from a contiguous MPI buffer.
size_t yac_collection_selection_get_pack_size(struct yac_collection_selection const *sel, MPI_Comm comm)
Compute the MPI pack size of a collection selection.
size_t const * yac_collection_selection_get_indices(struct yac_collection_selection const *collection_selection)
Get explicit selection indices if non-contiguous.
void yac_collection_selection_delete(struct yac_collection_selection *collection_selection)
Delete a collection selection object.
int yac_collection_selection_compare(struct yac_collection_selection const *a, struct yac_collection_selection const *b)
Compare two collection selections.
struct yac_collection_selection * yac_collection_selection_copy(const struct yac_collection_selection *collection_selection)
Selection of indices from a collection.
void yac_collection_selection_pack(struct yac_collection_selection const *sel, void *buffer, int buffer_size, int *position, MPI_Comm comm)
Pack a collection selection into a contiguous MPI buffer.
struct yac_collection_selection * yac_collection_selection_new(size_t collection_size, size_t const *selection_indices)
Create a new collection selection.
size_t yac_collection_selection_get_max_index(struct yac_collection_selection const *selection)
Get the maximum index of a collection selection.
#define xmalloc(size)
Definition ppm_xfuncs.h:66
int collection_size
double * buffer
#define yac_mpi_call(call, comm)
#define YAC_MPI_SIZE_T