YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interpolation_parallel1_c.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 <math.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <string.h>
9
10#include <mpi.h>
11#include <yaxt.h>
12
13#include "tests.h"
14#include "test_common.h"
15#include "dist_grid_utils.h"
18
24#define YAC_RAD (0.01745329251994329576923690768489) // M_PI / 180
25
26#define MAX_COLLECTION_SIZE (10)
27
28char const grid_name_src[] = "src_grid";
29char const grid_name_tgt[] = "tgt_grid";
30
31static void utest_target_main(
32 MPI_Comm target_comm, enum yac_interp_weights_reorder_type reorder_type);
33
34static void utest_source_main(
35 MPI_Comm source_comm, enum yac_interp_weights_reorder_type reorder_type);
36
37int main(int argc, char *argv[]) {
38
39 if (argc != 2) {
40 PUT_ERR("wrong number of arguments\n");
41 return TEST_EXIT_CODE;
42 }
43
44 enum yac_interp_weights_reorder_type reorder_type =
45 (strcmp(argv[1], "src") == 0)?YAC_MAPPING_ON_SRC:YAC_MAPPING_ON_TGT;
46
47 if ((reorder_type != YAC_MAPPING_ON_SRC) && strcmp(argv[1], "tgt")) {
48 PUT_ERR("invalid argument (has to be either \"src\" or \"tgt\")\n");
49 return TEST_EXIT_CODE;
50 }
51
52 MPI_Init(NULL, NULL);
53
54 xt_initialize(MPI_COMM_WORLD);
55
56 int comm_rank, comm_size;
57 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
58 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
59 MPI_Barrier(MPI_COMM_WORLD);
60
61 if (comm_size != 4) {
62 PUT_ERR("ERROR: wrong number of processes");
63 xt_finalize();
64 MPI_Finalize();
65 return TEST_EXIT_CODE;
66 }
67
68 // split processes into source and target
69
70 int tgt_flag = comm_rank < 2;
71
72 MPI_Comm split_comm;
73 MPI_Comm_split(MPI_COMM_WORLD, tgt_flag, 0, &split_comm);
74
75 if (tgt_flag) utest_target_main(split_comm, reorder_type);
76 else utest_source_main(split_comm, reorder_type);
77
78 MPI_Comm_free(&split_comm);
79 xt_finalize();
80 MPI_Finalize();
81
82 return TEST_EXIT_CODE;
83}
84
85/*
86 * The source grid is distributed among 2 processes
87 *
88 * The global source grid has 5x4 cells:
89 *
90 * 24--44--25--45--26--46--27--47--28--48--29
91 * | | | | | |
92 * 34 15 36 16 38 17 40 18 42 19 43
93 * | | | | | |
94 * 18--33--19--35--20--37--21--39--22--41--23
95 * | | | | | |
96 * 23 10 25 11 27 12 29 13 31 14 32
97 * | | | | | |
98 * 12--22--13--24--14--26--15--28--16--30--17
99 * | | | | | |
100 * 12 05 14 06 16 07 18 08 20 09 21
101 * | | | | | |
102 * 06--11--07--13--08--15--09--17--10--19--11
103 * | | | | | |
104 * 01 00 03 01 05 02 07 03 09 04 10
105 * | | | | | |
106 * 00--01--01--02--02--04--03--06--04--08--05
107 */
108static void utest_source_main(
109 MPI_Comm source_comm, enum yac_interp_weights_reorder_type reorder_type) {
110
111 int my_source_rank;
112 MPI_Comm_rank(source_comm, &my_source_rank);
113
114 double coordinates_x[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
115 double coordinates_y[] = {0.0, 1.0, 2.0, 3.0, 4.0};
116 size_t const num_cells[2] = {5,4};
117 size_t local_start[2][2] = {{0,0},{3,0}};
118 size_t local_count[2][2] = {{3,4},{2,4}};
119 int with_halo = 1;
120 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
121 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
122
124 utest_generate_basic_grid_data_reg2d(
126 local_start[my_source_rank], local_count[my_source_rank], with_halo);
127 struct yac_basic_grid * src_grid =
129 struct yac_basic_grid * tgt_grid =
131
132 struct yac_dist_grid_pair * grid_pair =
133 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
134
135 struct yac_interp_field src_fields[] =
136 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
137 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
139 {.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
140
141 struct yac_interp_grid * interp_grid =
144
145 struct interp_method * method_stack[] =
148 NULL};
149
150 struct yac_interp_weights * weights =
151 yac_interp_method_do_search(method_stack, interp_grid);
152
153 yac_interp_method_delete(method_stack);
154
155 struct interp_method * method_stack_nan[] =
158 NULL};
159
160 struct yac_interp_weights * weights_nan =
161 yac_interp_method_do_search(method_stack_nan, interp_grid);
162
163 yac_interp_method_delete(method_stack_nan);
164
165 // -------------------
166 // set up source data
167 // -------------------
168
169 // src_data dimensions [collection_idx]
170 // [pointset_idx]
171 // [local_idx]
172 double *** src_data = xmalloc(MAX_COLLECTION_SIZE * sizeof(*src_data));
173 for (size_t collection_idx = 0; collection_idx < MAX_COLLECTION_SIZE;
174 ++collection_idx) {
175 src_data[collection_idx] = xmalloc(1 * sizeof(**src_data));
176 src_data[collection_idx][0] =
177 xmalloc(grid_data.num_vertices * sizeof(***src_data));
178 for (size_t i = 0; i < grid_data.num_vertices; ++i)
179 src_data[collection_idx][0][i] =
180 (grid_data.core_vertex_mask[i])?
181 ((double)(grid_data.vertex_ids[i]) + (double)(collection_idx * 30)):
182 (-1.0);
183 }
184
186 ++collection_size) {
187
188 //---------------------------
189 // set up field interpolation
190 //---------------------------
191
192 struct yac_interpolation * interpolation =
194 weights, reorder_type, collection_size,
195 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
196 struct yac_interpolation * interpolation_copy =
197 yac_interpolation_copy(interpolation);
198
199 //---------------------
200 // do the interpolation
201 //---------------------
202
203 yac_interpolation_execute_put(interpolation, src_data);
204 yac_interpolation_execute_put(interpolation_copy, src_data);
205
206 yac_interpolation_delete(interpolation_copy);
207 yac_interpolation_delete(interpolation);
208 }
209
211 ++collection_size) {
212
213 //---------------------------
214 // set up field interpolation (NaN fixed fallback)
215 //---------------------------
216
217 struct yac_interpolation * interpolation_nan =
219 weights_nan, reorder_type, collection_size,
220 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
221 struct yac_interpolation * interpolation_nan_copy =
222 yac_interpolation_copy(interpolation_nan);
223
224 //---------------------
225 // do the interpolation
226 //---------------------
227
228 yac_interpolation_execute_put(interpolation_nan, src_data);
229 yac_interpolation_execute_put(interpolation_nan_copy, src_data);
230
231 yac_interpolation_delete(interpolation_nan_copy);
232 yac_interpolation_delete(interpolation_nan);
233 }
234
235 //--------
236 // cleanup
237 //--------
238
239
240 for (size_t collection_idx = 0; collection_idx < MAX_COLLECTION_SIZE;
241 ++collection_idx) {
242 free(src_data[collection_idx][0]);
243 free(src_data[collection_idx]);
244 }
245 free(src_data);
246
247 yac_basic_grid_delete(tgt_grid);
248 yac_basic_grid_delete(src_grid);
249 yac_interp_weights_delete(weights_nan);
251 yac_interp_grid_delete(interp_grid);
252 yac_dist_grid_pair_delete(grid_pair);
253}
254
255/*
256 * The target grid is distributed among 2 processes
257 *
258 * The global target grid has 6x3 cells:
259 *
260 * 21--39--22--40--23--41--24--42--25--43--26--44--27
261 * | | | | | | |
262 * 27 12 29 13 31 14 33 15 35 16 37 17 38
263 * | | | | | | |
264 * 14--26--15--28--16--30--17--32--18--34--19--36--20
265 * | | | | | | |
266 * 14 06 16 07 18 08 20 09 22 10 24 11 25
267 * | | | | | | |
268 * 07--13--08--15--09--17--10--19--11--21--12--23--13
269 * | | | | | | |
270 * 01 00 03 01 05 02 07 03 09 04 11 05 12
271 * | | | | | | |
272 * 00--00--01--02--02--04--03--06--04--08--05--10--06
273 */
274static void utest_target_main(
275 MPI_Comm target_comm, enum yac_interp_weights_reorder_type reorder_type) {
276
277 int my_target_rank;
278 MPI_Comm_rank(target_comm, &my_target_rank);
279
280 double coordinates_x[] = {0.5,1.5,2.5,3.5,4.5,5.5,6.5};
281 double coordinates_y[] = {0.5,1.5,2.5,3.5};
282 size_t const num_cells[2] = {6,3};
283 size_t local_start[2][2] = {{0,0},{3,0}};
284 size_t local_count[2][2] = {{3,3},{3,3}};
285 int with_halo = 0;
286 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
287 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
288
290 utest_generate_basic_grid_data_reg2d(
292 local_start[my_target_rank], local_count[my_target_rank], with_halo);
293 struct yac_basic_grid * tgt_grid =
295 struct yac_basic_grid * src_grid =
297
298 struct yac_dist_grid_pair * grid_pair =
299 yac_dist_grid_pair_new(tgt_grid, src_grid, MPI_COMM_WORLD);
300
301 struct yac_interp_field src_fields[] =
302 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
303 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
305 {.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
306
307 struct yac_interp_grid * interp_grid =
310
311 struct interp_method * method_stack[] =
314 NULL};
315
316 struct yac_interp_weights * weights =
317 yac_interp_method_do_search(method_stack, interp_grid);
318
319 yac_interp_method_delete(method_stack);
320
321 struct interp_method * method_stack_nan[] =
324 NULL};
325
326 struct yac_interp_weights * weights_nan =
327 yac_interp_method_do_search(method_stack_nan, interp_grid);
328
329 yac_interp_method_delete(method_stack_nan);
330
331 //---------------------
332 // do the interpolation
333 //---------------------
334
335 double target_field[MAX_COLLECTION_SIZE][16];
336 double * target_data[MAX_COLLECTION_SIZE];
337 for (unsigned i = 0; i < MAX_COLLECTION_SIZE; ++i)
338 target_data[i] = target_field[i];
339
341 ++collection_size) {
342
343 //---------------------------
344 // set up field interpolation
345 //---------------------------
346
347 struct yac_interpolation * interpolation[2];
348 interpolation[0] =
350 weights, reorder_type, collection_size,
351 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
352 interpolation[1] = yac_interpolation_copy(interpolation[0]);
353
354 for (size_t k = 0; k < 2; ++k) {
355
356 for (unsigned i = 0; i < collection_size; ++i)
357 for (unsigned j = 0; j < 16; ++j)
358 target_field[i][j] = -1;
359
360 yac_interpolation_execute_get(interpolation[k], target_data);
361
362 //----------------------------
363 // check interpolation results
364 //----------------------------
365
366 double ref_target_data[2][16] = {{3.5,4.5,5.5,6.5,
367 9.5,10.5,11.5,12.5,
368 15.5,16.5,17.5,18.5,
369 21.5,22.5,23.5,24.5},
370 {6.5,7.5,1337,1337,
371 12.5,13.5,1337,1337,
372 18.5,19.5,1337,1337,
373 24.5,25.5,1337,1337}};
374
375 for (unsigned i = 0; i < collection_size; ++i) {
376 for (unsigned j = 0; j < 16; ++j) {
377 if ((utest_double_are_equal(ref_target_data[my_target_rank][j], -1.0)) ||
378 (utest_double_are_equal(ref_target_data[my_target_rank][j], 1337.0))) {
379 if (utest_double_are_unequal(target_data[i][j],
380 ref_target_data[my_target_rank][j]))
381 PUT_ERR("error in interpolated data on target side\n");
382 } else {
383 if (utest_double_are_unequal(
384 target_data[i][j],
385 ref_target_data[my_target_rank][j] + (double)(i * 30)))
386 PUT_ERR("error in interpolated data on target side\n");
387 }
388 }
389 }
390 }
391
392 for (int i = 0; i < 2; ++i)
393 yac_interpolation_delete(interpolation[i]);
394 }
395
397 ++collection_size) {
398
399 //---------------------------
400 // set up field interpolation (NaN fixed fallback)
401 //---------------------------
402
403 struct yac_interpolation * interpolation_nan[2];
404 interpolation_nan[0] =
406 weights_nan, reorder_type, collection_size,
407 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
408 interpolation_nan[1] = yac_interpolation_copy(interpolation_nan[0]);
409
410 for (size_t k = 0; k < 2; ++k) {
411
412 for (unsigned i = 0; i < collection_size; ++i)
413 for (unsigned j = 0; j < 16; ++j)
414 target_field[i][j] = -1;
415
416 yac_interpolation_execute_get(interpolation_nan[k], target_data);
417
418 //----------------------------
419 // check interpolation results (NaN fixed fallback)
420 //----------------------------
421
422 // ref_nan_covered[rank][j]: finite reference values for covered points;
423 // -1.0 sentinel means the point is not locally owned (no data expected).
424 // Points that fall through to fixed(NAN) must satisfy isnan().
425 double ref_nan_covered[2][16] = {{3.5,4.5,5.5,6.5,
426 9.5,10.5,11.5,12.5,
427 15.5,16.5,17.5,18.5,
428 21.5,22.5,23.5,24.5},
429 {6.5,7.5,-1.0,-1.0,
430 12.5,13.5,-1.0,-1.0,
431 18.5,19.5,-1.0,-1.0,
432 24.5,25.5,-1.0,-1.0}};
433 // nan_fallback_mask[rank][j]: 1 if this point must be NaN
434 int nan_fallback_mask[2][16] = {{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0},
435 {0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1}};
436
437 for (unsigned i = 0; i < collection_size; ++i) {
438 for (unsigned j = 0; j < 16; ++j) {
439 if (nan_fallback_mask[my_target_rank][j]) {
440 if (!isnan(target_data[i][j]))
441 PUT_ERR("wrong interpolation result for NaN fixed fallback\n");
442 } else if (!utest_double_are_equal(
443 ref_nan_covered[my_target_rank][j], -1.0)) {
444 if (utest_double_are_unequal(
445 target_data[i][j],
446 ref_nan_covered[my_target_rank][j] + (double)(i * 30)))
447 PUT_ERR("wrong interpolation result for NaN fixed fallback\n");
448 }
449 }
450 }
451 }
452
453 for (int i = 0; i < 2; ++i)
454 yac_interpolation_delete(interpolation_nan[i]);
455 }
456
457 //---------
458 // clean up
459 //---------
460
461 yac_basic_grid_delete(src_grid);
462 yac_basic_grid_delete(tgt_grid);
463 yac_interp_weights_delete(weights_nan);
465 yac_interp_grid_delete(interp_grid);
466 yac_dist_grid_pair_delete(grid_pair);
467}
468
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:57
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
Definition basic_grid.c:70
void yac_basic_grid_delete(struct yac_basic_grid *grid)
Definition basic_grid.c:77
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2377
struct yac_dist_grid_pair * yac_dist_grid_pair_new(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Comm comm)
Definition dist_grid.c:2089
void yac_interp_grid_delete(struct yac_interp_grid *interp_grid)
struct yac_interp_grid * yac_interp_grid_new(struct yac_dist_grid_pair *grid_pair, char const *src_grid_name, char const *tgt_grid_name, size_t num_src_fields, struct yac_interp_field const *src_fields, struct yac_interp_field const tgt_field)
Definition interp_grid.c:31
void yac_interp_method_delete(struct interp_method **method)
Delete an interpolation stack and free its resources (but not the pointer array).
struct yac_interp_weights * yac_interp_method_do_search(struct interp_method **method, struct yac_interp_grid *interp_grid)
Perform weight computation using given interpolation stack and grid.
struct interp_method * yac_interp_method_avg_new(enum yac_interp_avg_weight_type weight_type, int partial_coverage)
@ YAC_INTERP_AVG_ARITHMETIC
struct interp_method * yac_interp_method_fixed_new(double value)
struct yac_interpolation * yac_interp_weights_get_interpolation(struct yac_interp_weights *weights, enum yac_interp_weights_reorder_type reorder, size_t collection_size, double frac_mask_fallback_value, double scaling_factor, double scaling_summand, char const *yaxt_exchanger_name, int is_source, int is_target)
void yac_interp_weights_delete(struct yac_interp_weights *weights)
yac_interp_weights_reorder_type
@ YAC_MAPPING_ON_TGT
weights will be applied at target processes
@ YAC_MAPPING_ON_SRC
weights will be applied at source processes
struct yac_interpolation * yac_interpolation_copy(struct yac_interpolation *interp)
Create a deep copy of an interpolation object.
void yac_interpolation_delete(struct yac_interpolation *interp)
Free an interpolation object and release all resources.
void yac_interpolation_execute_get(struct yac_interpolation *interp, double **tgt_field)
Complete interpolation and write results to the target field (get phase).
void yac_interpolation_execute_put(struct yac_interpolation *interp, double ***src_fields)
Provide source field data and start asynchronous execution of interpolation (put phase).
double const YAC_FRAC_MASK_NO_VALUE
@ YAC_LOC_CORNER
Definition location.h:15
#define xmalloc(size)
Definition ppm_xfuncs.h:66
enum yac_location location
Definition basic_grid.h:16
struct yac_interp_field tgt_field
Definition interp_grid.c:26
size_t num_src_fields
Definition interp_grid.c:27
struct yac_dist_grid_pair * grid_pair
Definition interp_grid.c:25
struct yac_interp_field src_fields[]
Definition interp_grid.c:28
int collection_size
static MPI_Comm split_comm
char const grid_name_tgt[]
#define MAX_COLLECTION_SIZE
char const grid_name_src[]
double coordinates_x[]
size_t num_cells[2]
double coordinates_y[]
#define TEST_EXIT_CODE
Definition tests.h:15
#define PUT_ERR(string)
Definition tests.h:10