YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_dummy_coupling_raw_c.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <mpi.h>
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <string.h>
10#include <math.h>
11#include "tests.h"
12#include "test_common.h"
13#include "yac.h"
14
20#define RAD (0.01745329251994329576923690768489) // M_PI / 180
21#define FRAC_MASK_TOL (1e-12)
22#define RESULT_TOL (1e-2)
23
42
44 double *** src_field_buffer, double *** src_frac_mask_buffer,
45 double ** tgt_field, size_t collection_size,
47 size_t num_tgt_points, int use_csr_format);
48
49static void interp_weights_data_free(
51
52static void multi_compute_weights(
53 double const tgt_coords[3], int src_cell_id, size_t src_cell_idx,
54 int const ** global_results_points, double ** result_weights,
55 size_t * result_count, void * user_data);
56
58 int field_id, int use_csr_format);
59
60static void check_results(
61 int is_tgt, int info, size_t collection_size, size_t num_tgt_points,
62 double *** src_field_buffer, double *** src_frac_mask_buffer,
63 struct interp_weights_data interp_weights_data, int * tgt_global_ids,
64 double * ref_tgt_field_data, int use_csr_format);
65
76int main(void) {
77
78 // initialise YAC
79 yac_cinit();
81 yac_cdef_datetime("2000-01-01T00:00:00", "2000-01-02T00:00:00");
82
83 int size, rank;
84 MPI_Comm_rank ( MPI_COMM_WORLD, &rank );
85 MPI_Comm_size ( MPI_COMM_WORLD, &size );
86
87 if (size != 4) {
88 PUT_ERR("ERROR: wrong number of processes");
90 return TEST_EXIT_CODE;
91 }
92
93 int is_src = rank <= 1;
94 int is_tgt = (rank >= 1) && (rank < 3);
95 int is_dummy = !is_src && !is_tgt;
96 int src_rank = rank;
97 int tgt_rank = rank - 1;
98
99 // define local components
100 int comp_ids[2], src_comp_id, tgt_comp_id, dummy_comp_id;
101 int num_comps = 0;
102 char const * src_comp_name = "source_component";
103 char const * tgt_comp_name = "target_component";
104 char const * dummy_comp_name = "dummy_component";
105 char const * comp_names[2];
106 if (is_src) comp_names[num_comps++] = src_comp_name;
107 if (is_tgt) comp_names[num_comps++] = tgt_comp_name;
108 if (is_dummy) comp_names[num_comps++] = dummy_comp_name;
109 yac_cdef_comps(comp_names, num_comps, comp_ids);
110 dummy_comp_id = is_dummy?comp_ids[--num_comps]:-1;
111 tgt_comp_id = is_tgt?comp_ids[--num_comps]:-1;
112 src_comp_id = is_src?comp_ids[--num_comps]:-1;
113
114 // define local grids
115 int src_grid_id, tgt_grid_id, dummy_grid_id;
116 // quarter of the source grid is masked out
117 int src_cell_mask_id_quarter;
118 // half of the source grid is masked out (one complete process)
119 int src_cell_mask_id_half_a;
120 int src_cell_mask_id_half_b;
121 // half of the target grid is masked out (one complete process)
122 int tgt_cell_mask_id_half_a;
123 int tgt_cell_mask_id_half_b;
124 char const * src_grid_name = "source_grid";
125 char const * tgt_grid_name = "target_grid";
126 char const * dummy_grid_name = "dummy_grid";
127 int src_cell_global_ids[2][2] = {{0,2}, {1,3}};
128 int tgt_cell_global_ids[2][6] = {{0,1,2, 3,4,5}, {3,4,5, 6,7,8}};
129 int tgt_vertex_global_ids[2][12] = {{0,1,2,3, 4,5,6,7, 8,9,10,11},
130 {4,5,6,7, 8,9,10,11, 12,13,14,15}};
131 if (is_src) {
132 int nbr_vertices[2] = {2,3};
133 int cyclic[2] = {0, 0};
134 double x_vertices[2][2] = {{-1.0,0.0}, {0.0,1.0}};
135 double y_vertices[3] = {-1.0,0.0,1.0};
136 int src_cell_is_valid[3][2][2] =
137 {{{0,1},{1,1}},{{1,1},{0,0}},{{0,0},{1,1}}};
138 for (int i = 0; i < nbr_vertices[0]; ++i) x_vertices[src_rank][i] *= RAD;
139 for (int i = 0; i < nbr_vertices[1]; ++i) y_vertices[i] *= RAD;
141 src_grid_name, nbr_vertices, cyclic,
142 x_vertices[src_rank], y_vertices, &src_grid_id);
144 src_cell_global_ids[src_rank], YAC_LOCATION_CELL, src_grid_id);
146 src_grid_id, (nbr_vertices[0] - 1) * (nbr_vertices[1] - 1),
147 YAC_LOCATION_CELL, src_cell_is_valid[0][src_rank],
148 &src_cell_mask_id_quarter);
150 src_grid_id, (nbr_vertices[0] - 1) * (nbr_vertices[1] - 1),
151 YAC_LOCATION_CELL, src_cell_is_valid[1][src_rank],
152 &src_cell_mask_id_half_a);
154 src_grid_id, (nbr_vertices[0] - 1) * (nbr_vertices[1] - 1),
155 YAC_LOCATION_CELL, src_cell_is_valid[2][src_rank],
156 &src_cell_mask_id_half_b);
157 } else {
158 src_grid_id = -1;
159 src_cell_mask_id_quarter = -1;
160 src_cell_mask_id_half_a = -1;
161 src_cell_mask_id_half_b = -1;
162 }
163 if (is_tgt) {
164 int nbr_vertices[2] = {4,3};
165 int cyclic[2] = {0, 0};
166 double x_vertices[4] = {-1.5,-0.5,0.5,1.5};
167 double y_vertices[2][3] = {{-1.5,-0.5,0.5}, {-0.5,0.5,1.5}};
168 int tgt_cell_is_valid_a[2][6] = {{0,0,0, 0,0,0},{0,0,0, 1,1,1}};
169 int tgt_cell_is_valid_b[2][6] = {{1,1,1, 0,0,0},{0,0,0, 0,0,0}};
170 for (int i = 0; i < nbr_vertices[0]; ++i) x_vertices[i] *= RAD;
171 for (int i = 0; i < nbr_vertices[1]; ++i) y_vertices[tgt_rank][i] *= RAD;
173 tgt_grid_name, nbr_vertices, cyclic,
174 x_vertices, y_vertices[tgt_rank], &tgt_grid_id);
176 tgt_cell_global_ids[tgt_rank], YAC_LOCATION_CELL, tgt_grid_id);
178 tgt_vertex_global_ids[tgt_rank], YAC_LOCATION_CORNER, tgt_grid_id);
180 tgt_grid_id, (nbr_vertices[0] - 1) * (nbr_vertices[1] - 1),
181 YAC_LOCATION_CELL, tgt_cell_is_valid_a[tgt_rank],
182 &tgt_cell_mask_id_half_a);
184 tgt_grid_id, (nbr_vertices[0] - 1) * (nbr_vertices[1] - 1),
185 YAC_LOCATION_CELL, tgt_cell_is_valid_b[tgt_rank],
186 &tgt_cell_mask_id_half_b);
187 } else {
188 tgt_grid_id = -1;
189 tgt_cell_mask_id_half_a = -1;
190 tgt_cell_mask_id_half_b = -1;
191 }
193 dummy_grid_name, (int[]){2,2}, (int[]){0,0},
194 (double[]){-1,1}, (double[]){-1,1}, &dummy_grid_id);
195
196 // define cell points
197 int src_cell_point_id, tgt_cell_point_id, tgt_vertex_point_id,
198 dummy_cell_point_id;
199 if (is_src) {
200 int num_cells[2] = {1,2};
201 double x_cells[2][2] = {{-0.5}, {0.5}};
202 double y_cells[2] = {-0.5,0.5};
203 for (int i = 0; i < num_cells[0]; ++i) x_cells[src_rank][i] *= RAD;
204 for (int i = 0; i < num_cells[1]; ++i) y_cells[i] *= RAD;
206 src_grid_id, num_cells, YAC_LOCATION_CELL,
207 x_cells[src_rank], y_cells, &src_cell_point_id);
208 } else {
209 src_cell_point_id = -1;
210 }
211 if (is_tgt) {
212 int num_cells[2] = {3,2};
213 int num_vertices[2] = {4,3};
214 double x_cells[3] = {-1.0,0.0,1.0};
215 double y_cells[2][2] = {{-1.0,0.0}, {0.0,1.0}};
216 double x_vertices[4] = {-1.5,-0.5,0.5,1.5};
217 double y_vertices[2][3] = {{-1.5,-0.5,0.5}, {-0.5,0.5,1.5}};
218 for (int i = 0; i < num_cells[0]; ++i) x_cells[i] *= RAD;
219 for (int i = 0; i < num_cells[1]; ++i) y_cells[tgt_rank][i] *= RAD;
220 for (int i = 0; i < num_vertices[0]; ++i) x_vertices[i] *= RAD;
221 for (int i = 0; i < num_vertices[1]; ++i) y_vertices[tgt_rank][i] *= RAD;
223 tgt_grid_id, num_cells, YAC_LOCATION_CELL,
224 x_cells, y_cells[tgt_rank], &tgt_cell_point_id);
226 tgt_grid_id, num_vertices, YAC_LOCATION_CORNER,
227 x_vertices, y_vertices[tgt_rank], &tgt_vertex_point_id);
228 } else {
229 tgt_cell_point_id = -1;
230 tgt_vertex_point_id = -1;
231 }
233 dummy_grid_id, (int[]){1,1}, YAC_LOCATION_CELL,
234 (double[]){0}, (double[]){0}, &dummy_cell_point_id);
235
236 // additional definitions
237 size_t collection_size = 1;
238 if (is_src)
240 multi_compute_weights, NULL, "multi_compute_weights");
241 double fixed_value = -2.0;
242 double frac_mask_fallback_value = 3.0;
243 int interp_stack_conserv, interp_stack_callback;
244 yac_cget_interp_stack_config(&interp_stack_conserv);
246 interp_stack_conserv, 1, 0, 1, YAC_CONSERV_DESTAREA);
247 yac_cadd_interp_stack_config_fixed(interp_stack_conserv, fixed_value);
248 yac_cget_interp_stack_config(&interp_stack_callback);
250 interp_stack_callback, "multi_compute_weights");
251 yac_cadd_interp_stack_config_fixed(interp_stack_callback, fixed_value);
252 int ext_couple_config;
253 yac_cget_ext_couple_config(&ext_couple_config);
255
256 // all test configurations
257 enum {SRC = 0, TGT = 1};
258 struct {
259 struct {
260 char const * name;
261 int * point_ids;
262 int * mask_ids;
263 int ** global_ids;
264 int num_points;
265 int id;
266 } field[2];
267 char const * coupling_period;
268 int interp_stack_config;
270 int use_csr_format;
272 double *** src_field_buffer;
273 double *** src_frac_mask_buffer;
274 } test_configs[] =
275 {
276 { // TEST_IDX = 0
277 .field =
278 {{.name = "source_field",
279 .point_ids = (int[]){src_cell_point_id},
280 .mask_ids = (int[]){src_cell_mask_id_quarter},
281 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
282 .num_points = 1},
283 {.name = "target_field",
284 .point_ids = (int[]){tgt_cell_point_id},
285 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
286 .mask_ids = (int[]){-1},
287 .num_points = 1}},
288 .coupling_period = "1",
289 .interp_stack_config = interp_stack_conserv,
290 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
291 .use_csr_format = 0
292 },
293 { // TEST_IDX = 1
294 .field =
295 {{.name = "source_field_frac",
296 .point_ids = (int[]){src_cell_point_id},
297 .mask_ids = (int[]){src_cell_mask_id_quarter},
298 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
299 .num_points = 1},
300 {.name = "target_field_frac",
301 .point_ids = (int[]){tgt_cell_point_id},
302 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
303 .mask_ids = (int[]){-1},
304 .num_points = 1}},
305 .coupling_period = "1",
306 .interp_stack_config = interp_stack_conserv,
307 .frac_mask_fallback_value = frac_mask_fallback_value,
308 .use_csr_format = 0
309 },
310 { // TEST_IDX = 2
311 // test in which the process that has the role of source and target
312 // does not receive any data
313 // in addition this test check time reduction capabilities
314 .field =
315 {{.name = "source_field_full_a",
316 .point_ids = (int[]){src_cell_point_id},
317 .mask_ids = (int[]){-1},
318 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
319 .num_points = 1},
320 {.name = "target_field_half_a",
321 .point_ids = (int[]){tgt_cell_point_id},
322 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
323 .mask_ids = (int[]){tgt_cell_mask_id_half_a},
324 .num_points = 1}},
325 .coupling_period = "2",
326 .interp_stack_config = interp_stack_conserv,
327 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
328 .use_csr_format = 0
329 },
330 { // TEST_IDX = 3
331 // test in which the process that has only the role of target
332 // does not receive any data
333 // in addition this test check time reduction capabilities
334 .field =
335 {{.name = "source_field_full_b",
336 .point_ids = (int[]){src_cell_point_id},
337 .mask_ids = (int[]){-1},
338 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
339 .num_points = 1},
340 {.name = "target_field_half_b",
341 .point_ids = (int[]){tgt_cell_point_id},
342 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
343 .mask_ids = (int[]){tgt_cell_mask_id_half_b},
344 .num_points = 1}},
345 .coupling_period = "2",
346 .interp_stack_config = interp_stack_conserv,
347 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
348 .use_csr_format = 0
349 },
350 { // TEST_IDX = 4
351 // test in which the process that has the role of source and target
352 // does not send any data
353 // in addition this test check time reduction capabilities
354 .field =
355 {{.name = "source_field_half_a",
356 .point_ids = (int[]){src_cell_point_id},
357 .mask_ids = (int[]){src_cell_mask_id_half_a},
358 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
359 .num_points = 1},
360 {.name = "target_field_full_a",
361 .point_ids = (int[]){tgt_cell_point_id},
362 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
363 .mask_ids = (int[]){-1},
364 .num_points = 1}},
365 .coupling_period = "2",
366 .interp_stack_config = interp_stack_conserv,
367 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
368 .use_csr_format = 0
369 },
370 { // TEST_IDX = 5
371 // test in which the process that has the only role of source
372 // does not send any data
373 // in addition this test check time reduction capabilities
374 .field =
375 {{.name = "source_field_half_b",
376 .point_ids = (int[]){src_cell_point_id},
377 .mask_ids = (int[]){src_cell_mask_id_half_b},
378 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
379 .num_points = 1},
380 {.name = "target_field_full_b",
381 .point_ids = (int[]){tgt_cell_point_id},
382 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
383 .mask_ids = (int[]){-1},
384 .num_points = 1}},
385 .coupling_period = "2",
386 .interp_stack_config = interp_stack_conserv,
387 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
388 .use_csr_format = 0
389 },
390 { // TEST_IDX = 6
391 // test in which the process that has the role of source and target
392 // does not receive any data (with fractional masking)
393 // in addition this test check time reduction capabilities
394 .field =
395 {{.name = "source_field_frac_full_a",
396 .point_ids = (int[]){src_cell_point_id},
397 .mask_ids = (int[]){-1},
398 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
399 .num_points = 1},
400 {.name = "target_field_frac_half_a",
401 .point_ids = (int[]){tgt_cell_point_id},
402 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
403 .mask_ids = (int[]){tgt_cell_mask_id_half_a},
404 .num_points = 1}},
405 .coupling_period = "2",
406 .interp_stack_config = interp_stack_conserv,
407 .frac_mask_fallback_value = frac_mask_fallback_value,
408 .use_csr_format = 0
409 },
410 { // TEST_IDX = 7
411 // test in which the process that has only the role of target
412 // does not receive any data (with fractional masking)
413 // in addition this test check time reduction capabilities
414 .field =
415 {{.name = "source_field_frac_full_b",
416 .point_ids = (int[]){src_cell_point_id},
417 .mask_ids = (int[]){-1},
418 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
419 .num_points = 1},
420 {.name = "target_field_frac_half_b",
421 .point_ids = (int[]){tgt_cell_point_id},
422 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
423 .mask_ids = (int[]){tgt_cell_mask_id_half_b},
424 .num_points = 1}},
425 .coupling_period = "2",
426 .interp_stack_config = interp_stack_conserv,
427 .frac_mask_fallback_value = frac_mask_fallback_value,
428 .use_csr_format = 0
429 },
430 { // TEST_IDX = 8
431 // test in which the process that has the role of source and target
432 // does not send any data (with fractional masking)
433 // in addition this test check time reduction capabilities
434 .field =
435 {{.name = "source_field_frac_half_a",
436 .point_ids = (int[]){src_cell_point_id},
437 .mask_ids = (int[]){src_cell_mask_id_half_a},
438 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
439 .num_points = 1},
440 {.name = "target_field_frac_full_a",
441 .point_ids = (int[]){tgt_cell_point_id},
442 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
443 .mask_ids = (int[]){-1},
444 .num_points = 1}},
445 .coupling_period = "2",
446 .interp_stack_config = interp_stack_conserv,
447 .frac_mask_fallback_value = frac_mask_fallback_value,
448 .use_csr_format = 0
449 },
450 { // TEST_IDX = 9
451 // test in which the process that has the only role of source
452 // does not send any data (with fractional masking)
453 // in addition this test check time reduction capabilities
454 .field =
455 {{.name = "source_field_frac_half_b",
456 .point_ids = (int[]){src_cell_point_id},
457 .mask_ids = (int[]){src_cell_mask_id_half_b},
458 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
459 .num_points = 1},
460 {.name = "target_field_frac_full_b",
461 .point_ids = (int[]){tgt_cell_point_id},
462 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
463 .mask_ids = (int[]){-1},
464 .num_points = 1}},
465 .coupling_period = "2",
466 .interp_stack_config = interp_stack_conserv,
467 .frac_mask_fallback_value = frac_mask_fallback_value,
468 .use_csr_format = 0
469 },
470 { // TEST_IDX = 10
471 // test in the target field is generated from multiple source point
472 // sets
473 .field =
474 {{.name = "source_field_multi",
475 .point_ids = (int[]){src_cell_point_id, src_cell_point_id},
476 .mask_ids = (int[]){-1,-1},
477 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
478 .num_points = 2},
479 {.name = "target_field_multi",
480 .point_ids = (int[]){tgt_vertex_point_id},
481 .global_ids = (int*[]){is_tgt?tgt_vertex_global_ids[tgt_rank]:NULL},
482 .mask_ids = (int[]){-1},
483 .num_points = 1}},
484 .coupling_period = "1",
485 .interp_stack_config = interp_stack_callback,
486 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
487 .use_csr_format = 0
488 },
489 { // TEST_IDX = 11
490 // test in which a source field is sent to two target fields
491 // (one using raw data exchange and the other does not)
492 .field =
493 {{.name = "source_field_comp",
494 .point_ids = (int[]){src_cell_point_id},
495 .mask_ids = (int[]){src_cell_mask_id_quarter},
496 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
497 .num_points = 1},
498 {.name = "target_field_comp_raw",
499 .point_ids = (int[]){tgt_cell_point_id},
500 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
501 .mask_ids = (int[]){-1},
502 .num_points = 1}},
503 .coupling_period = "1",
504 .interp_stack_config = interp_stack_conserv,
505 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
506 .use_csr_format = 0
507 },
508 { // TEST_IDX = 12
509 .field =
510 {{.name = "source_field_csr",
511 .point_ids = (int[]){src_cell_point_id},
512 .mask_ids = (int[]){src_cell_mask_id_quarter},
513 .global_ids = (int*[]){is_src?src_cell_global_ids[src_rank]:NULL},
514 .num_points = 1},
515 {.name = "target_field_csr",
516 .point_ids = (int[]){tgt_cell_point_id},
517 .global_ids = (int*[]){is_tgt?tgt_cell_global_ids[tgt_rank]:NULL},
518 .mask_ids = (int[]){-1},
519 .num_points = 1}},
520 .coupling_period = "1",
521 .interp_stack_config = interp_stack_conserv,
522 .frac_mask_fallback_value = YAC_FRAC_MASK_NO_VALUE,
523 .use_csr_format = 1
524 }
525 };
526
527 // define configurations
528 for (size_t i = 0; i < sizeof(test_configs) / sizeof(test_configs[0]); ++i) {
529
530 // define source and target fields
531 for (int j = 0; j < 2; ++j) {
532 if (test_configs[i].field[j].point_ids[0] != -1) {
533 int comp_id = (j == SRC)?src_comp_id:tgt_comp_id;
534 if (test_configs[i].field[j].mask_ids[0] != -1)
536 test_configs[i].field[j].name, comp_id,
537 test_configs[i].field[j].point_ids,
538 test_configs[i].field[j].mask_ids,
539 test_configs[i].field[j].num_points,
540 1, "1", YAC_TIME_UNIT_SECOND,
541 &test_configs[i].field[j].id);
542 else
544 test_configs[i].field[j].name, comp_id,
545 test_configs[i].field[j].point_ids,
546 test_configs[i].field[j].num_points,
547 1, "1", YAC_TIME_UNIT_SECOND,
548 &test_configs[i].field[j].id);
549 } else {
550 test_configs[i].field[j].id = -1;
551 }
552 }
553
554 // enable fractional masking, if required
555 if (is_src && (test_configs[i].frac_mask_fallback_value !=
558 src_comp_name, src_grid_name, test_configs[i].field[SRC].name,
559 test_configs[i].frac_mask_fallback_value);
560
561 // define couple
563 src_comp_name, src_grid_name, test_configs[i].field[SRC].name,
564 tgt_comp_name, tgt_grid_name, test_configs[i].field[TGT].name,
565 test_configs[i].coupling_period,
567 test_configs[i].interp_stack_config, 0, 0, ext_couple_config);
568 }
569
570 int tgt_field_non_raw_id;
571 if (is_tgt) {
572 // define a file that will not use raw data exchange
573 // it will receive data from a source field, which also sends data
574 // to a target that uses raw data exchange
576 "target_field_comb_non_raw", tgt_comp_id, &tgt_cell_point_id,
577 1, 1, "1", YAC_TIME_UNIT_SECOND, &tgt_field_non_raw_id);
579 src_comp_name, src_grid_name, "source_field_comp",
580 tgt_comp_name, tgt_grid_name, "target_field_comb_non_raw",
582 interp_stack_conserv, 0, 0);
583 } else {
584 tgt_field_non_raw_id = -1;
585 }
586
587 // uncoupled dummy fields
588 int src_dummy_field_id = -1, tgt_dummy_field_id = -1;
589 switch (1 * is_src + 2 * is_tgt) {
590 case (0): { // neither source nor target
592 "target_field_dummy", dummy_comp_id, &dummy_cell_point_id,
593 1, 1, "1", YAC_TIME_UNIT_SECOND, &tgt_dummy_field_id);
595 "source_field_dummy", dummy_comp_id, &dummy_cell_point_id,
596 1, 1, "1", YAC_TIME_UNIT_SECOND, &src_dummy_field_id);
597 break;
598 }
599 case (1): { // only source
601 "target_field_dummy", src_comp_id, &dummy_cell_point_id,
602 1, 1, "1", YAC_TIME_UNIT_SECOND, &tgt_dummy_field_id);
603 break;
604 }
605 case (2): { // only target
607 "source_field_dummy", tgt_comp_id, &dummy_cell_point_id,
608 1, 1, "1", YAC_TIME_UNIT_SECOND, &src_dummy_field_id);
609 break;
610 }
611 case (3): { // source and target
612 break;
613 }
614 default: {
615 PUT_ERR("ERROR: invalid process type");
617 return TEST_EXIT_CODE;
618 }
619 } // role
620
621 // end definition phase
622 yac_cenddef();
623
624 // extract interpolation weight data and allocate source field buffer
625 for (size_t i = 0; i < sizeof(test_configs) / sizeof(test_configs[0]); ++i) {
626 test_configs[i].interp_weights_data =
628 test_configs[i].field[TGT].id, test_configs[i].use_csr_format);
629 size_t num_src_fields = test_configs[i].interp_weights_data.num_src_fields;
630 size_t * src_field_buffer_sizes =
631 test_configs[i].interp_weights_data.src_field_buffer_sizes;
632 size_t sum_src_field_buffer_sizes = 0;
633 for (size_t i = 0; i < num_src_fields; ++i)
634 sum_src_field_buffer_sizes += src_field_buffer_sizes[i];
635 double * src_field_buffer_1d =
636 (sum_src_field_buffer_sizes > 0)?
637 malloc(
638 collection_size * sum_src_field_buffer_sizes *
639 sizeof(*src_field_buffer_1d)):NULL;
640 double *** src_field_buffer =
641 malloc(collection_size * sizeof(*src_field_buffer));
642 for (size_t i = 0, offset = 0; i < collection_size; ++i) {
643 src_field_buffer[i] = malloc(num_src_fields * sizeof(**src_field_buffer));
644 for (size_t j = 0; j < num_src_fields; ++j) {
645 src_field_buffer[i][j] = src_field_buffer_1d + offset;
646 offset += src_field_buffer_sizes[j];
647 }
648 }
649 test_configs[i].src_field_buffer = src_field_buffer;
650 if (test_configs[i].frac_mask_fallback_value != YAC_FRAC_MASK_NO_VALUE) {
651 double * src_frac_mask_buffer_1d =
652 (sum_src_field_buffer_sizes > 0)?
653 malloc(
654 collection_size * sum_src_field_buffer_sizes *
655 sizeof(*src_frac_mask_buffer_1d)):NULL;
656 double *** src_frac_mask_buffer =
657 malloc(collection_size * sizeof(*src_frac_mask_buffer));
658 for (size_t i = 0, offset = 0; i < collection_size; ++i) {
659 src_frac_mask_buffer[i] =
660 malloc(num_src_fields * sizeof(**src_frac_mask_buffer));
661 for (size_t j = 0; j < num_src_fields; ++j) {
662 src_frac_mask_buffer[i][j] = src_frac_mask_buffer_1d + offset;
663 offset += src_field_buffer_sizes[j];
664 }
665 }
666 test_configs[i].src_frac_mask_buffer = src_frac_mask_buffer;
667 } else {
668 test_configs[i].src_frac_mask_buffer = NULL;
669 }
670 }
671
672 //-----------------------------------------------------
673 // do tests
674 //-----------------------------------------------------
675
676 enum {
679 GLOBAL_NUM_SRC_CELLS = 4,
680 GLOBAL_NUM_TGT_CELLS = 9,
681 GLOBAL_NUM_TGT_VERTICES = 16,
682 NUM_SRC_CELLS = 2,
683 NUM_TGT_CELLS = 6,
684 NUM_TGT_VERTICES = 12,
685 };
686 double global_src_field_data[MAX_NUM_SRC_FIELDS][GLOBAL_NUM_SRC_CELLS] =
687 {{1,2,3,4}, {-1,-2,-3,-4}};
688 double src_field_data[MAX_COLLECTION_SIZE][MAX_NUM_SRC_FIELDS][NUM_SRC_CELLS];
689 double * src_field_[MAX_COLLECTION_SIZE][MAX_NUM_SRC_FIELDS];
691 if (is_src) {
692 for (size_t i = 0; i < MAX_COLLECTION_SIZE; ++i) {
693 for (size_t j = 0; j < MAX_NUM_SRC_FIELDS; ++j) {
694 for (size_t k = 0; k < NUM_SRC_CELLS; ++k)
695 src_field_data[i][j][k] =
696 global_src_field_data[j][src_cell_global_ids[src_rank][k]];
697 src_field_[i][j] = src_field_data[i][j];
698 }
699 src_field[i] = src_field_[i];
700 }
701 }
702
704
705 { // some basic tests
706
707 enum {TEST_IDX = 0, NUM_TESTS_BASIC = 3, COLLECTION_SIZE = 1};
708 int src_field_id = test_configs[TEST_IDX].field[SRC].id;
709 int tgt_field_id = test_configs[TEST_IDX].field[TGT].id;
710 double *** src_field_buffer = test_configs[TEST_IDX].src_field_buffer;
711 double ref_tgt_field_data[1][GLOBAL_NUM_TGT_CELLS] =
712 {{fixed_value,0.25*(2),0.25*(2),
713 0.25*(3),0.25*(2+3+4),0.25*(2+4),
714 0.25*(3),0.25*(3+4),0.25*(4)}};
715
716 for (size_t t = 0; t < NUM_TESTS_BASIC; ++t) {
717
718 switch (1 * is_src + 2 * is_tgt) {
719 case (0): { // neither source nor target
720 break;
721 }
722 case (1): { // only source
723
724 // send source data
725 yac_cput(
726 src_field_id, COLLECTION_SIZE, src_field, &info, &ierror);
727 yac_cwait(src_field_id);
728 break;
729 }
730 case (2): { // only target
731
732 // receive source field buffer
733 switch (t) {
734 default:
735 case(0): // blocking get
737 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
738 &info, &ierror);
739 break;
740 case(1): // async get using source field buffer pointers
742 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
743 &info, &ierror);
744 yac_cwait(tgt_field_id);
745 break;
746 case(2): // async get using 1d source field buffer
748 tgt_field_id, COLLECTION_SIZE, src_field_buffer[0][0],
749 &info, &ierror);
750 yac_cwait(tgt_field_id);
751 break;
752 }
753 break;
754 }
755 case (3): { // source and target
756
758 src_field_id, tgt_field_id, COLLECTION_SIZE,
759 src_field, src_field_buffer, &send_info, &recv_info, &ierror);
760 info = recv_info;
761 break;
762 }
763 default: {
764 PUT_ERR("ERROR: invalid process type");
766 return TEST_EXIT_CODE;
767 }
768 } // role
769
771 is_tgt, info, COLLECTION_SIZE, NUM_TGT_CELLS,
772 src_field_buffer, NULL, test_configs[TEST_IDX].interp_weights_data,
773 test_configs[TEST_IDX].field[TGT].global_ids[0],
774 ref_tgt_field_data[0], test_configs[TEST_IDX].use_csr_format);
775 } // basic test idx
776 }
777
778 { // some basic tests using fractional masking
779
780 enum {TEST_IDX = 1, NUM_FRAC_MASKS = 3,
781 NUM_FRAC_TESTS = 4, COLLECTION_SIZE = 1, NUM_SRC_FIELDS = 1};
782 int src_field_id = test_configs[TEST_IDX].field[SRC].id;
783 int tgt_field_id = test_configs[TEST_IDX].field[TGT].id;
784 double *** src_field_buffer = test_configs[TEST_IDX].src_field_buffer;
785 double *** src_frac_mask_buffer =
786 test_configs[TEST_IDX].src_frac_mask_buffer;
787 double ref_tgt_field_data[2][GLOBAL_NUM_TGT_CELLS] =
788 {{fixed_value,0.25*(2),0.25*(2),
789 0.25*(3),0.25*(2+3+4),0.25*(2+4),
790 0.25*(3),0.25*(3+4),0.25*(4)},
792 (0.25*(1.0*3))/((0.25*1.0)/(0.25)),
793 (0.25*(0.0*2+0.5*3+1.0*4))/((0.25*(0.0+0.5+1.0))/(0.25+0.25+0.25)),
794 (0.25*(0.0*2+1.0*4))/((0.25*(0.0+1.0))/(0.25+0.25)),
795 (0.25*(0.5*3))/((0.25*0.5)/(0.25)),
796 (0.25*(0.5*3+1.0*4))/((0.25*(0.5+1.0))/(0.25+0.25)),
797 (0.25*(1.0*4))/((0.25*1.0)/(0.25))}};
798
799 double global_src_frac_mask_data
800 [NUM_FRAC_MASKS][NUM_SRC_FIELDS][GLOBAL_NUM_SRC_CELLS] =
801 {{{1,1,1,1}},{{0.5,0.0,0.5,1.0}}};
802 double src_frac_mask_data
803 [NUM_FRAC_MASKS][MAX_COLLECTION_SIZE][NUM_SRC_FIELDS][NUM_SRC_CELLS];
804 double * src_frac_mask_
805 [NUM_FRAC_MASKS][MAX_COLLECTION_SIZE][NUM_SRC_FIELDS];
806 double ** src_frac_mask[NUM_FRAC_MASKS][MAX_COLLECTION_SIZE];
807 if (is_src) {
808 for (size_t t = 0; t < NUM_FRAC_MASKS; ++t) {
809 for (size_t i = 0; i < MAX_COLLECTION_SIZE; ++i) {
810 for (size_t j = 0; j < NUM_SRC_FIELDS; ++j) {
811 for (size_t k = 0; k < NUM_SRC_CELLS; ++k)
812 src_frac_mask_data[t][i][j][k] =
813 global_src_frac_mask_data
814 [t][j][src_cell_global_ids[src_rank][k]];
815 src_frac_mask_[t][i][j] = src_frac_mask_data[t][i][j];
816 }
817 src_frac_mask[t][i] = src_frac_mask_[t][i];
818 }
819 }
820 }
821
822 for (size_t t = 0; t < NUM_FRAC_TESTS; ++t) {
823
824 switch (1 * is_src + 2 * is_tgt) {
825 case (0): { // neither source nor target
826 break;
827 }
828 case (1): { // only source
829
830 // send source data and fractional mask
832 src_field_id, COLLECTION_SIZE,
833 src_field, src_frac_mask[t&1], &info, &ierror);
834 yac_cwait(src_field_id);
835 break;
836 }
837 case (2): { // only target
838
839 // receive source field and source fractional mask
840 switch (t) {
841 default:
842 case(0):
844 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
845 src_frac_mask_buffer, &info, &ierror);
846 yac_cwait(tgt_field_id);
847 break;
848 case(1):
850 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
851 src_frac_mask_buffer, &info, &ierror);
852 break;
853 case(2):
855 tgt_field_id, COLLECTION_SIZE, src_field_buffer[0][0],
856 src_frac_mask_buffer[0][0], &info, &ierror);
857 yac_cwait(tgt_field_id);
858 break;
859 case(3):
861 tgt_field_id, COLLECTION_SIZE, src_field_buffer[0][0],
862 src_frac_mask_buffer[0][0], &info, &ierror);
863 break;
864 }
865 break;
866 }
867 case (3): { // source and target
868
869 // exchange source field data and source fractional mask
871 src_field_id, tgt_field_id, COLLECTION_SIZE,
872 src_field, src_frac_mask[t&1],
873 src_field_buffer, src_frac_mask_buffer,
874 &send_info, &recv_info, &ierror);
875 info = recv_info;
876 break;
877 }
878 default: {
879 PUT_ERR("ERROR: invalid process type");
881 return TEST_EXIT_CODE;
882 }
883 } // role
884
886 is_tgt, info, COLLECTION_SIZE, NUM_TGT_CELLS,
887 src_field_buffer, src_frac_mask_buffer,
888 test_configs[TEST_IDX].interp_weights_data,
889 test_configs[TEST_IDX].field[TGT].global_ids[0],
890 ref_tgt_field_data[t&1], test_configs[TEST_IDX].use_csr_format);
891 } // frac test idx
892 }
893
894 { // a couple of tests in which one process does not send/receive any data
895 // in addition this test check time reduction capabilities
896
897 enum {MIN_TEST_IDX = 2, MAX_TEST_IDX = 9,
898 COLLECTION_SIZE = 1, NUM_TIMESTEPS = 6, NUM_SRC_FIELDS = 1};
899 double ref_tgt_field_data[8][1][GLOBAL_NUM_TGT_CELLS] =
900 {{{-1.0,-1.0,-1.0,
901 -1.0,-1.0,-1.0,
902 0.25*(3),0.25*(3+4),0.25*(4)}},
903 {{0.25*(1),0.25*(1+2),0.25*(2),
904 -1.0,-1.0,-1.0,
905 -1.0,-1.0,-1.0}},
906 {{0.25*(1),0.25*(1),fixed_value,
907 0.25*(1+3),0.25*(1+3),fixed_value,
908 0.25*(3),0.25*(3),fixed_value}},
909 {{fixed_value,0.25*(2),0.25*(2),
910 fixed_value,0.25*(2+4),0.25*(2+4),
911 fixed_value,0.25*(4),0.25*(4)}},
912 {{-1.0,-1.0,-1.0,
913 -1.0,-1.0,-1.0,
914 0.25*(3),0.25*(3+4),0.25*(4)}},
915 {{0.25*(1),0.25*(1+2),0.25*(2),
916 -1.0,-1.0,-1.0,
917 -1.0,-1.0,-1.0}},
918 {{0.25*(1),0.25*(1),fixed_value,
919 0.25*(1+3),0.25*(1+3),fixed_value,
920 0.25*(3),0.25*(3),fixed_value}},
921 {{fixed_value,0.25*(2),0.25*(2),
922 fixed_value,0.25*(2+4),0.25*(2+4),
923 fixed_value,0.25*(4),0.25*(4)}}};
924 double global_src_frac_mask_data
925 [NUM_SRC_FIELDS][GLOBAL_NUM_SRC_CELLS] = {{1,1,1,1}};
926 double src_frac_mask_data
927 [MAX_COLLECTION_SIZE][NUM_SRC_FIELDS][NUM_SRC_CELLS];
928 double * src_frac_mask_ [MAX_COLLECTION_SIZE][NUM_SRC_FIELDS];
929 double ** src_frac_mask[MAX_COLLECTION_SIZE];
930 if (is_src) {
931 for (size_t i = 0; i < MAX_COLLECTION_SIZE; ++i) {
932 for (size_t j = 0; j < NUM_SRC_FIELDS; ++j) {
933 for (size_t k = 0; k < NUM_SRC_CELLS; ++k)
934 src_frac_mask_data[i][j][k] =
935 global_src_frac_mask_data[j][src_cell_global_ids[src_rank][k]];
936 src_frac_mask_[i][j] = src_frac_mask_data[i][j];
937 }
938 src_frac_mask[i] = src_frac_mask_[i];
939 }
940 }
941
942 for (int use_only_exchange = 0; use_only_exchange <= 1;
943 ++use_only_exchange) {
944 for (size_t test_idx = MIN_TEST_IDX; test_idx < MAX_TEST_IDX; ++test_idx) {
945
946 int src_field_id =
947 is_src?test_configs[test_idx].field[SRC].id:src_dummy_field_id;
948 int tgt_field_id =
949 is_tgt?test_configs[test_idx].field[TGT].id:tgt_dummy_field_id;
950 double *** src_field_buffer = test_configs[test_idx].src_field_buffer;
951 double *** src_frac_mask_buffer =
952 test_configs[test_idx].src_frac_mask_buffer;
953 int with_frac_mask =
954 test_configs[test_idx].frac_mask_fallback_value !=
956
957 for (size_t t = 0; t < NUM_TIMESTEPS; ++t) {
958
959 info = YAC_ACTION_NONE;
960
961 switch (1 * is_src + 2 * is_tgt) {
962 case (0): { // neither source nor target
963
964 if (use_only_exchange) {
965 if (with_frac_mask)
967 src_field_id, tgt_field_id, COLLECTION_SIZE,
968 NULL, NULL, NULL, NULL,
969 &send_info, &recv_info, &ierror);
970 else
972 src_field_id, tgt_field_id, COLLECTION_SIZE,
973 NULL, NULL, &send_info, &recv_info, &ierror);
974 info = recv_info;
975 }
976 break;
977 }
978 case (1): { // only source
979
980 // send source data
981 if (use_only_exchange) {
982 if (with_frac_mask)
984 src_field_id, tgt_field_id, COLLECTION_SIZE,
985 src_field, src_frac_mask, NULL, NULL,
986 &send_info, &recv_info, &ierror);
987 else
989 src_field_id, tgt_field_id, COLLECTION_SIZE,
990 src_field, NULL, &send_info, &recv_info, &ierror);
991 info = recv_info;
992 } else {
993 // send source data
994 if (with_frac_mask)
996 src_field_id, COLLECTION_SIZE, src_field, src_frac_mask,
997 &info, &ierror);
998 else
999 yac_cput(
1000 src_field_id, COLLECTION_SIZE, src_field, &info, &ierror);
1001 }
1002 yac_cwait(src_field_id);
1003 break;
1004 }
1005 case (2): { // only target
1006
1007 // receive source field buffer
1008 if (use_only_exchange) {
1009 if (with_frac_mask)
1011 src_field_id, tgt_field_id, COLLECTION_SIZE,
1012 NULL, NULL, src_field_buffer, src_frac_mask_buffer,
1013 &send_info, &recv_info, &ierror);
1014 else
1016 src_field_id, tgt_field_id, COLLECTION_SIZE,
1017 NULL, src_field_buffer, &send_info, &recv_info, &ierror);
1018 } else {
1019 if (with_frac_mask)
1021 tgt_field_id, COLLECTION_SIZE,
1022 src_field_buffer, src_frac_mask_buffer, &info, &ierror);
1023 else
1025 tgt_field_id, COLLECTION_SIZE, src_field_buffer, &info, &ierror);
1026 }
1027 break;
1028 }
1029 case (3): { // source and target
1030
1031 if (with_frac_mask)
1033 src_field_id, tgt_field_id, COLLECTION_SIZE,
1034 src_field, src_frac_mask,
1035 src_field_buffer, src_frac_mask_buffer,
1036 &send_info, &recv_info, &ierror);
1037 else
1039 src_field_id, tgt_field_id, COLLECTION_SIZE,
1040 src_field, src_field_buffer, &send_info, &recv_info, &ierror);
1041 info = recv_info;
1042 break;
1043 }
1044 default: {
1045 PUT_ERR("ERROR: invalid process type");
1046 yac_cfinalize();
1047 return TEST_EXIT_CODE;
1048 }
1049 } // role
1050
1052 is_tgt, info, COLLECTION_SIZE, NUM_TGT_CELLS,
1053 src_field_buffer, with_frac_mask?src_frac_mask_buffer:NULL,
1054 test_configs[test_idx].interp_weights_data,
1055 test_configs[test_idx].field[TGT].global_ids[0],
1056 ref_tgt_field_data[test_idx-MIN_TEST_IDX][0],
1057 test_configs[test_idx].use_csr_format);
1058 } // time step
1059 } // test_idx
1060 } // use_only_exchange
1061 }
1062
1063 { // test using multiple source fields
1064
1065 enum {TEST_IDX = 10, COLLECTION_SIZE = 1};
1066 int src_field_id = test_configs[TEST_IDX].field[SRC].id;
1067 int tgt_field_id = test_configs[TEST_IDX].field[TGT].id;
1068 double *** src_field_buffer = test_configs[TEST_IDX].src_field_buffer;
1069 double ref_tgt_field_data[1][GLOBAL_NUM_TGT_VERTICES] =
1070 {{fixed_value, fixed_value, fixed_value, fixed_value,
1071 fixed_value, 1, 2, fixed_value,
1072 fixed_value, -3, -4, fixed_value,
1073 fixed_value, fixed_value, fixed_value, fixed_value}};
1074
1075 switch (1 * is_src + 2 * is_tgt) {
1076 case (0): { // neither source nor target
1077 break;
1078 }
1079 case (1): { // only source
1080
1081 // send source data
1082 yac_cput(
1083 src_field_id, COLLECTION_SIZE, src_field, &info, &ierror);
1084 yac_cwait(src_field_id);
1085 break;
1086 }
1087 case (2): { // only target
1088
1089 // receive source field buffer
1091 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
1092 &info, &ierror);
1093 break;
1094 }
1095 case (3): { // source and target
1096
1098 src_field_id, tgt_field_id, COLLECTION_SIZE,
1099 src_field, src_field_buffer, &send_info, &recv_info, &ierror);
1100 info = recv_info;
1101 break;
1102 }
1103 default: {
1104 PUT_ERR("ERROR: invalid process type");
1105 yac_cfinalize();
1106 return TEST_EXIT_CODE;
1107 }
1108 } // role
1109
1111 is_tgt, info, COLLECTION_SIZE, NUM_TGT_VERTICES,
1112 src_field_buffer, NULL,
1113 test_configs[TEST_IDX].interp_weights_data,
1114 test_configs[TEST_IDX].field[TGT].global_ids[0],
1115 ref_tgt_field_data[0], test_configs[TEST_IDX].use_csr_format);
1116 }
1117
1118 { // test with multiple targets
1119
1120 enum {TEST_IDX = 11, COLLECTION_SIZE = 1};
1121 int src_field_id = test_configs[TEST_IDX].field[SRC].id;
1122 int tgt_field_id = test_configs[TEST_IDX].field[TGT].id;
1123 double *** src_field_buffer = test_configs[TEST_IDX].src_field_buffer;
1124 double ref_tgt_field_data[1][GLOBAL_NUM_TGT_CELLS] =
1125 {{fixed_value,0.25*(2),0.25*(2),
1126 0.25*(3),0.25*(2+3+4),0.25*(2+4),
1127 0.25*(3),0.25*(3+4),0.25*(4)}};
1128
1129 switch (1 * is_src + 2 * is_tgt) {
1130 case (0): { // neither source nor target
1131 break;
1132 }
1133 case (1): { // only source
1134
1135 // send source data
1136 yac_cput(
1137 src_field_id, COLLECTION_SIZE, src_field, &info, &ierror);
1138 yac_cwait(src_field_id);
1139 break;
1140 }
1141 case (2): { // only target
1142
1143 // receive source field buffer
1145 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
1146 &info, &ierror);
1147 break;
1148 }
1149 case (3): { // source and target
1150
1151 yac_cput(
1152 src_field_id, COLLECTION_SIZE, src_field, &send_info, &ierror);
1154 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
1155 &recv_info, &ierror);
1156 info = recv_info;
1157 break;
1158 }
1159 default: {
1160 PUT_ERR("ERROR: invalid process type");
1161 yac_cfinalize();
1162 return TEST_EXIT_CODE;
1163 }
1164 } // role
1165
1167 is_tgt, info, COLLECTION_SIZE, NUM_TGT_CELLS,
1168 src_field_buffer, NULL,
1169 test_configs[TEST_IDX].interp_weights_data,
1170 test_configs[TEST_IDX].field[TGT].global_ids[0],
1171 ref_tgt_field_data[0], test_configs[TEST_IDX].use_csr_format);
1172
1173 if (is_tgt) {
1174
1175 double tgt_field_data[COLLECTION_SIZE][NUM_TGT_CELLS];
1176 double * tgt_field[COLLECTION_SIZE];
1177 for (size_t i = 0; i < COLLECTION_SIZE; ++i)
1178 tgt_field[i] = tgt_field_data[i];
1179
1180 // initialise target field
1181 for (size_t i = 0; i < COLLECTION_SIZE; ++i)
1182 for (size_t j = 0; j < NUM_TGT_CELLS; ++j)
1183 tgt_field[i][j] = -1.0;
1184
1185 yac_cget(
1186 tgt_field_non_raw_id, COLLECTION_SIZE, tgt_field, &info, &ierror);
1187
1188 // if data was received
1189 if ((info == YAC_ACTION_COUPLING) ||
1190 (info == YAC_ACTION_GET_FOR_RESTART)) {
1191
1192 // check results
1193 int * tgt_global_ids =
1194 test_configs[TEST_IDX].field[TGT].global_ids[0];
1195 for (size_t i = 0; i < COLLECTION_SIZE; ++i)
1196 for (size_t j = 0; j < NUM_TGT_CELLS; ++j)
1197 if (fabs(
1198 tgt_field_data[i][j] -
1199 ref_tgt_field_data[0][tgt_global_ids[j]]) >
1200 RESULT_TOL)
1201 PUT_ERR("wrong results");
1202 }
1203 }
1204 }
1205
1206 { // testing of interpolation weights data in csr format
1207
1208 enum {TEST_IDX = 12, NUM_TESTS_BASIC = 3, COLLECTION_SIZE = 1};
1209 int src_field_id = test_configs[TEST_IDX].field[SRC].id;
1210 int tgt_field_id = test_configs[TEST_IDX].field[TGT].id;
1211 double *** src_field_buffer = test_configs[TEST_IDX].src_field_buffer;
1212 double ref_tgt_field_data[1][GLOBAL_NUM_TGT_CELLS] =
1213 {{fixed_value,0.25*(2),0.25*(2),
1214 0.25*(3),0.25*(2+3+4),0.25*(2+4),
1215 0.25*(3),0.25*(3+4),0.25*(4)}};
1216
1217 for (size_t t = 0; t < NUM_TESTS_BASIC; ++t) {
1218
1219 switch (1 * is_src + 2 * is_tgt) {
1220 case (0): { // neither source nor target
1221 break;
1222 }
1223 case (1): { // only source
1224
1225 // send source data
1226 yac_cput(
1227 src_field_id, COLLECTION_SIZE, src_field, &info, &ierror);
1228 yac_cwait(src_field_id);
1229 break;
1230 }
1231 case (2): { // only target
1232
1233 // receive source field buffer
1234 switch (t) {
1235 default:
1236 case(0): // blocking get
1238 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
1239 &info, &ierror);
1240 break;
1241 case(1): // async get using source field buffer pointers
1243 tgt_field_id, COLLECTION_SIZE, src_field_buffer,
1244 &info, &ierror);
1245 yac_cwait(tgt_field_id);
1246 break;
1247 case(2): // async get using 1d source field buffer
1249 tgt_field_id, COLLECTION_SIZE, src_field_buffer[0][0],
1250 &info, &ierror);
1251 yac_cwait(tgt_field_id);
1252 break;
1253 }
1254 break;
1255 }
1256 case (3): { // source and target
1257
1259 src_field_id, tgt_field_id, COLLECTION_SIZE,
1260 src_field, src_field_buffer, &send_info, &recv_info, &ierror);
1261 info = recv_info;
1262 break;
1263 }
1264 default: {
1265 PUT_ERR("ERROR: invalid process type");
1266 yac_cfinalize();
1267 return TEST_EXIT_CODE;
1268 }
1269 } // role
1270
1272 is_tgt, info, COLLECTION_SIZE, NUM_TGT_CELLS,
1273 src_field_buffer, NULL, test_configs[TEST_IDX].interp_weights_data,
1274 test_configs[TEST_IDX].field[TGT].global_ids[0],
1275 ref_tgt_field_data[0], test_configs[TEST_IDX].use_csr_format);
1276 } // basic test idx
1277 }
1278
1279 yac_cfree_ext_couple_config(ext_couple_config);
1280 yac_cfree_interp_stack_config(interp_stack_conserv);
1281 yac_cfree_interp_stack_config(interp_stack_callback);
1282 for (size_t i = 0; i < sizeof(test_configs) / sizeof(test_configs[0]); ++i) {
1283 if (test_configs[i].interp_weights_data.num_src_fields > 0)
1284 free(test_configs[i].src_field_buffer[0][0]);
1285 for (size_t j = 0; j < collection_size; ++j)
1286 free(test_configs[i].src_field_buffer[j]);
1287 free(test_configs[i].src_field_buffer);
1288 if (test_configs[i].frac_mask_fallback_value != YAC_FRAC_MASK_NO_VALUE) {
1289 if (test_configs[i].interp_weights_data.num_src_fields > 0)
1290 free(test_configs[i].src_frac_mask_buffer[0][0]);
1291 for (size_t j = 0; j < collection_size; ++j)
1292 free(test_configs[i].src_frac_mask_buffer[j]);
1293 free(test_configs[i].src_frac_mask_buffer);
1294 }
1295 if (is_tgt) interp_weights_data_free(&test_configs[i].interp_weights_data);
1296 }
1297
1298 yac_cfinalize();
1299 return TEST_EXIT_CODE;
1300}
1301
1303 double *** src_field_buffer, double *** src_frac_mask_buffer,
1304 double ** tgt_field, size_t collection_size,
1306 size_t num_tgt_points, int use_csr_format) {
1307
1308 // ignore weights below a certain
1309 double const wgt_tol = 1e-6;
1310
1311 // we have to use memcpy to compare against YAC_FRAC_MASK_NO_VALUE,
1312 // because nan is a valid value for frac_mask_fallback_value and depending
1313 // on compiler optimisation a comparision agains nan can produce varying
1314 // results
1315 int with_frac_mask =
1318
1319 for (size_t collection_idx = 0; collection_idx < collection_size;
1320 ++collection_idx) {
1321
1322 // set fixed targets
1323 for (size_t i = 0, k = 0; i < interp_weights_data.num_fixed_values; ++i) {
1324
1325 double fixed_value = interp_weights_data.fixed_values[i];
1326 size_t num_fixed_tgt = interp_weights_data.num_tgt_per_fixed_value[i];
1327
1328 for (size_t j = 0; j < num_fixed_tgt; ++j, ++k)
1329 tgt_field[collection_idx][interp_weights_data.tgt_idx_fixed[k]] =
1330 fixed_value;
1331 }
1332
1333 size_t num_wgt_tgt =
1334 use_csr_format?num_tgt_points:interp_weights_data.num_wgt_tgt;
1335
1336 if (with_frac_mask) {
1337
1338 // set weighted targets
1339 for (size_t i = 0, k = 0; i < num_wgt_tgt; ++i) {
1340
1341 double tgt_value = 0.0;
1342 double frac_weight_sum = 0.0;
1343 double weight_sum = 0.0;
1344 size_t num_src =
1345 use_csr_format?
1349 size_t tgt_idx =
1350 use_csr_format?i:interp_weights_data.wgt_tgt_idx[i];
1351
1352 if (num_src == 0) continue;
1353
1354 for (size_t j = 0; j < num_src; ++j, ++k) {
1355 if (fabs(interp_weights_data.weights[k]) < wgt_tol) continue;
1356 tgt_value +=
1358 src_field_buffer
1359 [collection_idx]
1362 frac_weight_sum +=
1364 src_frac_mask_buffer
1365 [collection_idx]
1368 weight_sum += interp_weights_data.weights[k];
1369 }
1370
1371 tgt_field[collection_idx][tgt_idx] =
1372 (fabs(frac_weight_sum) > FRAC_MASK_TOL)?
1374 (tgt_value / frac_weight_sum) * weight_sum +
1377 }
1378
1379 } else {
1380
1381 // set weighted targets
1382 for (size_t i = 0, k = 0; i < num_wgt_tgt; ++i) {
1383
1384 double tgt_value = 0.0;
1385 size_t num_src =
1386 use_csr_format?
1390 size_t tgt_idx =
1391 use_csr_format?i:interp_weights_data.wgt_tgt_idx[i];
1392
1393 if (num_src == 0) continue;
1394
1395 for (size_t j = 0; j < num_src; ++j, ++k) {
1396 if (fabs(interp_weights_data.weights[k]) < wgt_tol) continue;
1397 tgt_value +=
1399 src_field_buffer
1400 [collection_idx]
1403 }
1404
1405 tgt_field[collection_idx][tgt_idx] =
1408 }
1409 }
1410 }
1411}
1412
1427
1429 double const tgt_coords[3], int src_cell_id, size_t src_cell_idx,
1430 int const ** global_results_points, double ** result_weights,
1431 size_t * result_count, void * user_data) {
1432
1433 // unused arguments
1434 (void)(tgt_coords);
1435 (void)(src_cell_idx);
1436 (void)(user_data);
1437
1438 // only the cells in the upper row of the source grid receive their
1439 // data from the second source field
1440 int use_second_src_field = src_cell_id >= 2;
1441
1442 static int results_point;
1443 static double result_weight;
1444
1445 results_point = src_cell_id;
1446 result_weight = 1.0;
1447
1448 global_results_points[use_second_src_field] = &results_point;
1449 global_results_points[use_second_src_field^1] = NULL;
1450 result_weights[use_second_src_field] = &result_weight;
1451 result_weights[use_second_src_field^1] = NULL;
1452 result_count[use_second_src_field] = 1;
1453 result_count[use_second_src_field^1] = 0;
1454}
1455
1457 int field_id, int use_csr_format) {
1458
1460
1461 if (field_id > -1) {
1462
1463 if (use_csr_format) {
1465 field_id,
1466 &data.frac_mask_fallback_value,
1467 &data.scaling_factor, &data.scaling_summand,
1468 &data.num_fixed_values, &data.fixed_values,
1469 &data.num_tgt_per_fixed_value, &data.tgt_idx_fixed,
1470 &data.src_indptr, &data.weights, &data.src_field_idx, &data.src_idx,
1471 &data.num_src_fields, &data.src_field_buffer_sizes);
1472 data.num_wgt_tgt = 0;
1473 data.wgt_tgt_idx = NULL;
1474 data.num_src_per_tgt = NULL;
1475 } else {
1477 field_id,
1478 &data.frac_mask_fallback_value,
1479 &data.scaling_factor, &data.scaling_summand,
1480 &data.num_fixed_values, &data.fixed_values,
1481 &data.num_tgt_per_fixed_value, &data.tgt_idx_fixed,
1482 &data.num_wgt_tgt, &data.wgt_tgt_idx, &data.num_src_per_tgt,
1483 &data.weights, &data.src_field_idx, &data.src_idx,
1484 &data.num_src_fields, &data.src_field_buffer_sizes);
1485 data.src_indptr = NULL;
1486 }
1487 } else {
1488 data.num_src_fields = 0;
1489 }
1490
1491 return data;
1492}
1493
1494static void check_results(
1495 int is_tgt, int info, size_t collection_size, size_t num_tgt_points,
1496 double *** src_field_buffer, double *** src_frac_mask_buffer,
1497 struct interp_weights_data interp_weights_data, int * tgt_global_ids,
1498 double * ref_tgt_field_data, int use_csr_format) {
1499
1500 // if data was received
1501 if (is_tgt &&
1502 ((info == YAC_ACTION_COUPLING) ||
1503 (info == YAC_ACTION_GET_FOR_RESTART))) {
1504
1505 double tgt_field_data[collection_size][num_tgt_points];
1506 double * tgt_field[collection_size];
1507 for (size_t i = 0; i < collection_size; ++i)
1508 tgt_field[i] = tgt_field_data[i];
1509
1510 // initialise target field
1511 for (size_t i = 0; i < collection_size; ++i)
1512 for (size_t j = 0; j < num_tgt_points; ++j)
1513 tgt_field[i][j] = -1.0;
1514
1515 // compute target field
1517 src_field_buffer, src_frac_mask_buffer,
1518 (double**)tgt_field, collection_size, interp_weights_data,
1519 num_tgt_points, use_csr_format);
1520
1521 // check results
1522 for (size_t i = 0; i < collection_size; ++i)
1523 for (size_t j = 0; j < num_tgt_points; ++j)
1524 if (fabs(
1525 tgt_field_data[i][j] - ref_tgt_field_data[tgt_global_ids[j]]) >
1526 RESULT_TOL)
1527 PUT_ERR("wrong results");
1528 }
1529}
@ TGT
Definition instance.c:105
@ SRC
Definition instance.c:104
void * user_data
double const YAC_FRAC_MASK_NO_VALUE
@ COLLECTION_SIZE
int collection_size
static void multi_compute_weights(double const tgt_coords[3], int src_cell_id, size_t src_cell_idx, int const **global_results_points, double **result_weights, size_t *result_count, void *user_data)
#define RESULT_TOL
static struct interp_weights_data get_interp_weights_data(int field_id, int use_csr_format)
static void compute_tgt_field(double ***src_field_buffer, double ***src_frac_mask_buffer, double **tgt_field, size_t collection_size, struct interp_weights_data interp_weights_data, size_t num_tgt_points, int use_csr_format)
#define FRAC_MASK_TOL
static void interp_weights_data_free(struct interp_weights_data *interp_weights_data)
#define RAD
static void check_results(int is_tgt, int info, size_t collection_size, size_t num_tgt_points, double ***src_field_buffer, double ***src_frac_mask_buffer, struct interp_weights_data interp_weights_data, int *tgt_global_ids, double *ref_tgt_field_data, int use_csr_format)
double * data
char const src_grid_name[]
char const tgt_grid_name[]
static double tgt_field_data[MAX_COLLECTION_SIZE][NUM_TGT_POINTS]
static double ref_tgt_field_data[MAX_COLLECTION_SIZE][NUM_TGT_POINTS]
#define MAX_COLLECTION_SIZE
size_t num_cells[2]
unsigned cyclic[2]
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10
int info
int comp_ids[1]
int ierror
int * field_id
int comp_id
char const * name
Definition toy_scrip.c:114
int id
Definition toy_scrip.c:115
void yac_cget_raw_frac_async(int const field_id, int collection_size, double ***src_field_buffer, double ***src_frac_mask_buffer, int *info, int *ierr)
Definition yac.c:2978
int const YAC_REDUCTION_TIME_AVERAGE
Definition yac.c:51
void yac_cget_raw_async(int const field_id, int collection_size, double ***src_field_buffer, int *info, int *ierr)
Definition yac.c:2946
void yac_cput_frac(int const field_id, int const collection_size, double ***const send_field, double ***const send_frac_mask, int *info, int *ierr)
Definition yac.c:3568
void yac_cenddef(void)
Definition yac.c:4363
void yac_cenable_field_frac_mask(const char *comp_name, const char *grid_name, const char *field_name, double frac_mask_fallback_value)
Definition yac.c:1416
void yac_cdef_field_mask(char const *name, int const comp_id, int const *point_ids, int const *mask_ids, int const num_pointsets, int collection_size, const char *timestep, int time_unit, int *field_id)
Definition yac.c:1300
void yac_cset_global_index(int const *global_index, int location, int grid_id)
Definition yac.c:5012
void yac_cget_raw_interp_weights_data_csr(int const field_id, double *frac_mask_fallback_value, double *scaling_factor, double *scaling_summand, size_t *num_fixed_values, double **fixed_values, size_t **num_tgt_per_fixed_value, size_t **tgt_idx_fixed, size_t **src_indptr_, double **weights, size_t **src_field_idx, size_t **src_idx, size_t *num_src_fields, size_t **src_field_buffer_sizes)
Definition yac.c:2210
void yac_cfree_ext_couple_config(int ext_couple_config_id)
Definition yac.c:1547
void yac_cdef_datetime(const char *start_datetime, const char *end_datetime)
Definition yac.c:738
int const YAC_LOCATION_CELL
Definition yac.c:31
void yac_cadd_compute_weights_callback(yac_func_compute_weights compute_weights_callback, void *user_data, char const *key)
Definition yac.c:5830
void yac_cget_raw(int const field_id, int collection_size, double ***src_field_buffer, int *info, int *ierr)
Definition yac.c:2933
void yac_cinit(void)
Definition yac.c:488
void yac_cget_raw_frac(int const field_id, int collection_size, double ***src_field_buffer, double ***src_frac_mask_buffer, int *info, int *ierr)
Definition yac.c:2960
void yac_cfinalize()
Finalises YAC.
Definition yac.c:717
void yac_cget_raw_async_(int const field_id, int const collection_size, double *src_field_buffer, int *info, int *ierr)
Definition yac.c:2877
void yac_cget_raw_interp_weights_data(int const field_id, double *frac_mask_fallback_value, double *scaling_factor, double *scaling_summand, size_t *num_fixed_values, double **fixed_values, size_t **num_tgt_per_fixed_value, size_t **tgt_idx_fixed, size_t *num_wgt_tgt, size_t **wgt_tgt_idx, size_t **num_src_per_tgt, double **weights, size_t **src_field_idx, size_t **src_idx, size_t *num_src_fields, size_t **src_field_buffer_size)
Definition yac.c:2170
void yac_cget_ext_couple_config(int *ext_couple_config_id)
Definition yac.c:1526
int const YAC_LOCATION_CORNER
Definition yac.c:32
void yac_cdef_couple_custom(char const *src_comp_name, char const *src_grid_name, char const *src_field_name, char const *tgt_comp_name, char const *tgt_grid_name, char const *tgt_field_name, char const *coupling_timestep, int time_unit, int time_reduction, int interp_stack_config_id, int src_lag, int tgt_lag, int ext_couple_config_id)
Definition yac.c:1896
int const YAC_CONSERV_DESTAREA
Definition yac.c:82
void yac_cget(int const field_id, int collection_size, double **recv_field, int *info, int *ierr)
Definition yac.c:2729
void yac_cdef_grid_reg2d(const char *grid_name, int nbr_vertices[2], int cyclic[2], double *x_vertices, double *y_vertices, int *grid_id)
Definition yac.c:4794
void yac_cset_ext_couple_config_use_raw_exchange(int ext_couple_config_id, int use_raw_exchange)
Definition yac.c:1762
void yac_cdef_points_reg2d(int const grid_id, int const *nbr_points, int const located, double const *x_points, double const *y_points, int *point_id)
Definition yac.c:1080
void yac_cexchange_raw_frac(int const send_field_id, int const recv_field_id, int const collection_size, double ***const send_field, double ***const send_frac_mask, double ***src_field_buffer, double ***src_frac_mask_buffer, int *send_info, int *recv_info, int *ierr)
Definition yac.c:4112
int const YAC_TIME_UNIT_SECOND
Definition yac.c:56
void yac_cadd_interp_stack_config_conservative(int interp_stack_config_id, int order, int enforced_conserv, int partial_coverage, int normalisation)
Definition yac.c:5204
void yac_cput(int const field_id, int const collection_size, double ***const send_field, int *info, int *ierr)
Definition yac.c:3684
int const YAC_ACTION_NONE
no data exchanges
Definition yac.c:39
void yac_cdef_calendar(int calendar)
Definition yac.c:746
void yac_cget_raw_frac_async_(int const field_id, int const collection_size, double *src_field_buffer, double *src_frac_mask_buffer, int *info, int *ierr)
Definition yac.c:2889
void yac_cwait(int field_id)
Definition yac.c:3205
void yac_cget_raw_frac_(int const field_id, int const collection_size, double *src_field_buffer, double *src_frac_mask_buffer, int *info, int *ierr)
Definition yac.c:2832
void yac_cdef_comps(char const **comp_names, int num_comps, int *comp_ids)
Definition yac.c:976
int const YAC_ACTION_GET_FOR_RESTART
last valid get
Definition yac.c:43
int const YAC_PROLEPTIC_GREGORIAN
Definition yac.c:65
void yac_cadd_interp_stack_config_fixed(int interp_stack_config_id, double value)
Definition yac.c:5785
static size_t num_points
Definition yac.c:159
int const YAC_ACTION_COUPLING
data exchange
Definition yac.c:41
void yac_cexchange_raw(int const send_field_id, int const recv_field_id, int const collection_size, double ***const send_field, double ***src_field_buffer, int *send_info, int *recv_info, int *ierr)
Definition yac.c:4323
void yac_cdef_mask(int const grid_id, int const nbr_points, int const located, int const *is_valid, int *mask_id)
Definition yac.c:1272
void yac_cadd_interp_stack_config_user_callback(int interp_stack_config_id, char const *func_compute_weights_key)
Definition yac.c:5817
void yac_cfree_interp_stack_config(int interp_stack_config_id)
Definition yac.c:5114
void yac_cget_interp_stack_config(int *interp_stack_config_id)
Definition yac.c:5100
void yac_cdef_field(char const *name, int const comp_id, int const *point_ids, int const num_pointsets, int collection_size, const char *timestep, int time_unit, int *field_id)
Definition yac.c:1373
void yac_cdef_couple(char const *src_comp_name, char const *src_grid_name, char const *src_field_name, char const *tgt_comp_name, char const *tgt_grid_name, char const *tgt_field_name, char const *coupling_timestep, int time_unit, int time_reduction, int interp_stack_config_id, int src_lag, int tgt_lag)
Definition yac.c:1928