YAC 3.20.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interp_weights_parallel.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 <unistd.h>
8#include <mpi.h>
9#include <yaxt.h>
10#include <netcdf.h>
11#include <string.h>
12
13#include "tests.h"
14#include "test_common.h"
15#include "geometry.h"
16#include "read_icon_grid.h"
20#include "yac_mpi.h"
21#include "dist_grid_utils.h"
22#include "io_utils.h"
25
32 NONE = 0,
33 DIRECT = 1,
34 SUM = 2,
35 WSUM = 3,
36 FIXED = 4,
37};
38
39#define FALLBACK_VALUE (-1.0)
40#define FIXED_VALUE (999.0)
41#define TOL (1e-6)
42
43static void utest_get_basic_grid_data(
44 char * filename, size_t * num_cells, size_t * num_vertices,
45 size_t * num_edges);
46static int utest_check_fixed_results(
47 struct yac_basic_grid_data * grid, int is_src,
48 struct yac_interp_weights * weights,
49 enum yac_interp_weights_reorder_type reorder_type,
50 double * field_data);
51static int utest_check_direct_results(
52 struct yac_basic_grid_data * grid, int is_src,
53 struct yac_interp_weights * weights,
54 enum yac_interp_weights_reorder_type reorder_type, size_t collection_size,
55 double *** src_data, double *** src_frac_masks, double ** tgt_data);
56static int utest_check_results_ref(
57 int is_src, struct yac_interp_weights * weights,
58 double * src_data, double * tgt_data, double * ref_tgt_data, size_t tgt_size,
59 int is_active_src, int is_active_tgt);
60
61static void utest_get_basic_weight_file_info(
62 char const * weight_file_name, int * contains_links, int * contains_fixed);
64 MPI_Comm comm, char const * msg, char const * source, int line);
65static char const * weight_file_name_on_existing =
66 "test_interp_weights_parallel_on_existing.nc";
67
68static void utest_interpolation_execute_raw(
69 struct yac_interpolation_exchange * interpolation_exchange,
71 size_t collection_size, double *** src_fields, double ** tgt_field);
72
73static void utest_interpolation_execute_frac_raw(
74 struct yac_interpolation_exchange * interpolation_exchange,
76 size_t collection_size, double *** src_fields, double *** src_frac_masks,
77 double ** tgt_field);
78
79static struct yac_basic_grid_data
80 utest_generate_dummy_grid_data(
81 size_t num_cells, size_t global_num_cells, size_t num_cells_offset);
82
83static char const * grid_names[2] = {"grid_a", "grid_b"};
84
85int main(int argc, char** argv) {
86
87 MPI_Init(NULL, NULL);
88
89 xt_initialize(MPI_COMM_WORLD);
90
91 int comm_rank, comm_size;
92 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
93 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
94
95 if (comm_size != 5) {
96 PUT_ERR("This test requires 5 processes\n");
97 xt_finalize();
98 MPI_Finalize();
99 return TEST_EXIT_CODE;
100 }
101
105 };
106 size_t reorder_type_count =
107 sizeof(reorder_types) / sizeof(reorder_types[0]);
108
109 { // test with 2 target and 3 source processes
110 // * number source and target points is identical
111 // * first target process owns all even target cells and the other
112 // all odd target cells
113 // * each source process owns one third of the source points
114 // (they are consecutive)
115 // * each process generates a part of the weights for a consecutive part
116 // of the target points
117 // * checks interpolation generation for cases, where target status is
118 // deactivated on a subset of target processes
119 int is_src = comm_rank < 3;
120
121 enum {
122 SRC_PROC_COUNT = 3,
123 TGT_PROC_COUNT = 2,
124 };
125 enum {
126 GLOBAL_SIZE =
127 SRC_PROC_COUNT * TGT_PROC_COUNT *
128 (SRC_PROC_COUNT + TGT_PROC_COUNT) * 2,
129 LOCAL_SIZE =
130 SRC_PROC_COUNT * TGT_PROC_COUNT * 2,
131 };
132
133 double wsum_weights[3*LOCAL_SIZE];
134 double sum_weights[3*LOCAL_SIZE];
135 double direct_weights[LOCAL_SIZE];
136 size_t wsum_num_src_per_tgt[LOCAL_SIZE];
137 size_t direct_num_src_per_tgt[LOCAL_SIZE];
138 struct remote_points * default_tgts = xmalloc(1 * sizeof(*default_tgts));
139 default_tgts->data = xmalloc(LOCAL_SIZE * sizeof(*default_tgts->data));
140 struct remote_points none_tgts;
141 struct remote_point * wsum_srcs =
142 xmalloc(3 * LOCAL_SIZE * sizeof(*wsum_srcs));
143 struct remote_point * direct_srcs =
144 xmalloc(LOCAL_SIZE * sizeof(*direct_srcs));
145
146 default_tgts->count = LOCAL_SIZE;
147 for (size_t i = 0; i < LOCAL_SIZE; ++i) {
148 for (size_t j = 0; j < 3; ++j) {
149 wsum_weights[3 * i + j] = (double)(j+1);
150 sum_weights[3 * i + j] = 1.0;
151 }
152 direct_weights[i] = 1.0;
153 wsum_num_src_per_tgt[i] = 3;
154 direct_num_src_per_tgt[i] = 1;
155
156 yac_int tgt_global_id = (yac_int)(comm_rank * LOCAL_SIZE + i);
157 default_tgts->data[i].global_id = tgt_global_id;
158 default_tgts->data[i].data.count = 1;
159 default_tgts->data[i].data.data.single.rank =
160 (int)(tgt_global_id & 1) + (int)SRC_PROC_COUNT;
161 default_tgts->data[i].data.data.single.orig_pos =
162 (uint64_t)(tgt_global_id / 2);
163
164 for (size_t j = 0; j < 3; ++j) {
165 yac_int src_global_id =
166 (tgt_global_id + (yac_int)j)%((yac_int)GLOBAL_SIZE);
167 wsum_srcs[3 * i + j].global_id = src_global_id;
168 wsum_srcs[3 * i + j].data.count = 1;
169 wsum_srcs[3 * i + j].data.data.single.rank =
170 (int)src_global_id % (int)SRC_PROC_COUNT;
171 wsum_srcs[3 * i + j].data.data.single.orig_pos =
172 (uint64_t)(src_global_id / SRC_PROC_COUNT);
173 }
174
175 yac_int src_global_id = tgt_global_id;
176 direct_srcs[i].global_id = src_global_id;
177 direct_srcs[i].data.count = 1;
178 direct_srcs[i].data.data.single.rank =
179 (int)src_global_id % (int)SRC_PROC_COUNT;
180 direct_srcs[i].data.data.single.orig_pos =
181 (uint64_t)(src_global_id / SRC_PROC_COUNT);
182 }
183 none_tgts.count = 0;
184 none_tgts.data = 0;
185
186 double * out_data =
187 (is_src)?xmalloc((GLOBAL_SIZE / SRC_PROC_COUNT) * sizeof(*out_data)):NULL;
188 if (is_src)
189 for (size_t i = 0; i < GLOBAL_SIZE / SRC_PROC_COUNT; ++i)
190 out_data[i] = (double)((yac_int)comm_rank + i * SRC_PROC_COUNT);
191 double * in_data =
192 (is_src)?NULL:xmalloc((GLOBAL_SIZE / TGT_PROC_COUNT) * sizeof(*in_data));
193 double * ref_in_data =
194 (is_src)?NULL:xmalloc((GLOBAL_SIZE / TGT_PROC_COUNT) * sizeof(*ref_in_data));
195
197 utest_generate_dummy_grid_data(
198 GLOBAL_SIZE / ((is_src)?SRC_PROC_COUNT:TGT_PROC_COUNT), GLOBAL_SIZE,
199 (size_t)comm_rank - ((is_src)?0:SRC_PROC_COUNT));
200
201 struct yac_basic_grid * src_grid, * tgt_grid;
202 if (is_src) {
205 } else {
208 }
209
210 struct yac_dist_grid_pair * grid_pair =
211 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
212
213 struct yac_interp_field src_fields[] =
214 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
215 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
217 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
218
219 struct yac_interp_grid * interp_grid =
222 yac_basic_grid_get_name(tgt_grid),
224
238 for (size_t i = 0; i < (1 << (2 * (SRC_PROC_COUNT + TGT_PROC_COUNT))); ++i) {
239
240 enum weight_type weight_type[SRC_PROC_COUNT + TGT_PROC_COUNT];
241 int max_weight_type = 0;
242
243 for (size_t j = 0; j < SRC_PROC_COUNT + TGT_PROC_COUNT; ++j) {
244 weight_type[j] = (enum weight_type)((i >> (3 * j)) & 3);
245 if ((int)(weight_type[j]) > max_weight_type)
246 max_weight_type = (int)(weight_type[j]);
247 }
248
249 struct remote_points * tgts;
250 size_t * num_src_per_tgt;
251 struct remote_point * srcs;
252 double * w;
253
254 switch (weight_type[comm_rank]) {
255 case(NONE):
256 default:
257 tgts = &none_tgts;
258 num_src_per_tgt = NULL;
259 srcs = NULL;
260 w = NULL;
261 break;
262 case(DIRECT):
263 tgts = default_tgts;
264 num_src_per_tgt = direct_num_src_per_tgt;
265 srcs = direct_srcs;
266 w = direct_weights;
267 break;
268 case(SUM):
269 tgts = default_tgts;
270 num_src_per_tgt = wsum_num_src_per_tgt;
271 srcs = wsum_srcs;
272 w = sum_weights;
273 break;
274 case(WSUM):
275 tgts = default_tgts;
276 num_src_per_tgt = wsum_num_src_per_tgt;
277 srcs = wsum_srcs;
278 w = wsum_weights;
279 break;
280 }
281
282 for (int j = MAX(max_weight_type, DIRECT); j <= (int)WSUM; ++j) {
283
284 struct yac_interp_weights * weights =
286 MPI_COMM_WORLD, YAC_LOC_CELL,
287 (enum yac_location[]){YAC_LOC_CELL}, 1);
288
289 switch (j) {
290 case(NONE):
291 default:
292 break;
293 case(DIRECT):
294 yac_interp_weights_add_direct(weights, tgts, srcs);
295 break;
296 case(SUM):
297 yac_interp_weights_add_sum(weights, tgts, num_src_per_tgt, srcs);
298 break;
299 case(WSUM):
301 weights, tgts, num_src_per_tgt, srcs, w);
302 break;
303 }
304
305 enum {ACTIVE_TARGET_CONFIG_COUNT = 4};
306 int active_target_configs[ACTIVE_TARGET_CONFIG_COUNT][TGT_PROC_COUNT] =
307 {{0,0},{0,1},{1,0},{1,1}};
308
309 for (size_t tgt_config_idx = 0;
310 tgt_config_idx < ACTIVE_TARGET_CONFIG_COUNT; ++tgt_config_idx) {
311
312 int is_active_src = 0;
313 int is_active_tgt = 0;
314
315 if (is_src) {
316
317 is_active_src = 1;
318
319 } else {
320
321 int tgt_rank = (yac_int)(comm_rank - (int)SRC_PROC_COUNT);
322 is_active_tgt = active_target_configs[tgt_config_idx][tgt_rank];
323
324 for (size_t k = 0; k < GLOBAL_SIZE / TGT_PROC_COUNT; ++k) {
325 yac_int tgt_global_id = (yac_int)tgt_rank + k * TGT_PROC_COUNT;
326 // which rank generates the weights
327 int weight_rank = (int)(tgt_global_id / (yac_int)LOCAL_SIZE);
328 double ref_value;
329 switch (weight_type[weight_rank]) {
330 case(NONE):
331 default:
332 ref_value = FALLBACK_VALUE;
333 break;
334 case(DIRECT):
335 ref_value = (double)tgt_global_id;
336 break;
337 case(SUM):
338 ref_value = (double)(((tgt_global_id + 0) % GLOBAL_SIZE) +
339 ((tgt_global_id + 1) % GLOBAL_SIZE) +
340 ((tgt_global_id + 2) % GLOBAL_SIZE));
341 break;
342 case(WSUM):
343 ref_value = (double)(1 * ((tgt_global_id + 0) % GLOBAL_SIZE) +
344 2 * ((tgt_global_id + 1) % GLOBAL_SIZE) +
345 3 * ((tgt_global_id + 2) % GLOBAL_SIZE));
346 break;
347 };
348 ref_in_data[k] = is_active_tgt?ref_value:FALLBACK_VALUE;
349 in_data[k] = FALLBACK_VALUE;
350 }
351 }
352
353 // checking with different reorder types and collection sizes
354 if (utest_check_results_ref(
355 is_src, weights,
356 out_data, in_data, ref_in_data, GLOBAL_SIZE / TGT_PROC_COUNT,
357 is_active_src, is_active_tgt))
358 PUT_ERR("ERROR(yac_interp_weights_add_*): "
359 "invalid interpolation result");
360 }
361
362 MPI_Comm weights_comm =
364
365 int compare_result;
366 MPI_Comm_compare(weights_comm, MPI_COMM_WORLD, &compare_result);
367 if ((compare_result != MPI_IDENT) &&
368 (compare_result != MPI_CONGRUENT))
369 PUT_ERR("ERROR(yac_interp_weights_get_comm): wrong communicator");
370
372 }
373 }
374 yac_interp_grid_delete(interp_grid);
375 yac_dist_grid_pair_delete(grid_pair);
376 yac_basic_grid_delete(tgt_grid);
377 yac_basic_grid_delete(src_grid);
378 free(ref_in_data);
379 free(in_data);
380 free(out_data);
381 free(direct_srcs);
382 free(wsum_srcs);
383 free(default_tgts->data);
384 free(default_tgts);
385 }
386
387 { // test with 2 target and 3 source processes
388 // * checks interpolation generation for cases, where source status is
389 // deactivated on a subset of source processes
390 int is_src = comm_rank < 3;
391
392 enum {
393 SRC_PROC_COUNT = 3,
394 TGT_PROC_COUNT = 2,
395 };
396 enum {
397 SRC_NUM_POINTS = 3,
398 TGT_NUM_POINTS = 1,
399 };
400
401 int src_ranks[SRC_PROC_COUNT] = {0, 1, 2};
402 int tgt_ranks[TGT_PROC_COUNT] = {3, 4};
403 double wsum_weights[SRC_NUM_POINTS];
404 double sum_weights[SRC_NUM_POINTS];
405 double direct_weights[TGT_NUM_POINTS];
406 size_t wsum_num_src_per_tgt[TGT_NUM_POINTS];
407 size_t direct_num_src_per_tgt[TGT_NUM_POINTS];
408 struct remote_points * default_tgts =
409 xmalloc(TGT_NUM_POINTS * sizeof(*default_tgts));
410 default_tgts->data = xmalloc(TGT_NUM_POINTS * sizeof(*default_tgts->data));
411 struct remote_points none_tgts;
412 struct remote_point * wsum_srcs =
413 xmalloc(SRC_NUM_POINTS * sizeof(*wsum_srcs));
414 struct remote_point * direct_srcs =
415 xmalloc(TGT_NUM_POINTS * sizeof(*direct_srcs));
416
417 default_tgts->count = TGT_NUM_POINTS;
418 for (size_t tgt_point_idx = 0; tgt_point_idx < TGT_NUM_POINTS;
419 ++tgt_point_idx) {
420 for (size_t src_point_idx = 0; src_point_idx < SRC_NUM_POINTS;
421 ++src_point_idx) {
422 wsum_weights[SRC_NUM_POINTS * tgt_point_idx + src_point_idx] =
423 (double)(src_point_idx+1);
424 sum_weights[SRC_NUM_POINTS * tgt_point_idx + src_point_idx] = 1.0;
425 }
426 direct_weights[tgt_point_idx] = 1.0;
427 wsum_num_src_per_tgt[tgt_point_idx] = SRC_NUM_POINTS;
428 direct_num_src_per_tgt[tgt_point_idx] = 1;
429
430 yac_int tgt_global_id = (yac_int)tgt_point_idx;
431 default_tgts->data[tgt_point_idx].global_id = tgt_global_id;
432 default_tgts->data[tgt_point_idx].data.count = TGT_PROC_COUNT;
433 default_tgts->data[tgt_point_idx].data.data.multi =
434 xmalloc(
435 TGT_PROC_COUNT *
436 sizeof(*(default_tgts->data[tgt_point_idx].data.data.multi)));
437 for (size_t tgt_rank_idx = 0; tgt_rank_idx < TGT_PROC_COUNT;
438 ++tgt_rank_idx) {
439 default_tgts->data[tgt_point_idx].data.data.multi[tgt_rank_idx].
440 rank = tgt_ranks[tgt_rank_idx];
441 default_tgts->data[tgt_point_idx].data.data.multi[tgt_rank_idx].
442 orig_pos = tgt_point_idx;
443 }
444
445 for (size_t src_point_idx = 0; src_point_idx < SRC_NUM_POINTS;
446 ++src_point_idx) {
447 yac_int src_global_id = (yac_int)src_point_idx;
448 wsum_srcs[SRC_NUM_POINTS * tgt_point_idx + src_point_idx].
449 global_id = src_global_id;
450 wsum_srcs[SRC_NUM_POINTS * tgt_point_idx + src_point_idx].
451 data.count = SRC_PROC_COUNT;
452 wsum_srcs[SRC_NUM_POINTS * tgt_point_idx + src_point_idx].
453 data.data.multi =
454 xmalloc(SRC_PROC_COUNT * sizeof(*(wsum_srcs->data.data.multi)));
455 for (size_t src_rank_idx = 0; src_rank_idx < SRC_PROC_COUNT;
456 ++src_rank_idx) {
457 wsum_srcs[SRC_NUM_POINTS * tgt_point_idx + src_point_idx].
458 data.data.multi[src_rank_idx].rank = src_ranks[src_rank_idx];
459 wsum_srcs[SRC_NUM_POINTS * tgt_point_idx + src_point_idx].
460 data.data.multi[src_rank_idx].orig_pos = (uint64_t)src_point_idx;
461 }
462 }
463
464 yac_int src_global_id = tgt_global_id;
465 direct_srcs[tgt_point_idx].global_id = src_global_id;
466 direct_srcs[tgt_point_idx].data.count = SRC_PROC_COUNT;
467 direct_srcs[tgt_point_idx].data.data.multi =
468 xmalloc(SRC_PROC_COUNT * sizeof(*(direct_srcs->data.data.multi)));
469 for (size_t src_rank_idx = 0; src_rank_idx < SRC_PROC_COUNT;
470 ++src_rank_idx) {
471 direct_srcs[tgt_point_idx].data.data.multi[src_rank_idx].rank =
472 src_ranks[src_rank_idx];
473 direct_srcs[tgt_point_idx].data.data.multi[src_rank_idx].orig_pos = 0;
474 }
475 }
476 none_tgts.count = 0;
477 none_tgts.data = 0;
478
479 double * out_data = (is_src)?xmalloc(SRC_NUM_POINTS * sizeof(*out_data)):NULL;
480 if (is_src)
481 for (size_t i = 0; i < SRC_NUM_POINTS; ++i)
482 out_data[i] = (double)((yac_int)comm_rank + i * SRC_PROC_COUNT);
483 double * in_data =
484 (is_src)?NULL:xmalloc(TGT_NUM_POINTS * sizeof(*in_data));
485 double * ref_in_data =
486 (is_src)?NULL:xmalloc(TGT_NUM_POINTS * sizeof(*ref_in_data));
487
489 utest_generate_dummy_grid_data(
490 is_src?SRC_NUM_POINTS:TGT_NUM_POINTS,
491 is_src?SRC_NUM_POINTS:TGT_NUM_POINTS, 0);
492
493 struct yac_basic_grid * src_grid, * tgt_grid;
494 if (is_src) {
497 } else {
500 }
501
502 struct yac_dist_grid_pair * grid_pair =
503 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
504
505 struct yac_interp_field src_fields[] =
506 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
507 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
509 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
510
511 struct yac_interp_grid * interp_grid =
514 yac_basic_grid_get_name(tgt_grid),
516
518 enum {NUM_WEIGHT_TYPES = sizeof(weight_types) / sizeof(weight_types[0])};
519
520 for (size_t weight_type_idx = 0; weight_type_idx < NUM_WEIGHT_TYPES;
521 ++weight_type_idx) {
522
523 enum weight_type weight_type = weight_types[weight_type_idx];
524
525 struct remote_points * tgts;
526 size_t * num_src_per_tgt;
527 struct remote_point * srcs;
528 double * w;
529
530 struct yac_interp_weights * weights =
532 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
533
534 switch (weight_type) {
535 case(NONE):
536 default:
537 tgts = &none_tgts;
538 num_src_per_tgt = NULL;
539 srcs = NULL;
540 w = NULL;
541 break;
542 case (FIXED):
543 tgts = default_tgts;
545 break;
546 case(DIRECT):
547 tgts = default_tgts;
548 num_src_per_tgt = direct_num_src_per_tgt;
549 srcs = direct_srcs;
550 w = direct_weights;
551 yac_interp_weights_add_direct(weights, tgts, srcs);
552 break;
553 case(SUM):
554 tgts = default_tgts;
555 num_src_per_tgt = wsum_num_src_per_tgt;
556 srcs = wsum_srcs;
557 w = sum_weights;
558 yac_interp_weights_add_sum(weights, tgts, num_src_per_tgt, srcs);
559 break;
560 case(WSUM):
561 tgts = default_tgts;
562 num_src_per_tgt = wsum_num_src_per_tgt;
563 srcs = wsum_srcs;
564 w = wsum_weights;
566 weights, tgts, num_src_per_tgt, srcs, w);
567 break;
568 }
569
570 for (int active_source_rank = 0; active_source_rank < SRC_PROC_COUNT;
571 ++active_source_rank) {
572
573 int is_active_src = 0;
574 int is_active_tgt = 0;
575
576 if (is_src) {
577
578 is_active_src = active_source_rank == comm_rank;
579
580 } else {
581
582 is_active_tgt = 1;
583
584 for (size_t tgt_point_idx = 0; tgt_point_idx < TGT_NUM_POINTS;
585 ++tgt_point_idx) {
586 switch (weight_type) {
587 case(NONE):
588 default:
589 ref_in_data[tgt_point_idx] = FALLBACK_VALUE;
590 break;
591 case(FIXED):
592 ref_in_data[tgt_point_idx] = FIXED_VALUE;
593 break;
594 case(DIRECT):
595 ref_in_data[tgt_point_idx] =
596 (double)(tgt_point_idx + active_source_rank);
597 break;
598 case(SUM):
599 ref_in_data[tgt_point_idx] =
600 (double)(
601 (tgt_point_idx + active_source_rank + 0 * SRC_NUM_POINTS) +
602 (tgt_point_idx + active_source_rank + 1 * SRC_NUM_POINTS) +
603 (tgt_point_idx + active_source_rank + 2 * SRC_NUM_POINTS));
604 break;
605 case(WSUM):
606 ref_in_data[tgt_point_idx] =
607 (double)(
608 1 * (tgt_point_idx + active_source_rank + 0 * SRC_NUM_POINTS) +
609 2 * (tgt_point_idx + active_source_rank + 1 * SRC_NUM_POINTS) +
610 3 * (tgt_point_idx + active_source_rank + 2 * SRC_NUM_POINTS));
611 break;
612 };
613 in_data[tgt_point_idx] = FALLBACK_VALUE;
614 }
615 }
616
617 // checking with different reorder types and collection sizes
618 if (utest_check_results_ref(
619 is_src, weights,
620 out_data, in_data, ref_in_data, TGT_NUM_POINTS,
621 is_active_src, is_active_tgt))
622 PUT_ERR("ERROR(yac_interp_weights_add_*): "
623 "invalid interpolation result");
624 }
625
626 MPI_Comm weights_comm =
628
629 int compare_result;
630 MPI_Comm_compare(weights_comm, MPI_COMM_WORLD, &compare_result);
631 if ((compare_result != MPI_IDENT) &&
632 (compare_result != MPI_CONGRUENT))
633 PUT_ERR("ERROR(yac_interp_weights_get_comm): wrong communicator");
634
636 }
637
638 yac_interp_grid_delete(interp_grid);
639 yac_dist_grid_pair_delete(grid_pair);
640 yac_basic_grid_delete(tgt_grid);
641 yac_basic_grid_delete(src_grid);
642 free(ref_in_data);
643 free(in_data);
644 free(out_data);
645 for (size_t tgt_point_idx = 0; tgt_point_idx < TGT_NUM_POINTS;
646 ++tgt_point_idx) {
647 free(direct_srcs[tgt_point_idx].data.data.multi);
648 free(default_tgts->data[tgt_point_idx].data.data.multi);
649 for (size_t src_point_idx = 0; src_point_idx < SRC_NUM_POINTS;
650 ++src_point_idx) {
651 free(
652 wsum_srcs[
653 SRC_NUM_POINTS * tgt_point_idx + src_point_idx].data.data.multi);
654 }
655 }
656 free(direct_srcs);
657 free(wsum_srcs);
658 free(default_tgts->data);
659 free(default_tgts);
660 }
661
662 {
663 int is_src = comm_rank < (comm_size / 2);
664
665 MPI_Comm local_grid_comm;
666 int local_grid_comm_size;
667 MPI_Comm_split(MPI_COMM_WORLD, is_src, 0, &local_grid_comm);
668 MPI_Comm_size(local_grid_comm, &local_grid_comm_size);
669
670 set_even_io_rank_list(local_grid_comm);
671
672 setenv("YAC_YAXT_EXCHANGER", "irecv_isend", 1);
673
674 if (argc != 2) {
675 PUT_ERR("ERROR: missing grid file directory");
676 xt_finalize();
677 MPI_Finalize();
678 return TEST_EXIT_CODE;
679 }
680
681 char * filenames[2];
682 char * grid_filenames[] =
683 {"icon_grid_R02B01.nc", "icon_grid_R03B01.nc"};
684 for (int i = 0; i < 2; ++i)
685 filenames[i] =
686 strcat(
687 strcpy(
688 malloc(strlen(argv[1]) + strlen(grid_filenames[i]) + 2), argv[1]),
689 grid_filenames[i]);
690
693 filenames[is_src], local_grid_comm);
694 struct yac_basic_grid * grids[2] =
697
698 struct yac_dist_grid_pair * grid_pair =
699 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
700
701 struct yac_interp_field src_fields[] =
702 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
703 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
705 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
706
707 struct yac_interp_grid * interp_grid =
711
712 struct yac_interp_weights * weights =
714 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
715
716 size_t num_tgt_cells, num_tgt_vertices, num_tgt_edges;
717 utest_get_basic_grid_data(
718 filenames[0], &num_tgt_cells, &num_tgt_vertices, &num_tgt_edges);
719 size_t num_src_cells, num_src_vertices, num_src_edges;
720 utest_get_basic_grid_data(
721 filenames[1], &num_src_cells, &num_src_vertices, &num_src_edges);
722
723 {
724 size_t count;
725 size_t * tgt_points;
726 yac_interp_grid_get_tgt_points(interp_grid, &tgt_points, &count);
727 yac_int * tgt_global_ids = xmalloc(count * sizeof(*tgt_global_ids));
728 size_t * size_t_buffer = xmalloc(2 * count * sizeof(*size_t_buffer));
729 size_t * odd_tgt_points = size_t_buffer;
730 size_t * even_tgt_points = size_t_buffer + count;
732 interp_grid, tgt_points, count, tgt_global_ids);
733
734 size_t odd_count = 0;
735 size_t even_count = 0;
736 for (size_t i = 0; i < count; ++i) {
737 if (tgt_global_ids[i] & 1) odd_tgt_points[odd_count++] = tgt_points[i];
738 else even_tgt_points[even_count++] = tgt_points[i];
739 }
740
741 struct remote_points odd_tgts = {
742 .data =
744 interp_grid, odd_tgt_points, odd_count),
745 .count = odd_count};
746 struct remote_points even_tgts = {
747 .data =
749 interp_grid, even_tgt_points, even_count),
750 .count = even_count};
751
752 yac_interp_weights_add_fixed(weights, &odd_tgts, -1.0);
753 yac_interp_weights_add_fixed(weights, &even_tgts, -2.0);
754
755 free(odd_tgts.data);
756 free(even_tgts.data);
757 free(size_t_buffer);
758 free(tgt_global_ids);
759 free(tgt_points);
760 }
761
762 double * field_data =
763 xmalloc(grid_data.num_cells * sizeof(*field_data));
764
765 for (size_t reorder_type = 0; reorder_type < reorder_type_count;
766 ++reorder_type)
767 if (utest_check_fixed_results(
768 &grid_data, is_src, weights,
769 reorder_types[reorder_type], field_data))
770 PUT_ERR("ERROR(yac_interp_weights_add_fixed): "
771 "invalid interpolation result");
772
773 // check writing and reading
774 {
775 char const * weight_file_name =
776 "test_interp_weights_parallel_fixed.nc";
777 // write weights to file
779 weights, weight_file_name, grid_names[1], grid_names[0],
780 num_src_cells, num_tgt_cells, YAC_WEIGHT_FILE_ERROR);
781
782 // read weights
783 struct interp_method * method_stack[2] = {
787 struct yac_interp_weights * weights_from_file =
788 yac_interp_method_do_search(method_stack, interp_grid);
789 yac_interp_method_delete(method_stack);
790
791 if (utest_check_fixed_results(
792 &grid_data, is_src, weights_from_file, YAC_MAPPING_ON_SRC, field_data))
793 PUT_ERR("ERROR(yac_interp_weights_add_fixed): "
794 "invalid interpolation result (read from file)");
795 if (comm_rank == 0) unlink(weight_file_name);
796 yac_interp_weights_delete(weights_from_file);
797 }
798
799 free(field_data);
800
802 yac_interp_grid_delete(interp_grid);
803 yac_dist_grid_pair_delete(grid_pair);
804 yac_basic_grid_delete(grids[1]);
805 yac_basic_grid_delete(grids[0]);
806 free(filenames[1]);
807 free(filenames[0]);
808 MPI_Comm_free(&local_grid_comm);
809
810 unsetenv("YAC_YAXT_EXCHANGER");
811 }
812
813 {
814 int is_src = comm_rank < (comm_size / 2);
815
816 MPI_Comm local_grid_comm;
817 int local_grid_comm_size;
818 MPI_Comm_split(MPI_COMM_WORLD, is_src, 0, &local_grid_comm);
819 MPI_Comm_size(local_grid_comm, &local_grid_comm_size);
820
821 set_even_io_rank_list(local_grid_comm);
822
823 if (argc != 2) {
824 PUT_ERR("ERROR: missing grid file directory");
825 xt_finalize();
826 MPI_Finalize();
827 return TEST_EXIT_CODE;
828 }
829
830 char * filenames[2];
831 char * grid_filenames[] =
832 {"icon_grid_R02B01.nc", "icon_grid_R03B01.nc"};
833 for (int i = 0; i < 2; ++i)
834 filenames[i] =
835 strcat(
836 strcpy(
837 malloc(strlen(argv[1]) + strlen(grid_filenames[i]) + 2), argv[1]),
838 grid_filenames[i]);
839
842 filenames[is_src], local_grid_comm);
843 struct yac_basic_grid * grids[2] =
846
847 struct yac_dist_grid_pair * grid_pair =
848 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
849
850 struct yac_interp_field src_fields[] =
851 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
852 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
854 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
855
856 struct yac_interp_grid * interp_grid =
860
861 struct yac_interp_weights * weights =
863 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
864
865 size_t num_tgt_cells, num_tgt_vertices, num_tgt_edges;
866 utest_get_basic_grid_data(
867 filenames[0], &num_tgt_cells, &num_tgt_vertices, &num_tgt_edges);
868
869 {
870 // get all local target points
871 size_t count;
872 size_t * tgt_points;
873 yac_interp_grid_get_tgt_points(interp_grid, &tgt_points, &count);
874
875 // get global ids of local target points
876 yac_int * tgt_global_ids = xmalloc(count * sizeof(*tgt_global_ids));
878 interp_grid, tgt_points, count, tgt_global_ids);
879
880 // get local ids of matching source points
881 size_t * src_points = xmalloc(count * sizeof(*src_points));
883 interp_grid, 0, tgt_global_ids, count, src_points);
884 free(tgt_global_ids);
885
886 struct remote_points tgts = {
887 .data =
889 interp_grid, tgt_points, count),
890 .count = count};
891
892 struct remote_point * srcs =
894 interp_grid, 0, src_points, count);
895
896 yac_interp_weights_add_direct(weights, &tgts, srcs);
897
898 free(tgts.data);
899 free(tgt_points);
900 free(srcs);
901 free(src_points);
902 }
903
904 double *** src_data, *** src_frac_masks, ** tgt_data;
905
906 if (is_src) {
907 src_data = xmalloc(4 * sizeof(*src_data));
908 for (size_t i = 0; i < 4; ++i)
909 src_data[i] = xmalloc(1 * sizeof(**src_data));
910
911 for (size_t collection_idx = 0; collection_idx < 4;
912 ++collection_idx) {
913 double * src_field =
914 xmalloc(grid_data.num_cells * sizeof(*src_field));
915 for (size_t i = 0; i < grid_data.num_cells; ++i)
916 src_field[i] =
917 (grid_data.core_cell_mask[i])?
918 (double)(grid_data.cell_ids[i]):(-1.0);
919 src_data[collection_idx][0] = src_field;
920 }
921 src_frac_masks = xmalloc(4 * sizeof(*src_frac_masks));
922 for (size_t i = 0; i < 4; ++i)
923 src_frac_masks[i] = xmalloc(1 * sizeof(**src_frac_masks));
924
925 for (size_t collection_idx = 0; collection_idx < 4;
926 ++collection_idx) {
927 double * src_frac_mask =
928 xmalloc(grid_data.num_cells * sizeof(*src_frac_mask));
929 for (size_t i = 0; i < grid_data.num_cells; ++i)
930 src_frac_mask[i] = (grid_data.cell_ids[i]&1)?1.0:0.0;
931 src_frac_masks[collection_idx][0] = src_frac_mask;
932 }
933 tgt_data = NULL;
934 } else {
935 tgt_data = xmalloc(4 * sizeof(*tgt_data));
936 for (size_t collection_idx = 0; collection_idx < 4;
937 ++collection_idx)
938 tgt_data[collection_idx] =
939 xmalloc(grid_data.num_cells * sizeof(**tgt_data));
940 src_data = NULL;
941 src_frac_masks = NULL;
942 }
943
944 // checking with different reorder types and collection sizes
945 for (size_t reorder_type = 0; reorder_type < reorder_type_count;
946 ++reorder_type)
947 for (size_t collection_size = 1; collection_size <= 4;
948 collection_size *= 2)
949 if (utest_check_direct_results(
950 &grid_data, is_src, weights, reorder_types[reorder_type],
951 collection_size, src_data, src_frac_masks, tgt_data))
952 PUT_ERR("ERROR(yac_interp_weights_add_direct): "
953 "invalid interpolation result");
954
955 // check writing and reading
956 {
957 char const * weight_file_name =
958 "test_interp_weights_parallel_direct.nc";
959 // write weights to file
961 weights, weight_file_name, grid_names[1], grid_names[0], 0, 0,
963
964 // read weights
965 struct interp_method * method_stack[2] = {
969 struct yac_interp_weights * weights_from_file =
970 yac_interp_method_do_search(method_stack, interp_grid);
971 yac_interp_method_delete(method_stack);
972
973 // check results
974 if (utest_check_direct_results(
975 &grid_data, is_src, weights, YAC_MAPPING_ON_SRC, 1,
976 src_data, src_frac_masks, tgt_data))
977 PUT_ERR("ERROR(yac_interp_weights_add_direct): "
978 "invalid interpolation result (read from file)");
979 if (comm_rank == 0) unlink(weight_file_name);
980 yac_interp_weights_delete(weights_from_file);
981 }
982
983 if (is_src) {
984 for (size_t collection_idx = 0; collection_idx < 4; ++collection_idx) {
985 free(src_data[collection_idx][0]);
986 free(src_data[collection_idx]);
987 free(src_frac_masks[collection_idx][0]);
988 free(src_frac_masks[collection_idx]);
989 }
990 free(src_data);
991 free(src_frac_masks);
992 } else {
993 for (size_t collection_idx = 0; collection_idx < 4; ++collection_idx)
994 free(tgt_data[collection_idx]);
995 free(tgt_data);
996 }
997
999 yac_interp_grid_delete(interp_grid);
1000 yac_dist_grid_pair_delete(grid_pair);
1001 yac_basic_grid_delete(grids[1]);
1002 yac_basic_grid_delete(grids[0]);
1003 free(filenames[1]);
1004 free(filenames[0]);
1005 MPI_Comm_free(&local_grid_comm);
1006 }
1007
1008 { // check what happens when not all processes receive data
1009 int is_src = comm_rank < (comm_size / 2);
1010
1011 MPI_Comm local_grid_comm;
1012 int local_grid_comm_size;
1013 MPI_Comm_split(MPI_COMM_WORLD, is_src, 0, &local_grid_comm);
1014 MPI_Comm_size(local_grid_comm, &local_grid_comm_size);
1015
1016 set_even_io_rank_list(local_grid_comm);
1017
1018 if (argc != 2) {
1019 PUT_ERR("ERROR: missing grid file directory");
1020 xt_finalize();
1021 MPI_Finalize();
1022 return TEST_EXIT_CODE;
1023 }
1024
1025 char * filenames[2];
1026 char * grid_filenames[] =
1027 {"icon_grid_R02B01.nc", "icon_grid_R03B01.nc"};
1028 for (int i = 0; i < 2; ++i)
1029 filenames[i] =
1030 strcat(
1031 strcpy(
1032 malloc(strlen(argv[1]) + strlen(grid_filenames[i]) + 2), argv[1]),
1033 grid_filenames[i]);
1034
1037 filenames[is_src], local_grid_comm);
1038 struct yac_basic_grid * grids[2] =
1041
1042 struct yac_dist_grid_pair * grid_pair =
1043 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
1044
1045 struct yac_interp_field src_fields[] =
1046 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
1047 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
1049 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
1050
1051 struct yac_interp_grid * interp_grid =
1055
1056 struct yac_interp_weights * weights =
1058 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
1059
1060 size_t num_tgt_cells, num_tgt_vertices, num_tgt_edges;
1061 utest_get_basic_grid_data(
1062 filenames[0], &num_tgt_cells, &num_tgt_vertices, &num_tgt_edges);
1063
1064 if (comm_rank == 0) {
1065
1066 struct remote_points tgts = {
1067 .data =
1069 interp_grid, (size_t[]){0}, 1), .count = 1};
1070
1071 struct remote_point * srcs =
1073 interp_grid, 0, (size_t[]){0}, 1);
1074
1075 yac_interp_weights_add_direct(weights, &tgts, srcs);
1076
1077 free(tgts.data);
1078 free(srcs);
1079 } else {
1080 struct remote_points tgts = {.data = NULL, .count = 0};
1081
1082 struct remote_point * srcs =
1083 yac_interp_grid_get_src_remote_points(interp_grid, 0, NULL, 0);
1084
1085 yac_interp_weights_add_direct(weights, &tgts, srcs);
1086
1087 free(tgts.data);
1088 free(srcs);
1089 }
1090
1091 for (size_t i = 1; i <= 16; i *= 2) {
1092
1093 struct yac_interpolation * interpolation =
1095 weights, YAC_MAPPING_ON_SRC, i,
1096 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1097
1098 yac_interpolation_delete(interpolation);
1099 }
1100
1102 yac_interp_grid_delete(interp_grid);
1103 yac_dist_grid_pair_delete(grid_pair);
1104 yac_basic_grid_delete(grids[1]);
1105 yac_basic_grid_delete(grids[0]);
1106 free(filenames[1]);
1107 free(filenames[0]);
1108 MPI_Comm_free(&local_grid_comm);
1109 }
1110
1111 { // test yac_interp_weights_wcopy_weights
1112
1113 struct yac_interp_weights * weights =
1115 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
1116
1117 // predefined stencils:
1118 // on rank 0:
1119 // global_id=0 : fixed value 1.0
1120 // global_id=1 : fixed value 2.0
1121 // on rank 1:
1122 // global_id=2 : fixed value 3.0
1123 // global_id=3 : direct from src 0
1124 // on rank 2:
1125 // global_id=4 : direct from src 1
1126 // global_id=5 : sum from src 2 and 3
1127 // on rank 3:
1128 // global_id=6 : sum from src 1, 2, and 3
1129 // global_id=7 : wsum from src 0.5*1 and 0.5*3
1130 // on rank 4:
1131 // global_id=8 : wsum from src 0.2*3, 0.5*5, and 0.4*4
1132 switch (comm_rank) {
1133 default:
1134 case (0): {
1135 {
1136 struct remote_point remote_tgt_points[] =
1137 {{.global_id = 0,
1138 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
1139 struct remote_points tgts = {
1140 .data = remote_tgt_points,
1141 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1142 };
1143
1144 double fixed_value = 1.0;
1146 }
1147 {
1148 struct remote_point remote_tgt_points[] =
1149 {{.global_id = 1,
1150 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}};
1151 struct remote_points tgts = {
1152 .data = remote_tgt_points,
1153 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1154 };
1155
1156 double fixed_value = 2.0;
1158 }
1159 break;
1160 }
1161 case (1): {
1162 {
1163 struct remote_point remote_tgt_points[] =
1164 {{.global_id = 2,
1165 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}};
1166 struct remote_points tgts = {
1167 .data = remote_tgt_points,
1168 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1169 };
1170
1171 double fixed_value = 3.0;
1173 }
1174 {
1175 struct remote_point remote_tgt_points[] =
1176 {{.global_id = 3,
1177 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
1178 struct remote_points tgts = {
1179 .data = remote_tgt_points,
1180 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1181 };
1182 struct remote_point srcs[] =
1183 {{.global_id = 0,
1184 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
1185 yac_interp_weights_add_direct(weights, &tgts, srcs);
1186 }
1187 break;
1188 }
1189 case (2): {
1190 {
1191 struct remote_point remote_tgt_points[] =
1192 {{.global_id = 4,
1193 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}}};
1194 struct remote_points tgts = {
1195 .data = remote_tgt_points,
1196 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1197 };
1198 struct remote_point srcs[] =
1199 {{.global_id = 1,
1200 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}};
1201 yac_interp_weights_add_direct(weights, &tgts, srcs);
1202 }
1203 {
1204 struct remote_point remote_tgt_points[] =
1205 {{.global_id = 5,
1206 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}}};
1207 struct remote_points tgts = {
1208 .data = remote_tgt_points,
1209 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1210 };
1211 size_t num_src_per_tgt[] = {2};
1212 struct remote_point srcs[] =
1213 {{.global_id = 2,
1214 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1215 {.global_id = 3,
1216 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
1217 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, srcs);
1218 }
1219 break;
1220 }
1221 case (3): {
1222 {
1223 struct remote_point remote_tgt_points[] =
1224 {{.global_id = 6,
1225 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 6}}}};
1226 struct remote_points tgts = {
1227 .data = remote_tgt_points,
1228 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1229 };
1230 size_t num_src_per_tgt[] = {3};
1231 struct remote_point srcs[] =
1232 {{.global_id = 1,
1233 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1234 {.global_id = 2,
1235 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1236 {.global_id = 3,
1237 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
1238 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, srcs);
1239 }
1240 {
1241 struct remote_point remote_tgt_points[] =
1242 {{.global_id = 7,
1243 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 7}}}};
1244 struct remote_points tgts = {
1245 .data = remote_tgt_points,
1246 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1247 };
1248 size_t num_src_per_tgt[] = {2};
1249 struct remote_point srcs[] =
1250 {{.global_id = 1,
1251 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1252 {.global_id = 3,
1253 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
1254 double w[] = {0.5, 0.5};
1255 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
1256 }
1257 break;
1258 }
1259 case (4): {
1260 {
1261 struct remote_point remote_tgt_points[] =
1262 {{.global_id = 8,
1263 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 8}}}};
1264 struct remote_points tgts = {
1265 .data = remote_tgt_points,
1266 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1267 };
1268 size_t num_src_per_tgt[] = {3};
1269 struct remote_point srcs[] =
1270 {{.global_id = 3,
1271 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
1272 {.global_id = 5,
1273 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}},
1274 {.global_id = 4,
1275 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}}};
1276 double w[] = {0.2, 0.5, 0.4};
1277 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
1278 }
1279 break;
1280 }
1281 };
1282
1283 // copied stencils:
1284 // on rank 0:
1285 // global_id 10: 1.0 * (fixed_value 1.0 from global_id 0)
1286 // global_id 11: 4.0 * (fixed_value 2.0 from global_id 1) +
1287 // 0.5 * (fixed_value 3.0 from global_id 2)
1288 // on rank 1:
1289 // global_id 12: 0.3 * (direct from global_id 3)
1290 // global_id 13: 0.5 * (direct from global_id 4) +
1291 // 0.1 * (direct from global_id 3)
1292 // on rank 2:
1293 // global_id 14: 0.2 * (sum from global_id 5)
1294 // global_id 15: 0.1 * (direct from global_id 3) +
1295 // 0.9 * (sum from global_id 6)
1296 // global_id 16: 0.3 * (direct from global_id 4) +
1297 // 0.3 * (sum from global_id 6) +
1298 // 0.4 * (sum from global_id 5)
1299 // on rank 3:
1300 // global_id 17: 0.1 * (wsum from global_id 7)
1301 // global_id 18: 0.2 * (wsum from global_id 7) +
1302 // 0.8 * (direct from global_id 3)
1303 // global_id 19: 0.1 * (direct from global_id 4) +
1304 // 0.2 * (sum from global_id 5) +
1305 // 0.3 * (wsum from global_id 8)
1306 // global_id 20: 1.0 * (direct from global_id 3) +
1307 // 1.0 * (sum from global_id 5)
1308 // global_id 21: 0.5 * (direct from global_id 3)
1309 // global_id 22: 0.9 * (fixed_value 1.0 from global_id 0)
1310 switch (comm_rank) {
1311 case(0): {
1312 struct remote_point remote_tgt_points[] =
1313 {{.global_id = 10,
1314 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 10}}},
1315 {.global_id = 11,
1316 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 11}}}
1317 };
1318 struct remote_points tgts = {
1319 .data = remote_tgt_points,
1320 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1321 };
1322
1323 size_t num_stencils_per_tgt[] = {1,2};
1324 size_t stencil_indices[] = {0,1,0};
1325 int stencil_ranks[] = {0,0,1};
1326 double w[] = {1.0,4.0,0.5};
1327
1329 weights, &tgts, num_stencils_per_tgt, stencil_indices,
1330 stencil_ranks, w);
1331
1332 break;
1333 }
1334 case(1): {
1335 struct remote_point remote_tgt_points[] =
1336 {{.global_id = 12,
1337 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 12}}},
1338 {.global_id = 13,
1339 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 13}}}
1340 };
1341 struct remote_points tgts = {
1342 .data = remote_tgt_points,
1343 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1344 };
1345
1346 size_t num_stencils_per_tgt[] = {1,2};
1347 size_t stencil_indices[] = {1,0,1};
1348 int stencil_ranks[] = {1,2,1};
1349 double w[] = {0.3,0.5,0.1};
1350
1352 weights, &tgts, num_stencils_per_tgt, stencil_indices,
1353 stencil_ranks, w);
1354
1355 break;
1356 }
1357 case(2): {
1358 struct remote_point remote_tgt_points[] =
1359 {{.global_id = 14,
1360 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 14}}},
1361 {.global_id = 15,
1362 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 15}}},
1363 {.global_id = 16,
1364 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 16}}}
1365 };
1366 struct remote_points tgts = {
1367 .data = remote_tgt_points,
1368 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1369 };
1370
1371 size_t num_stencils_per_tgt[] = {1,2,3};
1372 size_t stencil_indices[] = {1,1,0,0,0,1};
1373 int stencil_ranks[] = {2,1,3,2,3,2};
1374 double w[] = {0.2,0.1,0.9,0.3,0.3,0.4};
1375
1377 weights, &tgts, num_stencils_per_tgt, stencil_indices,
1378 stencil_ranks, w);
1379
1380 break;
1381 }
1382 case(3): {
1383 struct remote_point remote_tgt_points[] =
1384 {{.global_id = 17,
1385 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 17}}},
1386 {.global_id = 18,
1387 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 18}}},
1388 {.global_id = 19,
1389 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 19}}},
1390 {.global_id = 20,
1391 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 20}}},
1392 {.global_id = 21,
1393 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 21}}},
1394 {.global_id = 22,
1395 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 22}}}};
1396 struct remote_points tgts = {
1397 .data = remote_tgt_points,
1398 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1399 };
1400
1401 size_t num_stencils_per_tgt[] = {1,2,3,2,1,1};
1402 size_t stencil_indices[] = {1,1,1,0,1,0,1,1,1,0};
1403 int stencil_ranks[] = {3,3,1,2,2,4,1,2,1,0};
1404 double w[] = {0.1,0.2,0.8,0.1,0.2,0.3,1.0,1.0,0.5,0.9};
1405
1407 weights, &tgts, num_stencils_per_tgt, stencil_indices,
1408 stencil_ranks, w);
1409
1410 break;
1411 }
1412 default: {
1413
1415 weights, NULL, NULL, NULL, NULL, NULL);
1416 break;
1417 }
1418 }
1419
1420 struct yac_interpolation * interpolation =
1422 weights, YAC_MAPPING_ON_SRC, 1,
1423 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1424
1425 if (comm_rank == 0) {
1426
1427 double src_field_data[] = {1,2,3,4,5,6,7,8,9,10},
1428 tgt_field_data[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1429 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1430 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
1432 {1.0,2.0,3.0,1.0,2.0,3.0+4.0,2.0+3.0+4.0,0.5*2.0+0.5*4.0,
1433 0.2*4.0+0.5*6.0+0.4*5.0,-1,
1434 1.0,9.5,0.3*(1.0),0.5*(2.0)+0.1*(1.0),0.2*(3.0+4.0),
1435 0.1*(1.0)+0.9*(2.0+3.0+4.0),
1436 0.3*(2.0)+0.3*(2.0+3.0+4.0)+0.4*(3.0+4.0),
1437 0.1*(0.5*2.0 + 0.5*4.0),0.2*(0.5*2.0+0.5*4.0)+0.8*(1.0),
1438 0.1*(2.0)+0.2*(3.0+4.0)+0.3*(0.2*4.0+0.5*6.0+0.4*5.0),
1439 1.0*1.0+1.0*(3.0+4.0),0.5*1.0,0.9,-1,-1,-1,-1,-1,-1,-1};
1440 double * src_field = src_field_data,
1442 double ** src_fields = &src_field;
1443
1444 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
1445
1446 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
1447 PUT_ERR("invalid reference data");
1448
1449 for (size_t i = 0;
1450 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
1451 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
1452 PUT_ERR("ERROR in yac_interp_weights_wcopy_weights");
1453
1454 } else {
1455
1456 yac_interpolation_execute(interpolation, NULL, NULL);
1457 }
1458
1459 yac_interpolation_delete(interpolation);
1460
1462 }
1463
1464 { // test yac_interp_weights_wcopy_weights, sources are distributed among
1465 // processes and partially available on multiple ones
1466
1467 struct yac_interp_weights * weights =
1469 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
1470
1471 // predefined stencils:
1472 // on rank 0:
1473 // global_id=0 : sum from src 0, 1, and 2
1474 // global_id=1 : sum from src 1, 3, and 4
1475 // on rank 1:
1476 // global_id=2 : sum from src 2, 3, and 4
1477 // global_id=3 : sum from src 0, 4, and 6
1478 // on rank 2:
1479 // global_id=4 : wsum from src 0.3*0, 0.4*1, and 0.5*2
1480 // global_id=5 : wsum from src 0.1*1, 0.1*3, and 0.1*4
1481 // on rank 3:
1482 // global_id=6 : wsum from src 1.0*2, 1.0*3, and 1.0*4
1483 // global_id=7 : wsum from src 1.0*0, 2.0*4, and 3.0*6
1484 switch (comm_rank) {
1485 case (0): {
1486 struct remote_point remote_tgt_points[] =
1487 {{.global_id = 0,
1488 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1489 {.global_id = 1,
1490 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}};
1491 struct remote_points tgts = {
1492 .data = remote_tgt_points,
1493 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1494 };
1495 size_t num_src_per_tgt[] = {3,3};
1496 struct remote_point srcs[] =
1497 {{.global_id = 0,
1498 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1499 {.global_id = 1,
1500 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1501 {.global_id = 2,
1502 .data =
1503 {.count = 2,
1504 .data.multi =
1505 (struct remote_point_info[])
1506 {{.rank = 0, .orig_pos = 2},{.rank = 1, .orig_pos = 0}}}},
1507 {.global_id = 1,
1508 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1509 {.global_id = 3,
1510 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 1}}},
1511 {.global_id = 4,
1512 .data =
1513 {.count = 2,
1514 .data.multi =
1515 (struct remote_point_info[])
1516 {{.rank = 1, .orig_pos = 2},{.rank = 2, .orig_pos = 0}}}}};
1517 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, srcs);
1518 break;
1519 }
1520 case (1): {
1521 struct remote_point remote_tgt_points[] =
1522 {{.global_id = 2,
1523 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1524 {.global_id = 3,
1525 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
1526 struct remote_points tgts = {
1527 .data = remote_tgt_points,
1528 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1529 };
1530 size_t num_src_per_tgt[] = {3,3};
1531 struct remote_point srcs[] =
1532 {{.global_id = 2,
1533 .data =
1534 {.count = 2,
1535 .data.multi =
1536 (struct remote_point_info[])
1537 {{.rank = 0, .orig_pos = 2},{.rank = 1, .orig_pos = 0}}}},
1538 {.global_id = 3,
1539 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 1}}},
1540 {.global_id = 4,
1541 .data =
1542 {.count = 2,
1543 .data.multi =
1544 (struct remote_point_info[])
1545 {{.rank = 1, .orig_pos = 2},{.rank = 2, .orig_pos = 0}}}},
1546 {.global_id = 0,
1547 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1548 {.global_id = 4,
1549 .data =
1550 {.count = 2,
1551 .data.multi =
1552 (struct remote_point_info[])
1553 {{.rank = 1, .orig_pos = 2},{.rank = 2, .orig_pos = 0}}}},
1554 {.global_id = 6,
1555 .data = {.count = 1, .data.single = {.rank = 2, .orig_pos = 2}}}};
1556 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, srcs);
1557 break;
1558 }
1559 case (2): {
1560 struct remote_point remote_tgt_points[] =
1561 {{.global_id = 4,
1562 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}},
1563 {.global_id = 5,
1564 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}}};
1565 struct remote_points tgts = {
1566 .data = remote_tgt_points,
1567 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1568 };
1569 size_t num_src_per_tgt[] = {3,3};
1570 struct remote_point srcs[] =
1571 {{.global_id = 0,
1572 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1573 {.global_id = 1,
1574 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1575 {.global_id = 2,
1576 .data =
1577 {.count = 2,
1578 .data.multi =
1579 (struct remote_point_info[])
1580 {{.rank = 0, .orig_pos = 2},{.rank = 1, .orig_pos = 0}}}},
1581 {.global_id = 1,
1582 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1583 {.global_id = 3,
1584 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 1}}},
1585 {.global_id = 4,
1586 .data =
1587 {.count = 2,
1588 .data.multi =
1589 (struct remote_point_info[])
1590 {{.rank = 1, .orig_pos = 2},{.rank = 2, .orig_pos = 0}}}}};
1591 double w[] = {0.3,0.4,0.5, 0.1,0.1,0.1};
1592 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
1593 break;
1594 }
1595 case (3): {
1596 struct remote_point remote_tgt_points[] =
1597 {{.global_id = 6,
1598 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 6}}},
1599 {.global_id = 7,
1600 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 7}}}};
1601 struct remote_points tgts = {
1602 .data = remote_tgt_points,
1603 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1604 };
1605 size_t num_src_per_tgt[] = {3,3};
1606 struct remote_point srcs[] =
1607 {{.global_id = 2,
1608 .data =
1609 {.count = 2,
1610 .data.multi =
1611 (struct remote_point_info[])
1612 {{.rank = 0, .orig_pos = 2},{.rank = 1, .orig_pos = 0}}}},
1613 {.global_id = 3,
1614 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 1}}},
1615 {.global_id = 4,
1616 .data =
1617 {.count = 2,
1618 .data.multi =
1619 (struct remote_point_info[])
1620 {{.rank = 1, .orig_pos = 2},{.rank = 2, .orig_pos = 0}}}},
1621 {.global_id = 0,
1622 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1623 {.global_id = 4,
1624 .data =
1625 {.count = 2,
1626 .data.multi =
1627 (struct remote_point_info[])
1628 {{.rank = 1, .orig_pos = 2},{.rank = 2, .orig_pos = 0}}}},
1629 {.global_id = 6,
1630 .data = {.count = 1, .data.single = {.rank = 2, .orig_pos = 2}}}};
1631 double w[] = {1.0,1.0,1.0, 1.0,2.0,3.0};
1632 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
1633 break;
1634 }
1635 default: break;
1636 };
1637
1638 // copied stencils:
1639 // on rank 0:
1640 // global_id 9: 1.0 * (sum from global_id 0) +
1641 // 1.0 * (sum from global_id 2)
1642 // global_id 9: 0.1 * (sum from global_id 0) +
1643 // 0.2 * (sum from global_id 1) +
1644 // 0.3 * (sum from global_id 2) +
1645 // 0.4 * (sum from global_id 3)
1646 // global_id 10: 0.2 * (sum from global_id 2) +
1647 // 0.2 * (sum from global_id 3) +
1648 // 0.2 * (wsum from global_id 4) +
1649 // 0.2 * (wsum from global_id 5)
1650 // global_id 11: 0.25 * (wsum from global_id 5) +
1651 // 0.25 * (wsum from global_id 6) +
1652 // 0.25 * (wsum from global_id 7) +
1653 // 0.25 * (wsum from global_id 8)
1654 switch (comm_rank) {
1655 case(0): {
1656 struct remote_point remote_tgt_points[] =
1657 {{.global_id = 8,
1658 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 8}}},
1659 {.global_id = 9,
1660 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 9}}},
1661 {.global_id = 10,
1662 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 10}}},
1663 {.global_id = 11,
1664 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 11}}}};
1665 struct remote_points tgts = {
1666 .data = remote_tgt_points,
1667 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1668 };
1669
1670 size_t num_stencils_per_tgt[] = {2,4,4,4};
1671 size_t stencil_indices[] = {0,0, 0,1,0,1, 0,1,0,1, 0,1,0,1};
1672 int stencil_ranks[] = {0,1, 0,0,1,1, 1,1,2,2, 2,2,3,3};
1673 double w[] =
1674 {1.0,1.0, 0.1,0.2,0.3,0.4, 0.2,0.2,0.2,0.2, 0.25,0.25,0.25,0.25};
1675
1677 weights, &tgts, num_stencils_per_tgt, stencil_indices,
1678 stencil_ranks, w);
1679
1680 break;
1681 }
1682 default: {
1683
1685 weights, NULL, NULL, NULL, NULL, NULL);
1686 break;
1687 }
1688 }
1689 for (size_t i = 0; i < reorder_type_count; ++i) {
1690
1691 struct yac_interpolation * interpolation =
1693 weights, reorder_types[i], 1,
1694 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1695
1696 double src_field_data[3][3] = {{1,2,3},{3,4,5},{5,6,7}};
1697 double * src_field[5] =
1698 {src_field_data[0],src_field_data[1],src_field_data[2],NULL,NULL};
1699 double ** src_fields = &(src_field[comm_rank]);
1700 double tgt_field_data[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
1701 double * tgt_field = tgt_field_data;
1702
1703 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
1704
1705 if (comm_rank == 0) {
1706
1707 double ref_tgt_field_data[] =
1708 {1.0+2.0+3.0,
1709 2.0+4.0+5.0,
1710 3.0+4.0+5.0,
1711 1.0+5.0+7.0,
1712 0.3*1.0+0.4*2.0+0.5*3.0,
1713 0.1*2.0+0.1*4.0+0.1*5.0,
1714 1.0*3.0+1.0*4.0+1.0*5.0,
1715 1.0*1.0+2.0*5.0+3.0*7.0,
1716 1.0*(1.0+2.0+3.0)+1.0*(3.0+4.0+5.0),
1717 0.1*(1.0+2.0+3.0)+0.2*(2.0+4.0+5.0)+
1718 0.3*(3.0+4.0+5.)+0.4*(1.0+5.0+7.0),
1719 0.2*(3.0+4.0+5.0)+0.2*(1.0+5.0+7.0)+
1720 0.2*(0.3*1.0+0.4*2.0+0.5*3.0)+0.2*(0.1*2.0+0.1*4.0+0.1*5.0),
1721 0.25*(0.3*1.0+0.4*2.0+0.5*3.0)+0.25*(0.1*2.0+0.1*4.0+0.1*5.0)+
1722 0.25*(1.0*3.0+1.0*4.0+1.0*5.0)+0.25*(1.0*1.0+2.0*5.0+3.0*7.0)};
1723
1724 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
1725 PUT_ERR("invalid reference data");
1726
1727 for (size_t i = 0;
1728 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
1729 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
1730 PUT_ERR("ERROR in yac_interp_weights_wcopy_weights");
1731 }
1732
1733 yac_interpolation_delete(interpolation);
1734 }
1735
1737 }
1738
1739 { // test yac_interp_weights_wcopy_weights, with multiple stencils
1740 // containing the same sources
1741
1742 struct yac_interp_weights * weights =
1744 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
1745
1746 if (comm_rank == 0) {
1747
1748 // predefined stencil
1749 {
1750 struct remote_point remote_tgt_points[] =
1751 {{.global_id = 0,
1752 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
1753 struct remote_points tgts = {
1754 .data = remote_tgt_points,
1755 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1756 };
1757 size_t num_src_per_tgt[] = {1};
1758 struct remote_point srcs[] =
1759 {{.global_id = 0,
1760 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
1761 double w[] = {1.0};
1762 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
1763 }
1764
1765 // copy stencil
1766 {
1767 struct remote_point remote_tgt_points[] =
1768 {{.global_id = 1,
1769 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}};
1770 struct remote_points tgts = {
1771 .data = remote_tgt_points,
1772 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1773 };
1774
1775#define N (20)
1776 size_t num_stencils_per_tgt[] = {1 + 9 * N};
1777 size_t stencil_indices[1 + 9 * N];
1778 int stencil_ranks[1 + 9 * N];
1779 double w[1 + 9 * N];
1780
1781 for (size_t i = 0; i < (1 + 9 * N); ++i) {
1782 stencil_indices[i] = 0;
1783 stencil_ranks[i] = 0;
1784 }
1785 for (int i = 0, k = 0; i < N; ++i)
1786 for (int j = 0; j < 9; ++j, ++k)
1787 w[k] = pow(10.0, (double)(-i));
1788 w[9 * N] = pow(10.0, (double)(-N+1));
1789
1790 // copy stencil
1792 weights, &tgts, num_stencils_per_tgt, stencil_indices,
1793 stencil_ranks, w);
1794 }
1795 } else {
1797 weights, NULL, NULL, NULL, NULL, NULL);
1798 }
1799 for (size_t i = 0; i < reorder_type_count; ++i) {
1800
1801 struct yac_interpolation * interpolation =
1803 weights, reorder_types[i], 1,
1804 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1805
1806 double src_field_data[1][1] = {{1}};
1807 double * src_field[5] = {src_field_data[0],NULL,NULL,NULL,NULL};
1808 double ** src_fields = &(src_field[comm_rank]);
1809 double tgt_field_data[] = {-1,-1};
1810 double * tgt_field = tgt_field_data;
1811
1812 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
1813
1814 if (comm_rank == 0) {
1815
1816 double ref_tgt_field_data[] = {1.0, 10.0};
1817
1818 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
1819 PUT_ERR("invalid reference data");
1820
1821 for (size_t i = 0;
1822 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
1823 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > 0.0)
1824 PUT_ERR("ERROR in yac_interp_weights_wcopy_weights");
1825 }
1826
1827 yac_interpolation_delete(interpolation);
1828 }
1829
1831 }
1832
1833 { // test weights using multiple source fields
1834
1835 struct yac_interp_weights * weights =
1837 MPI_COMM_WORLD, YAC_LOC_CELL,
1839
1840 switch (comm_rank) {
1841 case (0): {
1842 // tgt global_id: 0
1843 // src_field 0:
1844 // 0.3 * src global_id 0
1845 // src field 1:
1846 // 0.3 * src global_id 0
1847 // src field 2:
1848 // 0.4 * src global_id 0
1849 // tgt global_id: 2
1850 // src_field 0:
1851 // 0.1 * src global_id 1
1852 // 0.1 * src global_id 2
1853 // src field 1:
1854 // 0.2 * src global_id 1
1855 // src field 2:
1856 // 0.3 * src global_id 3
1857 // 0.3 * src global_id 2
1858 // 0.3 * src global_id 1
1859 // tgt global_id: 3
1860 // src_field 0:
1861 // 1.0 * src global_id 5
1862 // 1.0 * src global_id 2
1863 // src field 1:
1864 // src field 2:
1865 // 1.0 * src global_id 4
1866 struct remote_point remote_tgt_points[] =
1867 {{.global_id = 0,
1868 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1869 {.global_id = 2,
1870 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1871 {.global_id = 3,
1872 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}
1873 };
1874 struct remote_points tgts = {
1875 .data = remote_tgt_points,
1876 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1877 };
1878 size_t num_src_per_field_per_tgt[3][3] = {{1,1,1},{2,1,3},{2,0,1}};
1879 struct remote_point srcs_per_field_data[3][5] =
1880 {{{.global_id = 0,
1881 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1882 {.global_id = 1,
1883 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1884 {.global_id = 2,
1885 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1886 {.global_id = 5,
1887 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}},
1888 {.global_id = 2,
1889 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}},
1890 {{.global_id = 0,
1891 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1892 {.global_id = 1,
1893 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}},
1894 {{.global_id = 0,
1895 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1896 {.global_id = 3,
1897 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
1898 {.global_id = 2,
1899 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1900 {.global_id = 1,
1901 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1902 {.global_id = 4,
1903 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}}}};
1904 struct remote_point * srcs_per_field[] =
1905 {srcs_per_field_data[0],
1906 srcs_per_field_data[1],
1907 srcs_per_field_data[2]};
1908 double w[] = {0.3,0.3,1.0, 0.1,0.1,0.2,0.3,0.3,0.3, 1.0,1.0,1.0};
1910 weights, &tgts, &num_src_per_field_per_tgt[0][0],
1911 srcs_per_field, w, 3);
1912 break;
1913 }
1914 case (1): {
1915 // tgt global_id: 4
1916 // src_field 0:
1917 // src global_id 0
1918 // src field 1:
1919 // src global_id 0
1920 // src field 2:
1921 // src global_id 0
1922 // tgt global_id: 5
1923 // src_field 0:
1924 // src global_id 1
1925 // src global_id 2
1926 // src field 1:
1927 // src global_id 1
1928 // src field 2:
1929 // src global_id 3
1930 // src global_id 2
1931 // src global_id 1
1932 // tgt global_id: 6
1933 // src_field 0:
1934 // src global_id 5
1935 // src global_id 2
1936 // src field 1:
1937 // src field 2:
1938 // src global_id 4
1939 struct remote_point remote_tgt_points[] =
1940 {{.global_id = 4,
1941 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}},
1942 {.global_id = 5,
1943 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}},
1944 {.global_id = 6,
1945 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 6}}}
1946 };
1947 struct remote_points tgts = {
1948 .data = remote_tgt_points,
1949 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
1950 };
1951 size_t num_src_per_field_per_tgt[3][3] = {{1,1,1},{2,1,3},{2,0,1}};
1952 struct remote_point srcs_per_field_data[3][5] =
1953 {{{.global_id = 0,
1954 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1955 {.global_id = 1,
1956 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1957 {.global_id = 2,
1958 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1959 {.global_id = 5,
1960 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}},
1961 {.global_id = 2,
1962 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}},
1963 {{.global_id = 0,
1964 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1965 {.global_id = 1,
1966 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}},
1967 {{.global_id = 0,
1968 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
1969 {.global_id = 3,
1970 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
1971 {.global_id = 2,
1972 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
1973 {.global_id = 1,
1974 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
1975 {.global_id = 4,
1976 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}}}};
1977 struct remote_point * srcs_per_field[] =
1978 {srcs_per_field_data[0],
1979 srcs_per_field_data[1],
1980 srcs_per_field_data[2]};
1982 weights, &tgts, &num_src_per_field_per_tgt[0][0], srcs_per_field, 3);
1983 break;
1984 }
1985 case (2): {
1986 // tgt global_id: 7
1987 // src_field 0:
1988 // src global_id 0
1989 // tgt global_id: 8
1990 // src_field 2:
1991 // src global_id 3
1992 // tgt global_id: 9
1993 // src_field 1:
1994 // src global_id 2
1995 // tgt global_id: 10
1996 // src_field 2:
1997 // src global_id 2
1998 // tgt global_id: 11
1999 // src_field 2:
2000 // src global_id 3
2001 struct remote_point remote_tgt_points[] =
2002 {{.global_id = 7,
2003 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 7}}},
2004 {.global_id = 8,
2005 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 8}}},
2006 {.global_id = 9,
2007 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 9}}},
2008 {.global_id = 10,
2009 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 10}}},
2010 {.global_id = 11,
2011 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 11}}}};
2012 struct remote_points tgts = {
2013 .data = remote_tgt_points,
2014 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2015 };
2016 size_t src_field_indices[] = {0,2,1,2,2};
2017 struct remote_point srcs_per_field_data[3][3] =
2018 {{{.global_id = 0,
2019 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}},
2020 {{.global_id = 2,
2021 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}},
2022 {{.global_id = 3,
2023 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
2024 {.global_id = 2,
2025 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2026 {.global_id = 3,
2027 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}}};
2028 struct remote_point * srcs_per_field[] =
2029 {srcs_per_field_data[0],
2030 srcs_per_field_data[1],
2031 srcs_per_field_data[2]};
2033 weights, &tgts, src_field_indices, srcs_per_field, 3);
2034 break;
2035 }
2036 default: break;
2037 };
2038
2039
2040 for (size_t i = 0; i < reorder_type_count; ++i) {
2041
2042 size_t collection_size = 1;
2043 double frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE;
2044 double scaling_factor = 1.0;
2045 double scaling_summand = 0.0;
2046 char const * yaxt_exchanger_name = NULL;
2047 struct yac_interpolation * interpolation =
2049 weights, reorder_types[i], collection_size,
2050 frac_mask_fallback_value, scaling_factor, scaling_summand,
2051 yaxt_exchanger_name, 1, 1);
2052 struct yac_interpolation_exchange * interpolation_exchange;
2056 scaling_factor, scaling_summand, yaxt_exchanger_name,
2057 &interpolation_exchange, &interp_weights_data, 1, 1);
2058
2059 if (comm_rank == 0) {
2060
2061 double src_field_data[3][10] = {{1,2,3,4,5,6,7,8,9,10},
2062 {10,20,30,40,50,60,70,80,90,100},
2063 {100,200,300,400,500,600,700,800,900,1000}};
2064 double tgt_field_data[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
2065 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
2066
2067 double ref_tgt_field_data[] =
2068 {0.3*1.0+0.3*10.0+1.0*100.0,
2069 -1,
2070 0.1*2.0+0.1*3.0+0.2*20.0+0.3*400.0+0.3*300.0+0.3*200.0,
2071 1.0*6.0+1.0*3.0+1.0*500.0,
2072 1.0+10.0+100.0,
2073 2.0+3.0+20.0+400.0+300.0+200.0,
2074 6.0+3.0+500.0,
2075 1.0,
2076 400.0,
2077 30.0,
2078 300.0,
2079 400.0,
2080 -1,-1,-1,-1,-1,-1,-1,-1};
2081 double * src_field[3] =
2082 {src_field_data[0], src_field_data[1], src_field_data[2]};
2083 double * tgt_field = tgt_field_data;
2084 double ** src_fields = src_field;
2085
2086 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
2087
2088 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
2089 PUT_ERR("invalid reference data");
2090
2091 for (size_t i = 0;
2092 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2093 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
2094 PUT_ERR("ERROR in multi source field support");
2095
2096 for (size_t i = 0;
2097 i < sizeof(tgt_field_data) / sizeof(tgt_field_data[0]); ++i)
2098 tgt_field_data[i] = -1;
2099
2100 utest_interpolation_execute_raw(
2101 interpolation_exchange, interp_weights_data, collection_size,
2102 &src_fields, &tgt_field);
2103
2104 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
2105 PUT_ERR("invalid reference data");
2106
2107 for (size_t i = 0;
2108 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2109 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
2110 PUT_ERR("ERROR in multi source field support raw");
2111
2112 } else {
2113
2114 yac_interpolation_execute(interpolation, NULL, NULL);
2115
2116 utest_interpolation_execute_raw(
2117 interpolation_exchange, interp_weights_data, collection_size,
2118 NULL, NULL);
2119 }
2120
2123 interpolation_exchange, "direct_mf");
2124 yac_interpolation_delete(interpolation);
2125 }
2126
2128 }
2129
2130 { // test interfaces for multiple source fields but only using
2131 // a single source field
2132
2133 struct yac_interp_weights * weights =
2135 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2136
2137 switch (comm_rank) {
2138 case (0): {
2139 // tgt global_id: 2
2140 // src_field 0:
2141 // src global_id 2
2142 struct remote_point remote_tgt_points[] =
2143 {{.global_id = 2,
2144 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}};
2145 struct remote_points tgts = {
2146 .data = remote_tgt_points,
2147 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2148 };
2149 size_t src_field_indices[] = {0,0,0};
2150 struct remote_point srcs_per_field_data[1][1] =
2151 {{{.global_id = 2,
2152 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}}};
2153 struct remote_point * srcs_per_field[] = {srcs_per_field_data[0]};
2155 weights, &tgts, src_field_indices, srcs_per_field, 1);
2156 break;
2157 }
2158 case (1): {
2159 // tgt global_id: 4
2160 // src_field 0:
2161 // src global_id 0
2162 // src global_id 2
2163 struct remote_point remote_tgt_points[] =
2164 {{.global_id = 4,
2165 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}}};
2166 struct remote_points tgts = {
2167 .data = remote_tgt_points,
2168 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2169 };
2170 size_t num_src_per_field_per_tgt[1][1] = {{2}};
2171 struct remote_point srcs_per_field_data[1][2] =
2172 {{{.global_id = 0,
2173 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2174 {.global_id = 2,
2175 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}}};
2176 struct remote_point * srcs_per_field[] = {srcs_per_field_data[0]};
2178 weights, &tgts, &num_src_per_field_per_tgt[0][0], srcs_per_field, 1);
2179 break;
2180 }
2181 case (2): {
2182 // tgt global_id: 6
2183 // src_field 0:
2184 // 0.7 * src global_id 5
2185 // 0.3 * src global_id 2
2186 struct remote_point remote_tgt_points[] =
2187 {{.global_id = 6,
2188 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 6}}}};
2189 struct remote_points tgts = {
2190 .data = remote_tgt_points,
2191 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2192 };
2193 size_t num_src_per_field_per_tgt[1][1] = {{2}};
2194 struct remote_point srcs_per_field_data[1][2] =
2195 {{{.global_id = 5,
2196 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}},
2197 {.global_id = 2,
2198 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}}};
2199 struct remote_point * srcs_per_field[] = {srcs_per_field_data[0]};
2200 double w[] = {0.7,0.3};
2202 weights, &tgts, &num_src_per_field_per_tgt[0][0],
2203 srcs_per_field, w, 1);
2204 break;
2205 }
2206 default: break;
2207 };
2208
2209 size_t collection_size = 1;
2210 double frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE;
2211 double scaling_factor = 1.0;
2212 double scaling_summand = 0.0;
2213 struct yac_interpolation * interpolation =
2216 frac_mask_fallback_value, scaling_factor, scaling_summand,
2217 NULL, 1, 1);
2218 struct yac_interpolation_exchange * interpolation_exchange;
2223 &interpolation_exchange, &interp_weights_data, 1, 1);
2224
2225 if (comm_rank == 0) {
2226
2227 double src_field_data[1][10] = {{1,2,3,4,5,6,7,8,9,10}};
2228 double tgt_field_data[] = {-1,-1,-1,-1,-1,-1,-1,-1};
2229
2230 double ref_tgt_field_data[] =
2231 {-1,-1,3.0,-1,1.0+3.0,-1,0.7*6.0+0.3*3.0,-1};
2232 double * src_field[1] = {src_field_data[0]};
2233 double * tgt_field = tgt_field_data;
2234 double ** src_fields = src_field;
2235
2236 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
2237
2238 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
2239 PUT_ERR("invalid reference data");
2240
2241 for (size_t i = 0;
2242 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2243 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
2244 PUT_ERR("ERROR in multi source field support");
2245
2246 for (size_t i = 0;
2247 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2248 tgt_field_data[i] = -1;
2249 utest_interpolation_execute_raw(
2250 interpolation_exchange, interp_weights_data, collection_size,
2251 &src_fields, &tgt_field);
2252
2253 for (size_t i = 0;
2254 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2255 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
2256 PUT_ERR("ERROR in multi source field support");
2257
2258 } else {
2259
2260 yac_interpolation_execute(interpolation, NULL, NULL);
2261
2262 utest_interpolation_execute_raw(
2263 interpolation_exchange, interp_weights_data, collection_size,
2264 NULL, NULL);
2265 }
2266
2269 interpolation_exchange, "interpolation raw");
2270 yac_interpolation_delete(interpolation);
2271
2273 }
2274
2275 { // test interfaces for multiple source fields,
2276 // the target points are available on all processes
2277
2278 struct yac_interp_weights * weights =
2280 MPI_COMM_WORLD, YAC_LOC_CELL,
2282
2283 switch (comm_rank) {
2284 case (0): {
2285 // tgt global_id: 2
2286 // src_field 1:
2287 // src global_id 2
2288 struct remote_point remote_tgt_points[] =
2289 {{.global_id = 2,
2290 .data =
2291 {.count = 5,
2292 .data.multi =
2293 (struct remote_point_info[]){{.rank = 0, .orig_pos = 2},
2294 {.rank = 1, .orig_pos = 2},
2295 {.rank = 2, .orig_pos = 2},
2296 {.rank = 3, .orig_pos = 2},
2297 {.rank = 4, .orig_pos = 2}}}}};
2298 struct remote_points tgts = {
2299 .data = remote_tgt_points,
2300 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2301 };
2302 size_t src_field_indices[] = {1};
2303 struct remote_point srcs_per_field_data[2][1] =
2304 {{{.global_id = -1}},
2305 {{.global_id = 2,
2306 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 2}}}}};
2307 struct remote_point * srcs_per_field[] =
2308 {srcs_per_field_data[0], srcs_per_field_data[1]};
2310 weights, &tgts, src_field_indices, srcs_per_field, 2);
2311 break;
2312 }
2313 case (1): {
2314 // tgt global_id: 4
2315 // src_field 0:
2316 // src global_id 0
2317 // src_field 1:
2318 // src global_id 2
2319 struct remote_point remote_tgt_points[] =
2320 {{.global_id = 4,
2321 .data =
2322 {.count = 5,
2323 .data.multi =
2324 (struct remote_point_info[]){{.rank = 0, .orig_pos = 4},
2325 {.rank = 1, .orig_pos = 4},
2326 {.rank = 2, .orig_pos = 4},
2327 {.rank = 3, .orig_pos = 4},
2328 {.rank = 4, .orig_pos = 4}}}}};
2329 struct remote_points tgts = {
2330 .data = remote_tgt_points,
2331 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2332 };
2333 size_t num_src_per_field_per_tgt[2][1] = {{1},{1}};
2334 struct remote_point srcs_per_field_data[2][1] =
2335 {{{.global_id = 0,
2336 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 0}}}},
2337 {{.global_id = 2,
2338 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 2}}}}};
2339 struct remote_point * srcs_per_field[] =
2340 {srcs_per_field_data[0], srcs_per_field_data[1]};
2342 weights, &tgts, &num_src_per_field_per_tgt[0][0], srcs_per_field, 2);
2343 break;
2344 }
2345 case (2): {
2346 // tgt global_id: 6
2347 // src_field 0:
2348 // 0.7 * src global_id 5
2349 // src_field 1:
2350 // 0.3 * src global_id 2
2351 struct remote_point remote_tgt_points[] =
2352 {{.global_id = 6,
2353 .data =
2354 {.count = 5,
2355 .data.multi =
2356 (struct remote_point_info[]){{.rank = 0, .orig_pos = 6},
2357 {.rank = 1, .orig_pos = 6},
2358 {.rank = 2, .orig_pos = 6},
2359 {.rank = 3, .orig_pos = 6},
2360 {.rank = 4, .orig_pos = 6}}}}};
2361 struct remote_points tgts = {
2362 .data = remote_tgt_points,
2363 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2364 };
2365 size_t num_src_per_field_per_tgt[2][1] = {{1},{1}};
2366 struct remote_point srcs_per_field_data[2][1] =
2367 {{{.global_id = 5,
2368 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 5}}}},
2369 {{.global_id = 2,
2370 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 2}}}}};
2371 struct remote_point * srcs_per_field[] =
2372 {srcs_per_field_data[0],srcs_per_field_data[1]};
2373 double w[] = {0.7,0.3};
2375 weights, &tgts, &num_src_per_field_per_tgt[0][0],
2376 srcs_per_field, w, 2);
2377 break;
2378 }
2379 default: break;
2380 };
2381
2382 size_t collection_size = 1;
2383 double frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE;
2384 double scaling_factor = 1.0;
2385 double scaling_summand = 0.0;
2386 struct yac_interpolation * interpolation =
2389 frac_mask_fallback_value, scaling_factor, scaling_summand, NULL, 1, 1);
2390 struct yac_interpolation_exchange * interpolation_exchange;
2395 &interpolation_exchange, &interp_weights_data, 1, 1);
2396
2397 double src_field_data[2][10] =
2398 {{1,2,3,4,5,6,7,8,9,10},{10,20,30,40,50,60,70,80,90,100}};
2399 double tgt_field_data[] = {-1,-1,-1,-1,-1,-1,-1,-1};
2400
2401 double ref_tgt_field_data[] =
2402 {-1,-1,30.0,-1,1.0+30.0,-1,0.7*6.0+0.3*30.0,-1};
2403 double * src_field[2] = {src_field_data[0],src_field_data[1]};
2404 double * tgt_field = tgt_field_data;
2405 double ** src_fields = src_field;
2406
2408 interpolation, (comm_rank == 1)?(&src_fields):NULL, &tgt_field);
2409
2410 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data))
2411 PUT_ERR("invalid reference data");
2412
2413 for (size_t i = 0;
2414 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2415 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
2416 PUT_ERR("ERROR in multi source field support");
2417
2418 for (size_t i = 0;
2419 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2420 tgt_field_data[i] = -1;
2421 utest_interpolation_execute_raw(
2422 interpolation_exchange, interp_weights_data, collection_size,
2423 (comm_rank == 1)?(&src_fields):NULL, &tgt_field);
2424
2425 for (size_t i = 0;
2426 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2427 if (fabs(tgt_field_data[i] - ref_tgt_field_data[i]) > TOL)
2428 PUT_ERR("ERROR in multi source field support");
2429
2432 interpolation_exchange, "interpolation raw");
2433 yac_interpolation_delete(interpolation);
2434
2436 }
2437
2438 { // test with stencil that writes to multiple locations on a single process
2439
2440 struct yac_interp_weights * weights =
2442 MPI_COMM_WORLD, YAC_LOC_CELL,
2444
2445 switch (comm_rank) {
2446 case (2): {
2447 // tgt global_id: 0
2448 // src_field 0:
2449 // 0.7 * src global_id 5
2450 // src_field 1:
2451 // 0.3 * src global_id 2
2452 struct remote_point remote_tgt_points[] =
2453 {{.global_id = 1,
2454 .data =
2455 {.count = 10,
2456 .data.multi =
2457 (struct remote_point_info[]){{.rank = 0, .orig_pos = 1},
2458 {.rank = 2, .orig_pos = 1},
2459 {.rank = 2, .orig_pos = 2},
2460 {.rank = 1, .orig_pos = 2},
2461 {.rank = 0, .orig_pos = 5},
2462 {.rank = 1, .orig_pos = 4},
2463 {.rank = 2, .orig_pos = 0},
2464 {.rank = 3, .orig_pos = 0},
2465 {.rank = 0, .orig_pos = 3},
2466 {.rank = 4, .orig_pos = 1}}}}};
2467 struct remote_points tgts = {
2468 .data = remote_tgt_points,
2469 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2470 };
2471 size_t num_src_per_field_per_tgt[2][1] = {{1},{1}};
2472 struct remote_point srcs_per_field_data[2][1] =
2473 {{{.global_id = 5,
2474 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}},
2475 {{.global_id = 2,
2476 .data = {.count = 1, .data.single = {.rank = 1, .orig_pos = 2}}}}};
2477 struct remote_point * srcs_per_field[] =
2478 {srcs_per_field_data[0],srcs_per_field_data[1]};
2479 double w[] = {0.7,0.3};
2481 weights, &tgts, &num_src_per_field_per_tgt[0][0],
2482 srcs_per_field, w, 2);
2483 break;
2484 }
2485 default: break;
2486 };
2487
2488 for (size_t i = 0; i < reorder_type_count; ++i) {
2489
2490 size_t collection_size = 1;
2491 double frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE;
2492 double scaling_factor = 1.0;
2493 double scaling_summand = 0.0;
2494 struct yac_interpolation * interpolation =
2497 frac_mask_fallback_value, scaling_factor, scaling_summand,
2498 NULL, 1, 1);
2499 struct yac_interpolation_exchange * interpolation_exchange;
2504 &interpolation_exchange, &interp_weights_data, 1, 1);
2505
2506 double src_field_data[2][10] =
2507 {{1,2,3,4,5,6,7,8,9,10},{10,20,30,40,50,60,70,80,90,100}};
2508 double tgt_field_data[] = {-1,-1,-1,-1,-1,-1,-1,-1};
2509
2510 double ref_target_value = 0.7*2.0 + 0.3*30.0;
2511 double ref_tgt_field_data[5][8] =
2512 {{-1,ref_target_value,-1,ref_target_value,-1,ref_target_value,-1,-1},
2513 {-1,-1,ref_target_value,-1,ref_target_value,-1,-1,-1},
2514 {ref_target_value,ref_target_value,ref_target_value,-1,-1,-1,-1,-1},
2515 {ref_target_value,-1,-1,-1,-1,-1,-1,-1},
2516 {-1,ref_target_value,-1,-1,-1,-1,-1,-1}};
2517 double * src_field[2] = {(comm_rank==0)?(src_field_data[0]):NULL,
2518 (comm_rank==1)?(src_field_data[1]):NULL};
2519 double * tgt_field = tgt_field_data;
2520 double ** src_fields = src_field;
2521
2523 interpolation, &src_fields, &tgt_field);
2524
2525 if (sizeof(tgt_field_data) != sizeof(ref_tgt_field_data[comm_rank]))
2526 PUT_ERR("invalid reference data");
2527
2528 for (size_t i = 0;
2529 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2530 if (fabs(tgt_field_data[i] - ref_tgt_field_data[comm_rank][i]) > TOL)
2531 PUT_ERR("ERROR in multi source field support");
2532
2533 for (size_t i = 0;
2534 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2535 tgt_field_data[i] = -1;
2536 utest_interpolation_execute_raw(
2537 interpolation_exchange, interp_weights_data, collection_size,
2538 &src_fields, &tgt_field);
2539
2540 for (size_t i = 0;
2541 i < sizeof(tgt_field_data)/sizeof(tgt_field_data[0]); ++i)
2542 if (fabs(tgt_field_data[i] - ref_tgt_field_data[comm_rank][i]) > TOL)
2543 PUT_ERR("ERROR in multi source field support");
2544
2547 interpolation_exchange, "interpolation raw");
2548 yac_interpolation_delete(interpolation);
2549 }
2550
2552 }
2553
2554 { // test writing empty stencil data to file
2555
2556 struct yac_interp_weights * weights =
2558 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2559
2560 struct remote_points tgts = {
2561 .data = NULL,
2562 .count = 0,
2563 };
2564 yac_interp_weights_add_fixed(weights, &tgts, -1.0);
2565
2566 // check writing and reading
2567 {
2568 char const * weight_file_name =
2569 "test_interp_weights_parallel_empty.nc";
2570 // write weights to file
2572 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2574
2575 MPI_Barrier(MPI_COMM_WORLD);
2576
2577 if (comm_rank == 0) unlink(weight_file_name);
2578 }
2579
2581 }
2582
2583 { // test writing empty stencil data to file
2584
2585 struct yac_interp_weights * weights =
2587 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2588
2589 struct remote_points tgts = {
2590 .data = NULL,
2591 .count = 0,
2592 };
2593 yac_interp_weights_add_direct(weights, &tgts, NULL);
2594
2595 // check writing and reading
2596 {
2597 char const * weight_file_name =
2598 "test_interp_weights_parallel_empty.nc";
2599 // write weights to file
2601 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2603
2604 MPI_Barrier(MPI_COMM_WORLD);
2605
2606 if (comm_rank == 0) unlink(weight_file_name);
2607 }
2608
2610 }
2611
2612 { // test writing empty stencil data to file
2613
2614 struct yac_interp_weights * weights =
2616 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2617
2618 struct remote_points tgts = {
2619 .data = NULL,
2620 .count = 0,
2621 };
2622 size_t num_src_per_tgt[] = {0};
2623 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, NULL);
2624
2625 // check writing and reading
2626 {
2627 char const * weight_file_name =
2628 "test_interp_weights_parallel_empty.nc";
2629 // write weights to file
2631 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2633
2634 MPI_Barrier(MPI_COMM_WORLD);
2635
2636 if (comm_rank == 0) unlink(weight_file_name);
2637 }
2638
2640 }
2641
2642 { // test writing empty stencil data to file
2643
2644 struct yac_interp_weights * weights =
2646 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2647
2648 struct remote_point remote_tgt_points[] =
2649 {{.global_id = 0,
2650 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
2651 struct remote_points tgts = {
2652 .data = remote_tgt_points,
2653 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2654 };
2655 size_t num_src_per_tgt[] = {0};
2656 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, NULL);
2657
2658 // check writing and reading
2659 {
2660 char const * weight_file_name =
2661 "test_interp_weights_parallel_empty.nc";
2662 // write weights to file
2664 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2666
2667 MPI_Barrier(MPI_COMM_WORLD);
2668
2669 if (comm_rank == 0) unlink(weight_file_name);
2670 }
2671
2673 }
2674
2675 { // test writing empty stencil data to file
2676
2677 struct yac_interp_weights * weights =
2679 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2680
2681 struct remote_point remote_tgt_points[] =
2682 {{.global_id = 0,
2683 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
2684 struct remote_points tgts = {
2685 .data = remote_tgt_points,
2686 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2687 };
2688 size_t num_src_per_tgt[] = {0};
2689 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, NULL, NULL);
2690
2691 // check writing and reading
2692 {
2693 char const * weight_file_name =
2694 "test_interp_weights_parallel_empty.nc";
2695 // write weights to file
2697 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2699
2700 MPI_Barrier(MPI_COMM_WORLD);
2701
2702 if (comm_rank == 0) unlink(weight_file_name);
2703 }
2704
2706 }
2707
2708 { // test writing empty stencil data to file
2709
2710 struct yac_interp_weights * weights =
2712 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2713
2714 struct remote_points tgts = {
2715 .data = NULL,
2716 .count = 0,
2717 };
2718 size_t num_src_per_tgt[] = {0};
2719 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, NULL, NULL);
2720
2721 // check writing and reading
2722 {
2723 char const * weight_file_name =
2724 "test_interp_weights_parallel_empty.nc";
2725 // write weights to file
2727 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2729
2730 MPI_Barrier(MPI_COMM_WORLD);
2731
2732 if (comm_rank == 0) unlink(weight_file_name);
2733 }
2734
2736 }
2737
2738 { // checking for a bug that occured then writing weights to file
2739
2740 struct yac_interp_weights * weights =
2742 MPI_COMM_WORLD, YAC_LOC_CELL,
2744
2745 if (comm_rank == 0) {
2746
2747 {
2748 struct remote_point tgt_points[] =
2749 {{.global_id = 4,
2750 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}},
2751 {.global_id = 5,
2752 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}}};
2753 struct remote_points tgts = {
2754 .data = tgt_points,
2755 .count = sizeof(tgt_points) / sizeof(tgt_points[0]),
2756 };
2757 struct remote_point srcs[] =
2758 {{.global_id = 4,
2759 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 4}}},
2760 {.global_id = 5,
2761 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 5}}}};
2762 yac_interp_weights_add_direct(weights, &tgts, srcs);
2763 }
2764
2765 {
2766 struct remote_point tgt_points[] =
2767 {{.global_id = 0,
2768 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2769 {.global_id = 1,
2770 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
2771 {.global_id = 2,
2772 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2773 {.global_id = 3,
2774 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
2775 {.global_id = 6,
2776 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 6}}},
2777 {.global_id = 7,
2778 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 7}}},
2779 {.global_id = 8,
2780 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 8}}},
2781 {.global_id = 9,
2782 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 9}}}};
2783 struct remote_points tgts = {
2784 .data = tgt_points,
2785 .count = sizeof(tgt_points) / sizeof(tgt_points[0]),
2786 };
2787 yac_interp_weights_add_fixed(weights, &tgts, -1.0);
2788 }
2789 }
2790
2791 char const * weight_file_name =
2792 "test_interp_weights_parallel_bug_check.nc";
2793 // write weights to file
2795 weights, weight_file_name, grid_names[0], grid_names[1], 0, 0,
2797 MPI_Barrier(MPI_COMM_WORLD);
2798 if (comm_rank == 0) unlink(weight_file_name);
2799
2801 }
2802
2803 {// check for a bug where weights were deleted based on a absolute weight
2804 // tolerance
2805 // on rank 0:
2806 // tgt global_id: 0
2807 // src_field 0:
2808 // 0.25 * src global_id 0
2809 // 0.25 * src global_id 1
2810 // 0.25 * src global_id 2
2811 // 0.25 * src global_id 3
2812 // tgt global_id: 1
2813 // src_field 0:
2814 // 0.25 * src global_id 0
2815 // 1e-16 * src global_id 1 // should be removed
2816 // 0.25 * src global_id 2
2817 // 1e-16 * src global_id 3 // should be removed
2818 // tgt global_id: 2
2819 // src_field 0:
2820 // 0.25 * src global_id 0
2821 // 0.25 * src global_id 1
2822 // 0.25 * src global_id 2
2823 // 0.25 * src global_id 3
2824 // tgt global_id: 3
2825 // src_field 0:
2826 // 1e-16 * src global_id 0
2827 // 1e-16 * src global_id 1
2828 // 1e-16 * src global_id 2
2829 // 1e-16 * src global_id 3
2830
2831 struct yac_interp_weights * weights =
2833 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2834
2835 if (comm_rank == 0) {
2836 struct remote_point remote_tgt_points[] =
2837 {{.global_id = 0,
2838 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2839 {.global_id = 1,
2840 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
2841 {.global_id = 2,
2842 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2843 {.global_id = 3,
2844 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
2845 struct remote_points tgts = {
2846 .data = remote_tgt_points,
2847 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2848 };
2849 size_t num_src_per_tgt[] = {4, 4, 4, 4};
2850 struct remote_point srcs[] =
2851 {{.global_id = 0,
2852 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2853 {.global_id = 1,
2854 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
2855 {.global_id = 2,
2856 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2857 {.global_id = 3,
2858 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
2859 {.global_id = 0,
2860 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2861 {.global_id = 1,
2862 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
2863 {.global_id = 2,
2864 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2865 {.global_id = 3,
2866 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
2867 {.global_id = 0,
2868 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2869 {.global_id = 1,
2870 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
2871 {.global_id = 2,
2872 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2873 {.global_id = 3,
2874 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}},
2875 {.global_id = 0,
2876 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2877 {.global_id = 1,
2878 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}},
2879 {.global_id = 2,
2880 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}},
2881 {.global_id = 3,
2882 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 3}}}};
2883 double w[] = {0.25, 0.25, 0.25, 0.25,
2884 0.25, 1.e-16, 0.25, 1.e-16,
2885 0.25, 0.25, 0.25, 0.25,
2886 1.e-16, 1.e-16, 1.e-16, 1.e-16};
2887 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
2888 }
2889
2890 struct yac_interpolation * interpolation =
2892 weights, YAC_MAPPING_ON_SRC, 1,
2893 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
2894
2895 if (comm_rank == 0) {
2896 double src_field_data[] = {1.0, 2.0, 3.0, 4.0};
2897 double tgt_field_data[] = {-1.0, -1.0, -1.0, -1.0};
2898 double ref_tgt_field_data[] = {
2899 0.25 * (1.0 + 2.0 + 3.0 + 4.0), // target 0: all weights 0.25
2900 0.25 * (1.0 + 3.0), // target 1: only weights 0.25 for src 0 and 2
2901 0.25 * (1.0 + 2.0 + 3.0 + 4.0), // target 2: all weights 0.25
2902 1e-16 * (1.0 + 2.0 + 3.0 + 4.0) // target 3: all weights 1e-16
2903 };
2904 double * src_field = src_field_data;
2905 double * tgt_field = tgt_field_data;
2906 double ** src_fields = &src_field;
2907
2908 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
2909
2910 for (size_t i = 0; i < 4; ++i) {
2911 if (fabs(tgt_field[i] - ref_tgt_field_data[i]) > TOL)
2912 PUT_ERR("ERROR: weights incorrectly deleted based on absolute tolerance");
2913 }
2914 } else {
2915 yac_interpolation_execute(interpolation, NULL, NULL);
2916 }
2917
2918 yac_interpolation_delete(interpolation);
2920 }
2921
2922 { // test NaN fixed value write/read roundtrip to test its support with weight files
2923 // on rank 0:
2924 // tgt global_id: 0 -> fixed NaN value
2925 // tgt global_id: 1 -> fixed NaN value
2926
2927 char const * weight_file_name =
2928 "test_interp_weights_parallel_nan_fixed.nc";
2929 char const * src_grid_name = "src_grid";
2930 char const * tgt_grid_name = "tgt_grid";
2931
2932 struct yac_interp_weights * weights =
2934 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
2935
2936 if (comm_rank == 0) {
2937 struct remote_point remote_tgt_points[] =
2938 {{.global_id = 0,
2939 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}},
2940 {.global_id = 1,
2941 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 1}}}};
2942 struct remote_points tgts = {
2943 .data = remote_tgt_points,
2944 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
2945 };
2946 yac_interp_weights_add_fixed(weights, &tgts, NAN);
2947 } else {
2948 struct remote_points tgts = {.data = NULL, .count = 0};
2949 yac_interp_weights_add_fixed(weights, &tgts, NAN);
2950 }
2951
2952 // write weights to file
2955 0, 0, YAC_WEIGHT_FILE_ERROR);
2956
2958
2959 // read weights back from file
2960 struct yac_interp_weights * weights_from_file;
2961
2962 {
2963 struct yac_basic_grid_data tgt_grid_data =
2964 utest_generate_dummy_grid_data(
2965 (comm_rank == 0)?2:0, 2, 0);
2966
2967 struct yac_basic_grid * src_grid =
2969 struct yac_basic_grid * tgt_grid =
2970 yac_basic_grid_new(tgt_grid_name, tgt_grid_data);
2971
2972 struct yac_dist_grid_pair * grid_pair =
2973 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
2974
2975 struct yac_interp_field src_fields[] =
2976 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX,
2977 .masks_idx = SIZE_MAX}};
2978 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
2980 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX,
2981 .masks_idx = SIZE_MAX};
2982
2983 struct yac_interp_grid * interp_grid =
2987
2988 struct interp_method * method_stack[2] = {
2992 weights_from_file =
2993 yac_interp_method_do_search(method_stack, interp_grid);
2994 yac_interp_method_delete(method_stack);
2995
2996 yac_interp_grid_delete(interp_grid);
2997 yac_dist_grid_pair_delete(grid_pair);
2998 yac_basic_grid_delete(tgt_grid);
2999 yac_basic_grid_delete(src_grid);
3000 }
3001
3002 // execute interpolation and check that NaN is received on target side
3003 {
3004 struct yac_interpolation * interpolation =
3006 weights_from_file, YAC_MAPPING_ON_SRC, 1,
3007 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
3008
3009 double tgt_field_data[] = {0.0, 0.0};
3010 double * tgt_field = tgt_field_data;
3011
3012 if (comm_rank == 0) {
3013 yac_interpolation_execute(interpolation, NULL, &tgt_field);
3014 for (size_t i = 0; i < 2; ++i)
3015 if (!isnan(tgt_field_data[i]))
3016 PUT_ERR("wrong NaN fixed value result");
3017 } else {
3018 yac_interpolation_execute(interpolation, NULL, NULL);
3019 }
3020
3021 yac_interpolation_delete(interpolation);
3022 }
3023
3024 yac_interp_weights_delete(weights_from_file);
3025 if (comm_rank == 0) unlink(weight_file_name);
3026 }
3027
3028 { // check that targets with zero sources are skipped for sum and wsum
3029 struct yac_interp_weights * weights =
3031 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
3032
3033 struct remote_point tgts_data[2] = {{0}};
3034 struct remote_points tgts = {.data = tgts_data, .count = 2};
3035 for (size_t i = 0; i < tgts.count; ++i) {
3036 tgts.data[i].global_id = (yac_int)(100 + i);
3037 tgts.data[i].data.count = 1;
3038 tgts.data[i].data.data.single.rank = comm_rank;
3039 tgts.data[i].data.data.single.orig_pos = i;
3040 }
3041
3042 size_t num_src_per_tgt[2] = {0, 1};
3043 struct remote_point srcs[1] = {{
3044 .global_id = 200,
3045 .data = {
3046 .count = 1, .data = {.single = {.rank = comm_rank, .orig_pos = 0}}}
3047 }};
3048 double w[1] = {2.0};
3049
3050 yac_interp_weights_add_wsum(weights, &tgts, num_src_per_tgt, srcs, w);
3051
3052 size_t interp_count = yac_interp_weights_get_interp_count(weights);
3053 if (interp_count != 1)
3054 PUT_ERR("ERROR(yac_interp_weights_add_wsum): "
3055 "unexpected number of generated stencils");
3056
3057 yac_int * interp_tgts = yac_interp_weights_get_interp_tgt(weights);
3058 if (interp_tgts[0] != tgts.data[1].global_id)
3059 PUT_ERR("ERROR(yac_interp_weights_add_wsum): "
3060 "target with zero sources was not skipped");
3061
3062 free(interp_tgts);
3064 }
3065
3066 { // test handling of existing weight file
3067 // (the last test is expected to call abort, so no further tests afterwards)
3068
3069 char const * src_grid_name = "src_grid";
3070 char const * tgt_grid_name = "tgt_grid";
3071
3072 struct yac_interp_weights * weights_existing =
3074 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
3075 {
3076 struct remote_point remote_tgt_points[] =
3077 {{.global_id = 0,
3078 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
3079 struct remote_points tgts = {
3080 .data = remote_tgt_points,
3081 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
3082 };
3083 double fixed_value = 1.0;
3084 yac_interp_weights_add_fixed(weights_existing, &tgts, fixed_value);
3085 }
3086
3087 struct yac_interp_weights * weights =
3089 MPI_COMM_WORLD, YAC_LOC_CELL, (enum yac_location[]){YAC_LOC_CELL}, 1);
3090 {
3091 struct remote_point remote_tgt_points[] =
3092 {{.global_id = 0,
3093 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 0}}}};
3094 struct remote_points tgts = {
3095 .data = remote_tgt_points,
3096 .count = sizeof(remote_tgt_points) / sizeof(remote_tgt_points[0]),
3097 };
3098 size_t num_src_per_tgt[] = {1};
3099 struct remote_point srcs[] =
3100 {{.global_id = 0,
3101 .data = {.count = 1, .data.single = {.rank = 0, .orig_pos = 2}}}};
3102 yac_interp_weights_add_sum(weights, &tgts, num_src_per_tgt, srcs);
3103 }
3104
3105 for (int with_existing_weight_file = 0; with_existing_weight_file < 2;
3106 ++with_existing_weight_file) {
3107
3108 // the last test should be "error on existing file"
3113 enum {NUM_ON_EXISTING = sizeof(on_existing) / sizeof(on_existing[0])};
3114
3115 for (size_t on_existing_idx = 0; on_existing_idx < NUM_ON_EXISTING;
3116 ++on_existing_idx) {
3117
3118 if (with_existing_weight_file)
3120 weights_existing, weight_file_name_on_existing,
3122
3123 enum yac_weight_file_on_existing curr_on_existing =
3124 on_existing[on_existing_idx];
3125
3126 // in case we test for an error for an existing weight file,
3127 // we expect the custom abort handler to be called
3128 if ((curr_on_existing == YAC_WEIGHT_FILE_ERROR) &&
3129 with_existing_weight_file)
3131 else
3133
3134 MPI_Barrier(MPI_COMM_WORLD);
3137 0, 0, curr_on_existing);
3138
3139 int contains_links = 0;
3140 int contains_fixed = 0;
3141 if (!((curr_on_existing == YAC_WEIGHT_FILE_ERROR) &&
3142 with_existing_weight_file))
3143 utest_get_basic_weight_file_info(
3144 weight_file_name_on_existing, &contains_links, &contains_fixed);
3145
3146 switch(curr_on_existing) {
3148 if (with_existing_weight_file) {
3149 // the orig weight file only contains a fixed value but not links
3150 if (!contains_fixed || contains_links)
3151 PUT_ERR("error in yac_interp_weights_write_to_file");
3152 } else {
3153 if (contains_fixed || !contains_links)
3154 PUT_ERR("error in yac_interp_weights_write_to_file");
3155 }
3156 break;
3158 // the new weight file only contains links but no fixed value
3159 if (contains_fixed || !contains_links)
3160 PUT_ERR("error in yac_interp_weights_write_to_file");
3161 break;
3163 // if there was no existing weight file
3164 if (!with_existing_weight_file) {
3165 // the new weight file only contains links but no fixed value
3166 if (contains_fixed || !contains_links)
3167 PUT_ERR("error in yac_interp_weights_write_to_file");
3168 } else {
3169
3170 // at least on process should have called the custom abort handler
3171 int abort_handler_was_called = 0;
3172 MPI_Allreduce(
3173 MPI_IN_PLACE, &abort_handler_was_called, 1,
3174 MPI_INT, MPI_MAX, MPI_COMM_WORLD);
3175
3176 if (!abort_handler_was_called)
3177 PUT_ERR("error in yac_interp_weights_write_to_file");
3178
3179 MPI_Barrier(MPI_COMM_WORLD);
3180 if (comm_rank == 0) unlink(weight_file_name_on_existing);
3181
3182 xt_finalize();
3183 MPI_Finalize();
3184 exit(TEST_EXIT_CODE);
3185 }
3186 break;
3187 default:
3188 PUT_ERR("internal test error");
3189 break;
3190 } // switch(curr_on_existing)
3191
3192 MPI_Barrier(MPI_COMM_WORLD);
3193 if (comm_rank == 0) unlink(weight_file_name_on_existing);
3194 } // on_existing_idx
3195 } // with_existing_weight_file
3196 }
3197
3198 // The test above is expected to call the abort handler, hence the code
3199 // should never reach this point. New tests should be added above.
3200
3201 PUT_ERR("internal test error");
3202 xt_finalize();
3203 MPI_Finalize();
3204
3205 return TEST_EXIT_CODE;
3206}
3207
3208static int utest_check_fixed_results_(
3209 struct yac_basic_grid_data * grid, int is_src,
3210 struct yac_interpolation * interpolation,
3211 double * field_data) {
3212
3213 int err_count = 0;
3214
3215 if (is_src)
3216 for (size_t j = 0; j < grid->num_cells; ++j)
3217 field_data[j] = (double)1;
3218 else
3219 for (size_t j = 0; j < grid->num_cells; ++j)
3220 field_data[j] = (double)-3;
3221
3222 double ** src_fields, * tgt_field;
3223 if (is_src) {
3224 src_fields = &field_data;
3225 tgt_field = NULL;
3226 } else {
3227 src_fields = NULL;
3228 tgt_field = field_data;
3229 }
3230
3231 yac_interpolation_execute(interpolation, &src_fields, &tgt_field);
3232
3233 if (!is_src) {
3234 for (size_t j = 0; j < grid->num_cells; ++j) {
3235 if (grid->core_cell_mask[j]) {
3236 if (grid->cell_ids[j] & 1) {
3237 if (tgt_field[j] != -1.0) ++err_count;
3238 } else {
3239 if (tgt_field[j] != -2.0) ++err_count;
3240 }
3241 } else {
3242 if (tgt_field[j] != -3.0) ++err_count;
3243 }
3244 }
3245 }
3246
3247 return err_count;
3248}
3249
3250static double ** allocate_src_data_raw(
3252
3253 double ** src_data_raw;
3254 static double dummy;
3255 int with_frac_mask =
3257 src_data_raw =
3258 xmalloc(
3259 (1 + with_frac_mask) * collection_size *
3260 interp_weights_data.num_src_fields * sizeof(*src_data_raw));
3261 {
3262 size_t k = 0;
3263 for (size_t i = 0; i < collection_size; ++i) {
3264 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k) {
3265 src_data_raw[k] =
3266 interp_weights_data.src_field_buffer_size[j]?
3267 xmalloc(
3268 interp_weights_data.src_field_buffer_size[j] *
3269 sizeof(*(src_data_raw[k]))):&dummy;
3270 }
3271 }
3272 if (with_frac_mask) {
3273 for (size_t i = 0; i < collection_size; ++i) {
3274 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k) {
3275 src_data_raw[k] =
3276 interp_weights_data.src_field_buffer_size[j]?
3277 xmalloc(
3278 interp_weights_data.src_field_buffer_size[j] *
3279 sizeof(*(src_data_raw[k]))):&dummy;
3280 }
3281 }
3282 }
3283 }
3284 return src_data_raw;
3285}
3286
3289 double ** src_data_raw) {
3290
3291 int with_frac_mask =
3293 size_t k = 0;
3294 for (size_t i = 0; i < collection_size; ++i)
3295 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k)
3296 if (interp_weights_data.src_field_buffer_size[j])
3297 free(src_data_raw[k]);
3298 if (with_frac_mask)
3299 for (size_t i = 0; i < collection_size; ++i)
3300 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k)
3301 if (interp_weights_data.src_field_buffer_size[j])
3302 free(src_data_raw[k]);
3303 free(src_data_raw);
3304}
3305
3306#if defined __NVCOMPILER && (__NVCOMPILER_MAJOR__ <= 24)
3307// NVHPC has problems compiling this routine if it is inlined
3308#pragma noinline
3309#endif
3312 double ** src_data_raw, double ** tgt_field) {
3313
3314#define FRAC_MASK_TOL (1e-12)
3315
3316 int with_frac_mask =
3318
3319 // apply fixed values
3320 for (size_t i = 0; i < collection_size; ++i) {
3321 for (size_t j = 0, l = 0; j < interp_weights_data.num_fixed_values; ++j) {
3322 for (size_t k = 0; k < interp_weights_data.num_tgt_per_fixed_value[j];
3323 ++k, ++l) {
3324 tgt_field[i][interp_weights_data.tgt_idx_fixed[l]] =
3326 }
3327 }
3328 }
3329
3330 // apply weights
3331 if (with_frac_mask) {
3332 for (size_t i = 0; i < collection_size; ++i) {
3333 size_t wgt_offset = 0;
3334 for (size_t j = 0; j < interp_weights_data.num_wgt_tgt; ++j) {
3335 double tgt_value = 0.0;
3336 double frac_weight_sum = 0.0;
3337 double weight_sum = 0.0;
3338#if defined __NVCOMPILER && (__NVCOMPILER_MAJOR__ <= 24)
3339// NVHPC has problems compiling the following code
3340#pragma novector
3341#endif
3342 for (size_t k = 0; k < interp_weights_data.num_src_per_tgt[j];
3343 ++k, ++wgt_offset) {
3344 tgt_value +=
3345 src_data_raw
3348 [interp_weights_data.src_idx[wgt_offset]] *
3349 interp_weights_data.weights[wgt_offset];
3350 frac_weight_sum +=
3351 src_data_raw
3355 [interp_weights_data.src_idx[wgt_offset]] *
3356 interp_weights_data.weights[wgt_offset];
3357 weight_sum += interp_weights_data.weights[wgt_offset];
3358 }
3359#if defined __NVCOMPILER && (__NVCOMPILER_MAJOR__ <= 24)
3360#pragma vector
3361#endif
3362 tgt_field[i][interp_weights_data.wgt_tgt_idx[j]] =
3363 (fabs(frac_weight_sum) > FRAC_MASK_TOL)?
3365 (tgt_value / frac_weight_sum * weight_sum) +
3368 }
3369 }
3370 } else {
3371 for (size_t i = 0; i < collection_size; ++i) {
3372 size_t wgt_offset = 0;
3373 for (size_t j = 0; j < interp_weights_data.num_wgt_tgt; ++j) {
3374 double tgt_value = 0.0;
3375#if defined __NVCOMPILER && (__NVCOMPILER_MAJOR__ <= 24)
3376// NVHPC has problems compiling the following code
3377#pragma novector
3378#endif
3379 for (size_t k = 0; k < interp_weights_data.num_src_per_tgt[j];
3380 ++k, ++wgt_offset) {
3381 tgt_value +=
3382 src_data_raw
3385 [interp_weights_data.src_idx[wgt_offset]] *
3386 interp_weights_data.weights[wgt_offset];
3387 }
3388#if defined __NVCOMPILER && (__NVCOMPILER_MAJOR__ <= 24)
3389#pragma vector
3390#endif
3391 tgt_field[i][interp_weights_data.wgt_tgt_idx[j]] =
3394 }
3395 }
3396 }
3397#undef FRAC_MASK_TOL
3398}
3399
3400static void utest_interpolation_execute_frac_raw(
3401 struct yac_interpolation_exchange * interpolation_exchange,
3403 size_t collection_size, double *** src_fields, double *** src_frac_masks,
3404 double ** tgt_field) {
3405
3406 int with_frac_mask =
3408
3409 double const * src_fields_2d[
3410 (1 + with_frac_mask) * collection_size *
3412 double dummy;
3413 {
3414 size_t k = 0;
3415 for (size_t i = 0; i < collection_size; ++i)
3416 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k)
3417 src_fields_2d[k] = src_fields?src_fields[i][j]:&dummy;
3418 if (with_frac_mask)
3419 for (size_t i = 0; i < collection_size; ++i)
3420 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k)
3421 src_fields_2d[k] = src_frac_masks?src_frac_masks[i][j]:&dummy;
3422 }
3423
3424 // allocate receive buffer
3425 double ** src_data_raw =
3427
3428 // execute interpolation
3430 interpolation_exchange, src_fields_2d, src_data_raw,
3431 "utest_interpolation_execute_raw");
3432
3433 // compute target field
3435 collection_size, interp_weights_data, src_data_raw, tgt_field);
3436
3437 // free receive buffer
3439}
3440
3441static void utest_interpolation_execute_raw(
3442 struct yac_interpolation_exchange * interpolation_exchange,
3444 size_t collection_size, double *** src_fields, double ** tgt_field) {
3445
3446 utest_interpolation_execute_frac_raw(
3447 interpolation_exchange, interp_weights_data, collection_size,
3448 src_fields, NULL, tgt_field);
3449}
3450
3452 struct yac_interpolation_exchange * interpolation_exchange,
3454 size_t collection_size, double *** src_fields, double *** src_frac_masks) {
3455
3456 int with_frac_mask =
3458
3459 double const * src_fields_2d[
3460 (1 + with_frac_mask) * collection_size * interp_weights_data.num_src_fields];
3461 static double dummy;
3462 {
3463 size_t k = 0;
3464 for (size_t i = 0; i < collection_size; ++i)
3465 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k)
3466 src_fields_2d[k] = src_fields?src_fields[i][j]:&dummy;
3467 if (with_frac_mask)
3468 for (size_t i = 0; i < collection_size; ++i)
3469 for (size_t j = 0; j < interp_weights_data.num_src_fields; ++j, ++k)
3470 src_fields_2d[k] = src_frac_masks?src_frac_masks[i][j]:&dummy;
3471 }
3472
3473 // send source data
3475 interpolation_exchange, src_fields_2d, "interpolation_put_frac_raw");
3476}
3477
3479 struct yac_interpolation_exchange * interpolation_exchange,
3481 size_t collection_size, double *** src_fields) {
3482
3484 interpolation_exchange, interp_weights_data, collection_size,
3485 src_fields, NULL);
3486}
3487
3489 struct yac_interpolation_exchange * interpolation_exchange,
3491 size_t collection_size, double ** tgt_field) {
3492
3493 // allocate receive buffer
3494 double ** src_data_raw =
3496
3497 // receive source data
3499 interpolation_exchange, src_data_raw, "interpolation_get_raw");
3500
3501 // compute target field
3503 collection_size, interp_weights_data, src_data_raw, tgt_field);
3504
3505 // free receive buffer
3507}
3508
3509static int utest_check_fixed_results_raw_(
3510 struct yac_basic_grid_data * grid, int is_src,
3511 struct yac_interpolation_exchange * interpolation_exchange,
3512 double * field_data, struct yac_interp_weights_data interp_weights_data) {
3513
3514 int err_count = 0;
3515
3516 if (is_src)
3517 for (size_t j = 0; j < grid->num_cells; ++j)
3518 field_data[j] = (double)1;
3519 else
3520 for (size_t j = 0; j < grid->num_cells; ++j)
3521 field_data[j] = (double)-3;
3522
3523 double ** src_fields, * tgt_field;
3524 if (is_src) {
3525 src_fields = &field_data;
3526 tgt_field = NULL;
3527 } else {
3528 src_fields = NULL;
3529 tgt_field = field_data;
3530 }
3531
3532 size_t collection_size = 1;
3533 utest_interpolation_execute_raw(
3534 interpolation_exchange, interp_weights_data, collection_size,
3535 &src_fields, &tgt_field);
3536
3537 if (!is_src) {
3538 for (size_t j = 0; j < grid->num_cells; ++j) {
3539 if (grid->core_cell_mask[j]) {
3540 if (grid->cell_ids[j] & 1) {
3541 if (tgt_field[j] != -1.0) ++err_count;
3542 } else {
3543 if (tgt_field[j] != -2.0) ++err_count;
3544 }
3545 } else {
3546 if (tgt_field[j] != -3.0) ++err_count;
3547 }
3548 }
3549 }
3550
3551 return err_count;
3552}
3553
3554static int utest_check_fixed_results(
3555 struct yac_basic_grid_data * grid, int is_src,
3556 struct yac_interp_weights * weights,
3557 enum yac_interp_weights_reorder_type reorder_type,
3558 double * field_data) {
3559
3560 int err_count = 0;
3561
3562 size_t const collection_size = 1;
3563 double const frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE;
3564 double const scaling_factor = 1.0;
3565 double const scaling_summand = 0.0;
3566 char const * yaxt_exchanger_name = NULL;
3567 {
3568 struct yac_interpolation * interpolation =
3570 weights, reorder_type, collection_size,
3571 frac_mask_fallback_value, scaling_factor, scaling_summand,
3572 yaxt_exchanger_name, 1, 1);
3573 struct yac_interpolation * interpolation_cpy =
3574 yac_interpolation_copy(interpolation);
3575
3576 err_count +=
3577 utest_check_fixed_results_(grid, is_src, interpolation, field_data) +
3578 utest_check_fixed_results_(grid, is_src, interpolation_cpy, field_data);
3579
3580 yac_interpolation_delete(interpolation_cpy);
3581 yac_interpolation_delete(interpolation);
3582 }
3583
3584 {
3585 struct yac_interpolation_exchange * interpolation_exchange;
3589 scaling_factor, scaling_summand, yaxt_exchanger_name,
3590 &interpolation_exchange, &interp_weights_data, 1, 1);
3591
3592 err_count +=
3593 utest_check_fixed_results_raw_(
3594 grid, is_src, interpolation_exchange, field_data, interp_weights_data);
3595
3597 interpolation_exchange, "utest_check_fixed_results");
3599 }
3600
3601 return err_count;
3602}
3603
3604static int utest_check_direct_results(
3605 struct yac_basic_grid_data * grid, int is_src,
3606 struct yac_interp_weights * weights,
3607 enum yac_interp_weights_reorder_type reorder_type, size_t collection_size,
3608 double *** src_fields, double *** src_frac_masks, double ** tgt_field) {
3609
3610 int err_count = 0;
3611
3612 { // test without fractional mask
3613
3615 double const scaling_factor = 1.0;
3616 double const scaling_summand = 0.0;
3617 char const * yaxt_exchanger_name = NULL;
3618
3619 {
3621 interpolations[0] =
3623 weights, reorder_type, collection_size,
3624 frac_mask_fallback_value, scaling_factor, scaling_summand,
3625 yaxt_exchanger_name, 1, 1);
3627
3628 for (int interp_idx = 0; interp_idx < 2; ++interp_idx) {
3629
3630 if (!is_src)
3631 for (size_t collection_idx = 0; collection_idx < collection_size;
3632 ++collection_idx)
3633 for (size_t k = 0; k < grid->num_cells; ++k)
3634 tgt_field[collection_idx][k] = -1;
3635
3637 interpolations[interp_idx], src_fields, tgt_field);
3638
3639 if (!is_src) {
3640 for (size_t collection_idx = 0; collection_idx < collection_size;
3641 ++collection_idx) {
3642 for (size_t j = 0; j < grid->num_cells; ++j) {
3643 if (grid->core_cell_mask[j]) {
3644 if (tgt_field[collection_idx][j] !=
3645 (double)(grid->cell_ids[j])) err_count++;
3646 } else {
3647 if (tgt_field[collection_idx][j] != -1.0) err_count++;
3648 }
3649 }
3650 }
3651 }
3652
3653 if (is_src) {
3654 yac_interpolation_execute_put(interpolations[interp_idx], src_fields);
3655 } else {
3656 for (size_t collection_idx = 0; collection_idx < collection_size;
3657 ++collection_idx)
3658 for (size_t k = 0; k < grid->num_cells; ++k)
3659 tgt_field[collection_idx][k] = -1;
3660 yac_interpolation_execute_get(interpolations[interp_idx], tgt_field);
3661 for (size_t collection_idx = 0; collection_idx < collection_size;
3662 ++collection_idx) {
3663 for (size_t j = 0; j < grid->num_cells; ++j) {
3664 if (grid->core_cell_mask[j]) {
3665 if (tgt_field[collection_idx][j] !=
3666 (double)(grid->cell_ids[j])) err_count++;
3667 } else {
3668 if (tgt_field[collection_idx][j] != -1.0) err_count++;
3669 }
3670 }
3671 }
3672 }
3674 }
3675 }
3676
3677 { // test raw interpolation
3678 struct yac_interpolation_exchange * interpolation_exchange;
3682 scaling_factor, scaling_summand, yaxt_exchanger_name,
3683 &interpolation_exchange, &interp_weights_data, 1, 1);
3684
3685 { // exchange
3686
3687 for (int exchange_type = 0; exchange_type < 2; ++exchange_type) {
3688
3689 if (!is_src)
3690 for (size_t collection_idx = 0; collection_idx < collection_size;
3691 ++collection_idx)
3692 for (size_t k = 0; k < grid->num_cells; ++k)
3693 tgt_field[collection_idx][k] = -1;
3694
3695 if (exchange_type) {
3696 utest_interpolation_execute_raw(
3697 interpolation_exchange, interp_weights_data, collection_size,
3698 src_fields, tgt_field);
3699 } else {
3700 if (is_src)
3702 interpolation_exchange, interp_weights_data, collection_size,
3703 src_fields);
3704 else
3706 interpolation_exchange, interp_weights_data, collection_size,
3707 tgt_field);
3708 }
3709
3710 if (!is_src) {
3711 for (size_t collection_idx = 0; collection_idx < collection_size;
3712 ++collection_idx) {
3713 for (size_t j = 0; j < grid->num_cells; ++j) {
3714 if (grid->core_cell_mask[j]) {
3715 if (tgt_field[collection_idx][j] !=
3716 (double)(grid->cell_ids[j])) err_count++;
3717 } else {
3718 if (tgt_field[collection_idx][j] != -1.0) err_count++;
3719 }
3720 }
3721 }
3722 }
3723 }
3724 }
3727 interpolation_exchange, "utest_check_direct_results");
3728 }
3729 }
3730
3731 { // test with fractional mask
3732
3733 double frac_mask_fallback_value = strtod("Inf", NULL);
3734 double scaling_factor = 1.0;
3735 double scaling_summand = 0.0;
3736 char const * yaxt_exchanger_name = NULL;
3737
3739 interpolations[0] =
3741 weights, reorder_type, collection_size, frac_mask_fallback_value,
3742 scaling_factor, scaling_summand, yaxt_exchanger_name, 1, 1);
3744
3745 for (int interp_idx = 0; interp_idx < 2; ++interp_idx) {
3746
3747 if (!is_src)
3748 for (size_t collection_idx = 0; collection_idx < collection_size;
3749 ++collection_idx)
3750 for (size_t k = 0; k < grid->num_cells; ++k)
3751 tgt_field[collection_idx][k] = -1;
3752
3754 interpolations[interp_idx], src_fields, src_frac_masks, tgt_field);
3755
3756 if (!is_src) {
3757 for (size_t collection_idx = 0; collection_idx < collection_size;
3758 ++collection_idx) {
3759 for (size_t j = 0; j < grid->num_cells; ++j) {
3760 if (grid->core_cell_mask[j]) {
3761 if (grid->cell_ids[j]&1) {
3762 if (tgt_field[collection_idx][j] !=
3763 (double)(grid->cell_ids[j])) err_count++;
3764 } else {
3765 if (!isinf(tgt_field[collection_idx][j])) err_count++;
3766 }
3767 } else {
3768 if (tgt_field[collection_idx][j] != -1.0) err_count++;
3769 }
3770 }
3771 }
3772 }
3773
3774 if (is_src) {
3776 interpolations[interp_idx], src_fields, src_frac_masks);
3777 } else {
3778 for (size_t collection_idx = 0; collection_idx < collection_size;
3779 ++collection_idx)
3780 for (size_t k = 0; k < grid->num_cells; ++k)
3781 tgt_field[collection_idx][k] = -1;
3782 yac_interpolation_execute_get(interpolations[interp_idx], tgt_field);
3783 for (size_t collection_idx = 0; collection_idx < collection_size;
3784 ++collection_idx) {
3785 for (size_t j = 0; j < grid->num_cells; ++j) {
3786 if (grid->core_cell_mask[j]) {
3787 if (grid->cell_ids[j]&1) {
3788 if (tgt_field[collection_idx][j] !=
3789 (double)(grid->cell_ids[j])) err_count++;
3790 } else {
3791 if (!isinf(tgt_field[collection_idx][j])) err_count++;
3792 }
3793 } else {
3794 if (tgt_field[collection_idx][j] != -1.0) err_count++;
3795 }
3796 }
3797 }
3798 }
3800 }
3801
3802 { // test raw interpolation
3803 struct yac_interpolation_exchange * interpolation_exchange;
3807 scaling_factor, scaling_summand, yaxt_exchanger_name,
3808 &interpolation_exchange, &interp_weights_data, 1, 1);
3809
3810 { // exchange
3811
3812 for (int exchange_type = 0; exchange_type < 2; ++exchange_type) {
3813
3814 if (!is_src)
3815 for (size_t collection_idx = 0; collection_idx < collection_size;
3816 ++collection_idx)
3817 for (size_t k = 0; k < grid->num_cells; ++k)
3818 tgt_field[collection_idx][k] = -1;
3819
3820 if (exchange_type) {
3821 utest_interpolation_execute_frac_raw(
3822 interpolation_exchange, interp_weights_data, collection_size,
3823 src_fields, src_frac_masks, tgt_field);
3824 } else {
3825 if (is_src)
3827 interpolation_exchange, interp_weights_data, collection_size,
3828 src_fields, src_frac_masks);
3829 else
3831 interpolation_exchange, interp_weights_data, collection_size,
3832 tgt_field);
3833 }
3834
3835 if (!is_src) {
3836 for (size_t collection_idx = 0; collection_idx < collection_size;
3837 ++collection_idx) {
3838 for (size_t j = 0; j < grid->num_cells; ++j) {
3839 if (grid->core_cell_mask[j]) {
3840 if (grid->cell_ids[j]&1) {
3841 if (tgt_field[collection_idx][j] !=
3842 (double)(grid->cell_ids[j])) err_count++;
3843 } else {
3844 if (!isinf(tgt_field[collection_idx][j])) err_count++;
3845 }
3846 } else {
3847 if (tgt_field[collection_idx][j] != -1.0) err_count++;
3848 }
3849 }
3850 }
3851 }
3852 }
3853 }
3856 interpolation_exchange, "utest_check_direct_results");
3857 }
3858 }
3859
3860 return err_count;
3861}
3862
3863static void utest_get_basic_grid_data(
3864 char * filename, size_t * num_cells, size_t * num_vertices,
3865 size_t * num_edges) {
3866
3867 int ncid;
3868
3869 yac_nc_open(filename, NC_NOWRITE, &ncid);
3870
3871 int dimid;
3872 yac_nc_inq_dimid(ncid, "cell", &dimid);
3873 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, num_cells));
3874 yac_nc_inq_dimid(ncid, "vertex", &dimid);
3875 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, num_vertices));
3876 yac_nc_inq_dimid(ncid, "edge", &dimid);
3877 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, num_edges));
3878
3879 YAC_HANDLE_ERROR(nc_close(ncid));
3880}
3881
3882static struct yac_basic_grid_data
3883 utest_generate_dummy_grid_data(
3884 size_t local_num_cells, size_t global_num_cells, size_t num_cells_offset) {
3885
3886 double coordinates_x[global_num_cells + 1];
3887 double coordinates_y[2] = {0.0, 1.0};
3888 size_t num_cells[2] = {global_num_cells, 1};
3889 size_t local_start[2] = {num_cells_offset, 0};
3890 size_t local_count[2] = {local_num_cells, 1};
3891
3892 for (size_t i = 0; i <= global_num_cells; ++i) coordinates_x[i] = (double)i;
3893
3894 return
3896 coordinates_x, coordinates_y, num_cells, local_start, local_count, 0);
3897}
3898
3899static int utest_check_results_ref(
3900 int is_src, struct yac_interp_weights * weights,
3901 double * src_data,
3902 double * tgt_data, double * ref_tgt_data, size_t tgt_size,
3903 int is_active_src, int is_active_tgt) {
3904
3905 int err_count = 0;
3906
3907 size_t collection_size = 1;
3908
3909 // representative subset of interpolation generation configurations
3910 // covering both reorder types, different scale factors/summands,
3911 // and both yaxt exchanger variants
3912 struct {
3913 double scale_factor;
3914 double scale_summand;
3915 char const * yaxt_exchanger;
3916 enum yac_interp_weights_reorder_type reorder_type;
3917 } interp_gen_config_params[] = {
3918 { 1.0, 0.0, NULL, YAC_MAPPING_ON_SRC}, // baseline src
3919 { 1.0, 0.0, NULL, YAC_MAPPING_ON_TGT}, // baseline tgt
3920 {-1.0, 0.0, NULL, YAC_MAPPING_ON_SRC}, // negative scale
3921 { 0.5, 10.0, NULL, YAC_MAPPING_ON_TGT}, // scale + offset
3922 { 1.0, -1.0, "irecv_isend", YAC_MAPPING_ON_SRC}, // alt exchanger src
3923 { 1.0, 0.0, "irecv_isend", YAC_MAPPING_ON_TGT}, // alt exchanger tgt
3924 };
3925 enum {
3926 NUM_CONFIGS =
3927 sizeof(interp_gen_config_params) / sizeof(interp_gen_config_params[0])};
3928
3929 struct yac_interpolation_gen_config * interp_gen_config =
3932 interp_gen_config, collection_size);
3933
3934 for (size_t config_idx = 0; config_idx < NUM_CONFIGS; ++config_idx) {
3935
3936 double scale_factor = interp_gen_config_params[config_idx].scale_factor;
3937 double scale_summand = interp_gen_config_params[config_idx].scale_summand;
3938
3940 interp_gen_config,
3941 interp_gen_config_params[config_idx].reorder_type);
3943 interp_gen_config, scale_factor);
3945 interp_gen_config, scale_summand);
3947 interp_gen_config,
3948 interp_gen_config_params[config_idx].yaxt_exchanger);
3949
3951 interpolations[0] =
3953 weights, interp_gen_config, is_active_src, is_active_tgt);
3955 struct yac_interpolation_exchange * interpolation_exchange;
3958 weights, interp_gen_config, &interpolation_exchange,
3959 &interp_weights_data, is_active_src, is_active_tgt);
3960
3961 for (int interp_idx = 0; interp_idx < 2; ++interp_idx) {
3962
3963 double * tgt_field[1] = {tgt_data};
3964 double * src_field[1] = {src_data};
3965 double ** src_fields[1] = {src_field};
3966
3967 if (!is_src)
3968 for (size_t k = 0; k < tgt_size; ++k) tgt_data[k] = -1;
3969
3971 interpolations[interp_idx], src_fields, tgt_field);
3972
3973 if (!is_src)
3974 for (size_t j = 0; j < tgt_size; ++j)
3975 if (!(((ref_tgt_data[j] == FALLBACK_VALUE) == (tgt_data[j] == FALLBACK_VALUE)) ||
3976 ((ref_tgt_data[j] == FIXED_VALUE) == (tgt_data[j] == FIXED_VALUE)) ||
3977 ((ref_tgt_data[j] != FALLBACK_VALUE) && (ref_tgt_data[j] != FIXED_VALUE) &&
3978 (fabs(
3979 (ref_tgt_data[j] * scale_factor +
3980 scale_summand) - tgt_data[j]) < TOL))))
3981 err_count++;
3982
3983 if (is_src) {
3985 interpolations[interp_idx], src_fields);
3986 } else {
3987 for (size_t k = 0; k < tgt_size; ++k) tgt_data[k] = -1;
3989 interpolations[interp_idx], tgt_field);
3990 for (size_t j = 0; j < tgt_size; ++j)
3991 if (!(((ref_tgt_data[j] == FALLBACK_VALUE) == (tgt_data[j] == FALLBACK_VALUE)) ||
3992 ((ref_tgt_data[j] == FIXED_VALUE) == (tgt_data[j] == FIXED_VALUE)) ||
3993 ((ref_tgt_data[j] != FALLBACK_VALUE) && (ref_tgt_data[j] != FIXED_VALUE) &&
3994 (fabs((ref_tgt_data[j] * scale_factor + scale_summand) -
3995 tgt_data[j]) < TOL))))
3996 err_count++;
3997 }
3999 }
4000
4001 {
4002 double * tgt_field[1] = {tgt_data};
4003 double * src_field[1] = {src_data};
4004 double ** src_fields[1] = {src_field};
4005
4006 if (!is_src)
4007 for (size_t k = 0; k < tgt_size; ++k) tgt_data[k] = -1;
4008
4009 utest_interpolation_execute_raw(
4010 interpolation_exchange, interp_weights_data, collection_size,
4011 src_fields, tgt_field);
4012
4013 if (!is_src)
4014 for (size_t j = 0; j < tgt_size; ++j)
4015 if (!(((ref_tgt_data[j] == FALLBACK_VALUE) == (tgt_data[j] == FALLBACK_VALUE)) ||
4016 ((ref_tgt_data[j] == FIXED_VALUE) == (tgt_data[j] == FIXED_VALUE)) ||
4017 ((ref_tgt_data[j] != FALLBACK_VALUE) && (ref_tgt_data[j] != FIXED_VALUE) &&
4018 (fabs((ref_tgt_data[j] * scale_factor + scale_summand) -
4019 tgt_data[j]) < TOL))))
4020 err_count++;
4021
4024 interpolation_exchange, "direct_mf");
4025 }
4026 } // config_idx
4027
4028 yac_interpolation_gen_config_delete(interp_gen_config);
4029
4030 return err_count;
4031}
4032
4033int get_logical_attribute(int ncid, char const * attribute_name) {
4034
4035 int attribute;
4036
4037 size_t attlen;
4038 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, NC_GLOBAL, attribute_name, &attlen));
4039 char att_text[attlen+1];
4040 memset(att_text, '\0', attlen+1);
4041 YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, attribute_name, att_text));
4042
4043 attribute = (strlen("TRUE") == attlen) &&
4044 !strncmp("TRUE", att_text, attlen);
4046 attribute ||
4047 ((strlen("FALSE") == attlen) &&
4048 !strncmp("FALSE", att_text, attlen)),
4049 " invalid global %s value %s", attribute_name, att_text);
4050
4051 return attribute;
4052}
4053
4054static void utest_get_basic_weight_file_info(
4055 char const * weight_file_name, int * contains_links, int * contains_fixed) {
4056
4057 MPI_Barrier(MPI_COMM_WORLD);
4058
4059 int ncid;
4060
4062 PUT_ERR("error in yac_interp_weights_write_to_file");
4063 *contains_fixed = 0;
4064 *contains_links = 0;
4065 return;
4066 }
4067
4068 yac_nc_open(weight_file_name, NC_NOWRITE, &ncid);
4069 *contains_links = get_logical_attribute(ncid, "contains_links");
4070 *contains_fixed = get_logical_attribute(ncid, "contains_fixed_dst");
4071 YAC_HANDLE_ERROR(nc_close(ncid));
4072}
4073
4075 MPI_Comm comm, char const * msg, char const * source, int line) {
4076
4077 UNUSED(comm);
4078 UNUSED(msg);
4079 UNUSED(source);
4080 UNUSED(line);
4081
4082 int abort_handler_was_called = 1;
4083 MPI_Allreduce(
4084 MPI_IN_PLACE, &abort_handler_was_called, 1,
4085 MPI_INT, MPI_MAX, MPI_COMM_WORLD);
4086
4087 int comm_rank;
4088 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
4089 MPI_Barrier(MPI_COMM_WORLD);
4090 if (comm_rank == 0) unlink(weight_file_name_on_existing);
4091
4092 // MPI_Abort may yield non-zero error codes of mpirun hence we
4093 // terminate the programm gracefully
4094 xt_finalize();
4095 MPI_Finalize();
4096 exit(TEST_EXIT_CODE);
4097}
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:57
char const * yac_basic_grid_get_name(struct yac_basic_grid *grid)
Definition basic_grid.c:130
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
#define UNUSED(x)
Definition core.h:72
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
struct yac_basic_grid_data yac_generate_basic_grid_data_reg2d(double const *global_coords_x, double const *global_coords_y, size_t const num_global_cells_[2], size_t const local_start[2], size_t const local_count[2], int with_halo)
void yac_interp_grid_delete(struct yac_interp_grid *interp_grid)
void yac_interp_grid_get_tgt_points(struct yac_interp_grid *interp_grid, size_t **tgt_indices, size_t *count)
Definition interp_grid.c:99
void yac_interp_grid_get_tgt_global_ids(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, yac_int *tgt_global_ids)
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
struct remote_point * yac_interp_grid_get_tgt_remote_points(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count)
struct remote_point * yac_interp_grid_get_src_remote_points(struct yac_interp_grid *interp_grid, size_t src_field_idx, size_t *src_points, size_t count)
void yac_interp_grid_src_global_to_local(struct yac_interp_grid *interp_grid, size_t src_field_idx, yac_int *src_global_ids, size_t count, size_t *src_local_ids)
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_file_new(char const *weight_file_name, enum yac_interp_file_on_missing_file on_missing_file, enum yac_interp_file_on_success on_success)
#define YAC_INTERP_FILE_ON_SUCCESS_DEFAULT
#define YAC_INTERP_FILE_ON_MISSING_FILE_DEFAULT
void yac_interp_weights_add_fixed(struct yac_interp_weights *weights, struct remote_points *tgts, double fixed_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_add_sum_mf(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_src_per_field_per_tgt, struct remote_point **srcs_per_field, size_t num_src_fields)
struct yac_interpolation * yac_interp_weights_get_interpolation_ext(struct yac_interp_weights const *weights, struct yac_interpolation_gen_config const *config, int is_source, int is_target)
void yac_interp_weights_add_wsum(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_src_per_tgt, struct remote_point *srcs, double *w)
void yac_interp_weights_delete(struct yac_interp_weights *weights)
void yac_interp_weights_get_interpolation_raw(struct yac_interp_weights *weights, size_t collection_size, double frac_mask_fallback_value, double scaling_factor, double scaling_summand, char const *yaxt_exchanger_name, struct yac_interpolation_exchange **interpolation_exchange, struct yac_interp_weights_data *interp_weights_data, int is_source, int is_target)
void yac_interp_weights_data_free(struct yac_interp_weights_data interp_weights_data)
void yac_interp_weights_wcopy_weights(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_stencils_per_tgt, size_t *stencil_indices, int *stencil_ranks, double *w)
void yac_interp_weights_add_wsum_mf(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_src_per_field_per_tgt, struct remote_point **srcs_per_field, double *w, size_t num_src_fields)
yac_int * yac_interp_weights_get_interp_tgt(struct yac_interp_weights *weights)
MPI_Comm yac_interp_weights_get_comm(struct yac_interp_weights *weights)
void yac_interp_weights_add_direct(struct yac_interp_weights *weights, struct remote_points *tgts, struct remote_point *srcs)
void yac_interp_weights_add_sum(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_src_per_tgt, struct remote_point *srcs)
struct yac_interp_weights * yac_interp_weights_new(MPI_Comm comm, enum yac_location tgt_location, enum yac_location *src_locations, size_t num_src_fields)
size_t yac_interp_weights_get_interp_count(struct yac_interp_weights *weights)
void yac_interp_weights_get_interpolation_raw_ext(struct yac_interp_weights const *weights, struct yac_interpolation_gen_config const *config, struct yac_interpolation_exchange **interpolation_exchange, struct yac_interp_weights_data *interp_weights_data, int is_source, int is_target)
void yac_interp_weights_write_to_file(struct yac_interp_weights *weights, char const *filename, char const *src_grid_name, char const *tgt_grid_name, size_t src_grid_size, size_t tgt_grid_size, enum yac_weight_file_on_existing on_existing)
void yac_interp_weights_add_direct_mf(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *src_field_indices, struct remote_point **srcs_per_field, size_t num_src_fields)
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
yac_weight_file_on_existing
@ YAC_WEIGHT_FILE_KEEP
keep existing weight file
@ YAC_WEIGHT_FILE_OVERWRITE
overwrite existing weight file
@ YAC_WEIGHT_FILE_ERROR
error when weight file existis already
struct yac_interpolation * yac_interpolation_copy(struct yac_interpolation *interp)
Create a deep copy of an interpolation object.
void yac_interpolation_execute(struct yac_interpolation *interp, double ***src_fields, double **tgt_field)
Execute interpolation synchronously and write results to the target field.
void yac_interpolation_delete(struct yac_interpolation *interp)
Free an interpolation object and release all resources.
void yac_interpolation_execute_frac(struct yac_interpolation *interp, double ***src_fields, double ***src_frac_masks, double **tgt_field)
Execute interpolation with fractional masks and write results to the target field.
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_frac(struct yac_interpolation *interp, double ***src_fields, double ***src_frac_masks)
Provide source field data with fractional masks and start asynchronous execution of interpolation (pu...
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
void yac_interpolation_exchange_execute_get(struct yac_interpolation_exchange *exchange, double **recv_data, char const *routine)
Execute the get phase and receive target data synchronously.
void yac_interpolation_exchange_execute(struct yac_interpolation_exchange *exchange, double const **send_data_, double **recv_data_, char const *routine)
Execute the full exchange (put + get) synchronously.
void yac_interpolation_exchange_execute_put(struct yac_interpolation_exchange *exchange, double const **send_data, char const *routine)
Execute only the put phase asynchronously.
void yac_interpolation_exchange_delete(struct yac_interpolation_exchange *exchange, char const *routine)
Delete an interpolation exchange and release resources.
Interpolation exchange object for temporary buffers and MPI exchanges.
void yac_interpolation_gen_config_set_reorder(struct yac_interpolation_gen_config *config, enum yac_interp_weights_reorder_type reorder)
Set the reordering strategy for interpolation weights.
void yac_interpolation_gen_config_set_collection_size(struct yac_interpolation_gen_config *config, size_t collection_size)
Set the number of contiguous fields (starting at "0") in the field collection.
void yac_interpolation_gen_config_set_scaling_factor(struct yac_interpolation_gen_config *config, double scaling_factor)
Set the multiplicative scaling factor.
void yac_interpolation_gen_config_set_yaxt_exchanger_name(struct yac_interpolation_gen_config *config, char const *name)
Set the name of the Yaxt exchanger.
void yac_interpolation_gen_config_delete(struct yac_interpolation_gen_config *config)
Release a interpolation generation configuration structure allocated by yac_interpolation_gen_config_...
struct yac_interpolation_gen_config * yac_interpolation_gen_config_new(void)
Allocate and initialise an interpolation generation configuration structure.
void yac_interpolation_gen_config_set_scaling_summand(struct yac_interpolation_gen_config *config, double scaling_summand)
Set the additive scaling summand.
Configuration management for interpolation generation.
#define YAC_FRAC_MASK_VALUE_IS_VALID(value)
Test whether a fractional mask value is valid.
int yac_file_exists(const char *filename)
Check whether a file exists.
Definition io_utils.c:394
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:311
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:344
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_EDGE
Definition location.h:16
@ YAC_LOC_CELL
Definition location.h:14
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct yac_basic_grid_data yac_read_icon_basic_grid_data_parallel(const char *filename, MPI_Comm comm)
single location information of a point
union remote_point_infos::@53 data
struct remote_point_info single
struct remote_point_info * multi
information (global id and location) about a point that
yac_int global_id
struct remote_point_infos data
structure containing the information (global id and location)
struct remote_point * data
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
Configuration structure for interpolation generation.
double frac_mask_fallback_value
void set_even_io_rank_list(MPI_Comm comm)
int collection_size
double * data
char const * weight_file_name
enum yac_interp_weights_reorder_type reorder_types[]
char const src_grid_name[]
char const tgt_grid_name[]
static double const fixed_value
enum yac_interp_spmap_weight_type weight_types[]
static double tgt_field_data[MAX_COLLECTION_SIZE][NUM_TGT_POINTS]
static double ref_tgt_field_data[MAX_COLLECTION_SIZE][NUM_TGT_POINTS]
#define N
static char const * grid_names[2]
static void on_existing_abort_handler(MPI_Comm comm, char const *msg, char const *source, int line)
static void interpolation_put_frac_raw(struct yac_interpolation_exchange *interpolation_exchange, struct yac_interp_weights_data interp_weights_data, size_t collection_size, double ***src_fields, double ***src_frac_masks)
static void interpolation_put_raw(struct yac_interpolation_exchange *interpolation_exchange, struct yac_interp_weights_data interp_weights_data, size_t collection_size, double ***src_fields)
static char const * weight_file_name_on_existing
int get_logical_attribute(int ncid, char const *attribute_name)
static void deallocate_src_data_raw(size_t collection_size, struct yac_interp_weights_data interp_weights_data, double **src_data_raw)
static double ** allocate_src_data_raw(size_t collection_size, struct yac_interp_weights_data interp_weights_data)
#define FRAC_MASK_TOL
static void interpolation_get_raw(struct yac_interpolation_exchange *interpolation_exchange, struct yac_interp_weights_data interp_weights_data, size_t collection_size, double **tgt_field)
#define FIXED_VALUE
#define FALLBACK_VALUE
static void apply_interp_weights_data(size_t collection_size, struct yac_interp_weights_data interp_weights_data, double **src_data_raw, double **tgt_field)
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
struct @6 interpolations[]
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
#define MAX(a, b)
void(* yac_abort_func)(MPI_Comm comm, const char *msg, const char *source, int line) __attribute__((noreturn))
Definition yac.h:3545
void yac_restore_default_abort_handler(void)
void yac_set_abort_handler(yac_abort_func custom_abort)
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
YAC_INT yac_int
Definition yac_types.h:15