YAC 3.13.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interpolation_exchange.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 <stdio.h>
7#include <string.h>
8#include <unistd.h>
9
10#include <mpi.h>
11#include <yaxt.h>
12
13#include "tests.h"
15#include "yac_mpi.h"
16#include "test_common.h"
17
23static void utest_check_exchange(
24 struct yac_interpolation_exchange * exchange,
25 int is_source, int is_target, int optional_put_get);
26
27int main(void) {
28
29 MPI_Init(NULL, NULL);
30
31 xt_initialize(MPI_COMM_WORLD);
32
33 int comm_rank, comm_size;
34 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
35 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
36
37 if (comm_size != 4) {
38 PUT_ERR("ERROR: wrong number of processes");
39 xt_finalize();
40 MPI_Finalize();
41 return TEST_EXIT_CODE;
42 }
43
44 int is_source, is_target;
45 switch (comm_rank) {
46 case(0):
47 is_source = 1;
48 is_target = 1;
49 break;
50 case(1):
51 is_source = 1;
52 is_target = 0;
53 break;
54 case(2):
55 is_source = 0;
56 is_target = 1;
57 break;
58 default:
59 is_source = 0;
60 is_target = 0;
61 break;
62 }
63
64 // generate redist
65 Xt_idxlist src_idxlist =
66 is_source?xt_idxvec_new((Xt_int[]){comm_rank}, 1):xt_idxempty_new();
67 Xt_idxlist tgt_idxlist =
68 is_target?xt_idxvec_new((Xt_int[]){0, 1}, 2):xt_idxempty_new();
69
70 Xt_xmap xmap =
71 xt_xmap_dist_dir_new(src_idxlist, tgt_idxlist, MPI_COMM_WORLD);
72
73 Xt_redist redist = xt_redist_p2p_new(xmap, MPI_DOUBLE);
74
75 // generate exchange
76 size_t num_fields = 1;
77 size_t collection_size = 1;
78 int with_frac_mask = 0;
79 struct yac_interpolation_exchange * exchange =
81 &redist, num_fields, collection_size, with_frac_mask, "simple exchange");
82 struct yac_interpolation_exchange * exchange_copy =
84
85 xt_redist_delete(redist);
86 xt_xmap_delete(xmap);
87 xt_idxlist_delete(tgt_idxlist);
88 xt_idxlist_delete(src_idxlist);
89
90 struct yac_interpolation_exchange * exchanges[] = {exchange, exchange_copy};
91 enum {NUM_EXCH = sizeof(exchanges) / sizeof(exchanges[0])};
92
93 for (int optional_put_get = 0; optional_put_get < 2; ++optional_put_get) {
94
95// #define NVHPC_BUG
96// Starting version 24.3, NVHPC generates invalid code here
97#ifdef NVHPC_BUG
98 utest_check_exchange(exchanges[0], is_source, is_target, optional_put_get);
99 utest_check_exchange(exchanges[1], is_source, is_target, optional_put_get);
100#else
101 for (size_t exch_idx = 0; exch_idx < NUM_EXCH; ++exch_idx)
102 utest_check_exchange(
103 exchanges[exch_idx], is_source, is_target, optional_put_get);
104#endif
105 }
106
107 for (size_t exch_idx = 0; exch_idx < NUM_EXCH; ++exch_idx)
108 yac_interpolation_exchange_delete(exchanges[exch_idx], "main cleanup");
109
110
111 xt_finalize();
112 MPI_Finalize();
113
114 return TEST_EXIT_CODE;
115}
116
117static void utest_check_exchange(
118 struct yac_interpolation_exchange * exchange,
119 int is_source, int is_target, int optional_put_get) {
120
121 int comm_rank;
122 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
123
125 PUT_ERR("ERROR in yac_interpolation_exchange_is_source");
127 PUT_ERR("ERROR in yac_interpolation_exchange_is_target");
128
129 double send_data_[1] = {(double)comm_rank};
130 double const * send_data = {is_source?&(send_data_[0]):NULL};
131 double recv_data_[2] = {-1.0, -1.0};
132 double * recv_data = {is_target?&(recv_data_[0]):NULL};
133 enum YAC_INTERP_EXCH_STATUS status;
134
135 // there should be no pending communication
136 if (yac_interpolation_exchange_put_test(exchange, "utest_check_exchange") !=
138 PUT_ERR("ERROR in yac_interpolation_exchange_execute");
139 if (yac_interpolation_exchange_get_test(exchange, "utest_check_exchange") !=
141 PUT_ERR("ERROR in yac_interpolation_exchange_execute");
142 if (yac_interpolation_exchange_status(exchange, "utest_check_exchange") !=
144 PUT_ERR("ERROR in yac_interpolation_exchange_status");
145
146 // this should not block
147 yac_interpolation_exchange_wait(exchange, "utest_check_exchange");
148
149 // simple exchange
150 recv_data_[0] = -1.0, recv_data_[1] = -1.0;
152 exchange, &send_data, &recv_data, "utest_check_exchange");
153 if (is_target)
154 if ((recv_data_[0] != 0.0) || (recv_data_[1] != 1.0))
155 PUT_ERR("ERROR in yac_interpolation_exchange_execute");
156 if (yac_interpolation_exchange_status(exchange, "utest_check_exchange") !=
158 PUT_ERR("ERROR in yac_interpolation_exchange_status");
159
160 // simple put/get exchange
161 if (!optional_put_get || is_source)
163 exchange, &send_data, "utest_check_exchange");
164 status = yac_interpolation_exchange_status(exchange, "utest_check_exchange");
165 if (is_target) {
166 if (is_source) {
167 if (status != YAC_INTERP_EXCH_WAIT_PUT)
168 PUT_ERR("ERROR in yac_interpolation_exchange_status");
170 exchange, "utest_check_exchange") == YAC_INTERP_EXCH_COMPLETE)
171 PUT_ERR("ERROR in yac_interpolation_exchange_execute");
172 } else {
173 if (status != YAC_INTERP_EXCH_IDLE)
174 PUT_ERR("ERROR in yac_interpolation_exchange_status");
175 }
176 } else {
177 if (is_source) {
178 if ((status != YAC_INTERP_EXCH_ACTIVE) &&
179 (status != YAC_INTERP_EXCH_IDLE))
180 PUT_ERR("ERROR in yac_interpolation_exchange_status");
181 } else {
182 if (status != YAC_INTERP_EXCH_IDLE)
183 PUT_ERR("ERROR in yac_interpolation_exchange_status");
184 }
185 }
186 recv_data_[0] = -1.0, recv_data_[1] = -1.0;
187 if (!optional_put_get || is_target)
189 exchange, &recv_data, "utest_check_exchange");
190 if (is_target && ((recv_data_[0] != 0.0) || (recv_data_[1] != 1.0)))
191 PUT_ERR("ERROR in yac_interpolation_exchange_execute_get");
192 if (is_source) yac_interpolation_exchange_wait(exchange, "utest_check_exchange");
193 if (yac_interpolation_exchange_status(exchange, "utest_check_exchange") !=
195 PUT_ERR("ERROR in yac_interpolation_exchange_status");
196
197 // simple put/get exchange with testing for completion
198 if (!optional_put_get || is_source) {
200 exchange, &send_data, "utest_check_exchange");
201 if (!is_target)
202 // this should return at some point
203 while (
205 exchange, "utest_check_exchange") == YAC_INTERP_EXCH_INCOMPLETE);
206 }
207 recv_data_[0] = -1.0, recv_data_[1] = -1.0;
208 if (!optional_put_get || is_target)
210 exchange, &recv_data, "utest_check_exchange");
211 if (is_target && ((recv_data_[0] != 0.0) || (recv_data_[1] != 1.0)))
212 PUT_ERR("ERROR in yac_interpolation_exchange_execute_get");
213 if (!optional_put_get || is_source)
214 yac_interpolation_exchange_wait(exchange, "utest_check_exchange");
215
216 for (int put_get_order = 0; put_get_order < 2; ++put_get_order) {
217
218 // async get
219 for (int i = 0; i < 2; ++i) {
220 if (put_get_order == i) {
221 if (!optional_put_get || is_source)
223 exchange, &send_data, "utest_check_exchange");
224 }
225 if (put_get_order != i) {
226 recv_data_[0] = -1.0, recv_data_[1] = -1.0;
227 if (!optional_put_get || is_target)
229 exchange, &recv_data, "utest_check_exchange");
230 }
231 }
232 yac_interpolation_exchange_wait(exchange, "utest_check_exchange");
233 if (is_target && ((recv_data_[0] != 0.0) || (recv_data_[1] != 1.0)))
234 PUT_ERR("ERROR in yac_interpolation_exchange_execute_get");
235
236 // async get with testing for completion
237 for (int i = 0; i < 2; ++i) {
238 if (put_get_order == i) {
239 if (!optional_put_get || is_source)
241 exchange, &send_data, "utest_check_exchange");
242 if ((i == 0) && is_source && is_target)
243 if (yac_interpolation_exchange_status(exchange, "utest_check_exchange") !=
245 PUT_ERR("ERROR in yac_interpolation_exchange_status");
246 }
247 if (put_get_order != i) {
248 recv_data_[0] = -1.0, recv_data_[1] = -1.0;
249 if (!optional_put_get || is_target)
251 exchange, &recv_data, "utest_check_exchange");
252 if ((i == 0) && is_source && is_target)
253 if (yac_interpolation_exchange_status(exchange, "utest_check_exchange") !=
255 PUT_ERR("ERROR in yac_interpolation_exchange_status");
256 }
257 }
258 status = yac_interpolation_exchange_status(exchange, "utest_check_exchange");
259 if ((status != YAC_INTERP_EXCH_IDLE) &&
260 (status != YAC_INTERP_EXCH_ACTIVE))
261 PUT_ERR("ERROR in yac_interpolation_exchange_status");
262 // this should return at some point
264 exchange, "utest_check_exchange") ==
267 exchange, "utest_check_exchange") ==
269 if (is_target && ((recv_data_[0] != 0.0) || (recv_data_[1] != 1.0)))
270 PUT_ERR("ERROR in yac_interpolation_exchange_execute_get");
271 }
272
273 // introduce delay to better simulate asynchronous behaviour
274 for (int i = 0; i < 4; ++i) {
275
276 for (int j = 0; j < 2; ++j) {
277 if ((i & 1) == j) {
278 if (!optional_put_get || is_source)
280 exchange, &send_data, "utest_check_exchange");
281 if (is_source) sleep(1);
282 }
283 if ((i & 1) != j) {
284 if (!optional_put_get || is_target)
286 exchange, &recv_data, "utest_check_exchange");
287 }
288 }
289 }
290 yac_interpolation_exchange_wait(exchange, "utest_check_exchange");
291
292 // introduce delay to better simulate asynchronous behaviour
293 for (int i = 0; i < 4; ++i) {
294 if (is_source && is_target && (i & 1)) {
296 exchange, &send_data, &recv_data, "utest_check_exchange");
297 } else {
299 exchange, &send_data, "utest_check_exchange");
300 if (is_source) sleep(1);
302 exchange, &recv_data, "utest_check_exchange");
303 }
304 }
305 yac_interpolation_exchange_wait(exchange, "utest_check_exchange");
306}
unsigned num_fields
int yac_interpolation_exchange_is_target(struct yac_interpolation_exchange *exchange)
Query whether the current process participates as target.
void yac_interpolation_exchange_execute_get_async(struct yac_interpolation_exchange *exchange, double **recv_data, char const *routine_name)
Execute the get phase asynchronously.
enum YAC_INTERP_EXCH_TEST_STATUS yac_interpolation_exchange_put_test(struct yac_interpolation_exchange *exchange, char const *routine_name)
Test whether the put phase has completed.
struct yac_interpolation_exchange * yac_interpolation_exchange_copy(struct yac_interpolation_exchange *exchange)
Create a deep copy of an interpolation exchange.
void yac_interpolation_exchange_delete(struct yac_interpolation_exchange *exchange, char const *routine_name)
Delete an interpolation exchange and release resources.
void yac_interpolation_exchange_execute_get(struct yac_interpolation_exchange *exchange, double **recv_data, char const *routine_name)
Execute the get phase and receive target data synchronously.
void yac_interpolation_exchange_wait(struct yac_interpolation_exchange *exchange, char const *routine_name)
Wait for completion of pending put/get phases.
enum YAC_INTERP_EXCH_TEST_STATUS yac_interpolation_exchange_get_test(struct yac_interpolation_exchange *exchange, char const *routine_name)
Test whether the get phase has completed.
void yac_interpolation_exchange_execute_put(struct yac_interpolation_exchange *exchange, double const **send_data, char const *routine_name)
Execute only the put phase asynchronously.
struct yac_interpolation_exchange * yac_interpolation_exchange_new(Xt_redist *redists, size_t num_fields, size_t collection_size, int with_frac_mask, char const *name)
Create a new interpolation exchange object.
void yac_interpolation_exchange_execute(struct yac_interpolation_exchange *exchange, double const **send_data_, double **recv_data_, char const *routine_name)
Execute the full exchange (put + get) synchronously.
enum YAC_INTERP_EXCH_STATUS yac_interpolation_exchange_status(struct yac_interpolation_exchange *exchange, char const *routine_name)
int yac_interpolation_exchange_is_source(struct yac_interpolation_exchange *exchange)
Query whether the current process participates as source.
Interpolation exchange object for temporary buffers and MPI exchanges.
@ YAC_INTERP_EXCH_INCOMPLETE
Operation still in progress.
@ YAC_INTERP_EXCH_COMPLETE
No ongoing operation.
YAC_INTERP_EXCH_STATUS
Status of an interpolation exchange.
@ YAC_INTERP_EXCH_ACTIVE
Exchange is active.
@ YAC_INTERP_EXCH_WAIT_PUT
Waiting for put phase completion.
@ YAC_INTERP_EXCH_WAIT_GET
Waiting for get phase completion.
@ YAC_INTERP_EXCH_IDLE
No ongoing exchange.
int collection_size
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10