YAC 3.12.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
8#include "utils_core.h"
10#include "yac_mpi_internal.h"
11
13 size_t collection_size; //< Number of elements selected
14 int is_contiguous; //< 1 if indices are exactly 0..collection_size−1,
15 //< 0 otherwise
16 size_t selection_indices[]; //< Explicit indices if non-contiguous
17};
18
20 size_t collection_size, size_t const * selection_indices) {
21
22 // if empty collection selection
23 if (collection_size == 0) return NULL;
24
25 int is_contiguous = 1;
26
27 // if the user provided selection indices
28 if (selection_indices != NULL) {
29
30 // check if the provided selection indices are actually contiguous
31 for (size_t i = 0; (i < collection_size) && is_contiguous; ++i) {
33 }
34 }
35
36 struct yac_collection_selection * collection_selection =
37 xmalloc(
38 sizeof(*collection_selection) +
39 (is_contiguous?0:(collection_size * sizeof(*selection_indices))));
40
41 collection_selection->collection_size = collection_size;
42 collection_selection->is_contiguous = is_contiguous;
43 if (!is_contiguous) {
44 memcpy(
45 collection_selection->selection_indices, selection_indices,
47 }
48
49 return collection_selection;
50}
51
53 const struct yac_collection_selection * collection_selection) {
54
55 if (!collection_selection) return NULL;
56
57 size_t mem_size =
58 sizeof(*collection_selection) +
59 (collection_selection->is_contiguous ? 0 :
60 (collection_selection->collection_size *
61 sizeof(*collection_selection->selection_indices)));
62
63 struct yac_collection_selection * copy = xmalloc(mem_size);
64
65 memcpy(copy, collection_selection, mem_size);
66
67 return copy;
68}
69
71 struct yac_collection_selection * collection_selection) {
72
73 free(collection_selection);
74}
75
77 struct yac_collection_selection const * collection_selection) {
78
79 return (collection_selection == NULL)?1:collection_selection->is_contiguous;
80}
81
83 struct yac_collection_selection const *collection_selection) {
84
85 return (collection_selection == NULL)?0:collection_selection->collection_size;
86}
87
89 struct yac_collection_selection const * collection_selection) {
90
91 if (!collection_selection) return NULL;
92 return
93 collection_selection->is_contiguous ?
94 NULL : collection_selection->selection_indices;
95}
96
97
99 struct yac_collection_selection const * selection) {
100
101 size_t collection_size =
103
104 size_t max_index;
105
106 // if the collection size is empty
107 if (collection_size == 0) {
108
109 // dummy value
110 max_index = SIZE_MAX;
111
112 // if non-empty contiguous indices
113 } else if (yac_collection_selection_is_contiguous(selection)) {
114
115 // contiguous indices: 0 .. n-1
116 return collection_size - 1;
117
118 // if non-empty non-contiguous indices
119 } else {
120
121 size_t const * indices = yac_collection_selection_get_indices(selection);
122
124 indices != NULL, "ERROR(yac_collection_selection_get_max_index): "
125 "internal error");
126
127 max_index = indices[0];
128 for (size_t i = 1; i < collection_size; ++i) {
129 if (indices[i] > max_index) {
130 max_index = indices[i];
131 }
132 }
133 }
134
135 return max_index;
136}
137
139 struct yac_collection_selection const * a,
140 struct yac_collection_selection const * b) {
141
142 // Same pointer or both NULL
143 int ret = (a == b);
144 if (ret) return 0;
145
146 // One is NULL, the other is not
147 ret = (a == NULL) - (b == NULL);
148 if (ret) return ret;
149
152
153 // Different collection sizes
154 ret = (size_a > size_b) - (size_a < size_b);
155 if (ret) return ret;
156
159
160 // Both are contiguous and same size
161 if (contig_a && contig_b) return 0;
162
163 // One is contiguous, the other is not
164 ret = contig_a - contig_b;
165 if (ret) return ret;
166
167 // Both are non-contiguous, compare indices
168 size_t const * indices_a = yac_collection_selection_get_indices(a);
169 size_t const * indices_b = yac_collection_selection_get_indices(b);
170
171 for (size_t i = 0; i < size_a; ++i) {
172 ret = (indices_a[i] > indices_b[i]) - (indices_a[i] < indices_b[i]);
173 if (ret) return ret;
174 }
175
176 return 0; // Equal
177}
178
180 struct yac_collection_selection const * sel, MPI_Comm comm) {
181
182 // set to dummy value if sel == NULL
183 struct yac_collection_selection const empty_sel =
184 {.collection_size = 0, .is_contiguous = 1};
185 if (sel == NULL) sel = &empty_sel;
186
187 int size_t_pack_size, int_pack_size, indices_pack_size = 0;
188
189 // base fields
190 yac_mpi_call(MPI_Pack_size(1, YAC_MPI_SIZE_T, comm, &size_t_pack_size), comm);
191 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
192
193 // if the collection is non-empty and non-contiguous
194 if (!sel->is_contiguous && sel->collection_size > 0) {
195
196 YAC_ASSERT(sel->collection_size <= INT_MAX,
197 "ERROR(yac_collection_selection_get_pack_size): 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,
233 "ERROR(yac_collection_selection_pack): collection too large");
234
236 MPI_Pack(
237 sel->selection_indices, (int)sel->collection_size,
238 YAC_MPI_SIZE_T, buffer, buffer_size, position, comm), comm);
239 }
240}
241
243 void const * buffer, int buffer_size, int * position, MPI_Comm comm) {
244
245 size_t collection_size;
247 MPI_Unpack(buffer, buffer_size, position,
248 &collection_size, 1, YAC_MPI_SIZE_T, comm), comm);
249
250 int is_contiguous;
252 MPI_Unpack(buffer, buffer_size, position,
253 &is_contiguous, 1, MPI_INT, comm), comm);
254
255 struct yac_collection_selection * sel = NULL;
256
257 if (collection_size > 0) {
258
259 sel = xmalloc(
260 sizeof(*sel) +
261 (is_contiguous?0:(collection_size * sizeof(sel->selection_indices[0]))));
262
265
266 if (!is_contiguous && collection_size > 0) {
267
268 YAC_ASSERT(collection_size <= INT_MAX,
269 "ERROR(yac_collection_selection_unpack): collection too large");
270
272 MPI_Unpack(
273 buffer, buffer_size, position, sel->selection_indices,
274 (int)collection_size, YAC_MPI_SIZE_T, comm), comm);
275 }
276 }
277
278 return sel;
279}
#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