YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interp_method_dnn_parallel.c
Go to the documentation of this file.
1// Copyright (c) 2026 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <math.h>
8
9#include "tests.h"
13#include "dist_grid_utils.h"
14#include "yac_mpi.h"
15#include "geometry.h"
17
18#include <mpi.h>
19#include <yaxt.h>
20
26static void utest_compute_reference_result(
27 struct yac_interp_method_dnn_config const dnn_config,
28 double const * src_coordinates_x, double const * src_coordinates_y,
29 int const * src_global_mask, size_t const src_size_x, size_t const src_size_y,
30 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
31 size_t const tgt_size_x, size_t const tgt_size_y,
32 double * ref_tgt_results);
33
34static double const fixed_value = -1.0;
35
36int main (void) {
37
38 MPI_Init(NULL, NULL);
39
40 xt_initialize(MPI_COMM_WORLD);
41
42 int comm_rank, comm_size;
43 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
44 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
45 MPI_Barrier(MPI_COMM_WORLD);
46
47 if (comm_size != 5) {
48 PUT_ERR("ERROR: wrong number of processes");
49 xt_finalize();
50 MPI_Finalize();
51 return TEST_EXIT_CODE;
52 }
53
54 enum yac_interp_weights_reorder_type reorder_type[2] =
56 enum {NUM_REORDER_TYPES = sizeof(reorder_type)/sizeof(reorder_type[0])};
57
58 { // Test DNN with fixed search distance, distance weights, and fixed value fallback
59
60 // corner and cell ids for a 7 x 7 grid (x == target point position)
61 // uses 4 source processes (ranks 0 to 3) and 1 target process (rank 4)
62
63 // 56-----57-----58-----59-----60-----61-----62-----63
64 // | x| x| x| x| x| x| x|
65 // | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
66 // | | | | | | | |
67 // 48-----49-----50-----51-----52-----53-----54-----55
68 // | x| x| x| x| x| x| x|
69 // | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
70 // | | | | | | | |
71 // 40-----41-----42-----43-----44-----45-----46-----47
72 // | x| x| x| x| x| x| x|
73 // | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
74 // | | | | | | | |
75 // 32-----33-----34-----35-----36-----37-----38-----39
76 // | x| x| x| x| x| x| x|
77 // | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
78 // | | | | | | | |
79 // 24-----25-----26-----27-----28-----29-----30-----31
80 // | x| x| x| x| x| x| x|
81 // | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
82 // | | | | | | | |
83 // 16-----17-----18-----19-----20-----21-----22-----23
84 // | x| x| x| x| x| x| x|
85 // | 07 | 08 | 09 | 10 | 11 | 12 | 13 |
86 // | | | | | | | |
87 // 08-----09-----10-----11-----12-----13-----14-----15
88 // | x| x| x| x| x| x| x|
89 // | 00 | 01 | 02 | 03 | 04 | 05 | 06 |
90 // | | | | | | | |
91 // 00-----01-----02-----03-----04-----05-----06-----07
92 //
93 // the grid is distributed among the processes as follows:
94 // (index == process)
95 //
96 // 3---3---3---3---3---3---3---3
97 // | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
98 // 3---3---3---3---3---3---3---3
99 // | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
100 // 3---3---3---1---2---2---3---3
101 // | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
102 // 1---1---1---2---2---2---2---2
103 // | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
104 // 1---1---1---1---2---2---2---2
105 // | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
106 // 1---1---1---0---0---0---2---2
107 // | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
108 // 0---0---0---0---0---0---0---0
109 // | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
110 // 0---0---0---0---0---0---0---0
111 //
112 // the source mask looks as follows (# == masked point)
113 //
114 // +---+---+---+---+---+---+---#
115 // | | | | | | | |
116 // +---+---+---+---+---+---#---+
117 // | | | | | | | |
118 // +---+---+---+---+---#---+---+
119 // | | | | | | | |
120 // +---+---+---+---#---+---+---+
121 // | | | | | | | |
122 // #---#---#---#---+---+---+---+
123 // | | | | | | | |
124 // #---#---#---#---+---+---+---+
125 // | | | | | | | |
126 // #---#---#---#---+---+---+---+
127 // | | | | | | | |
128 // #---#---#---#---+---+---+---+
129
130 enum {NUM_CELLS_X = 7, NUM_CELLS_Y = 7, NUM_PROCS = 5, TGT_RANK = 4};
131 char const * src_grid_name= "src_grid";
132 char const * tgt_grid_name= "tgt_grid";
133 double coordinates_x[NUM_CELLS_X+1] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
134 double coordinates_y[NUM_CELLS_Y+1] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
135 double cell_coordinates_x[NUM_CELLS_X] = {0.75,1.75,2.75,3.75,4.75,5.75,6.75};
136 double cell_coordinates_y[NUM_CELLS_Y] = {0.75,1.75,2.75,3.75,4.75,5.75,6.75};
137 size_t const num_cells[2] = {NUM_CELLS_X,NUM_CELLS_Y};
138 size_t const local_start[NUM_PROCS][2] = {{0,0},{0,2},{3,2},{0,5}, {0,0}};
139 size_t const local_count[NUM_PROCS][2] = {{7,2},{3,3},{4,3},{7,2}, {7,7}};
140 int const with_halo = 0;
141 int const src_global_corner_mask[NUM_CELLS_X+1][NUM_CELLS_Y+1] = {
142 {0,0,0,0,1,1,1,1},
143 {0,0,0,0,1,1,1,1},
144 {0,0,0,0,1,1,1,1},
145 {0,0,0,0,1,1,1,1},
146 {1,1,1,1,0,1,1,1},
147 {1,1,1,1,1,0,1,1},
148 {1,1,1,1,1,1,0,1},
149 {1,1,1,1,1,1,1,0}};
150 for (size_t i = 0; i <= NUM_CELLS_X; ++i) coordinates_x[i] *= YAC_RAD;
151 for (size_t i = 0; i <= NUM_CELLS_Y; ++i) coordinates_y[i] *= YAC_RAD;
152 for (size_t i = 0; i < NUM_CELLS_X; ++i) cell_coordinates_x[i] *= YAC_RAD;
153 for (size_t i = 0; i < NUM_CELLS_Y; ++i) cell_coordinates_y[i] *= YAC_RAD;
154
155 int const is_tgt = comm_rank == TGT_RANK;
156
158 utest_generate_basic_grid_data_reg2d(
160 local_start[comm_rank], local_count[comm_rank], with_halo);
161
162 struct yac_basic_grid * grid =
164 struct yac_basic_grid * empty_grid =
166
167 // define custom coordinates and masks in grid data
168 if (is_tgt) {
169 yac_coordinate_pointer tgt_cell_coordinates =
170 xmalloc(NUM_CELLS_X * NUM_CELLS_Y * sizeof(*tgt_cell_coordinates));
171 for (size_t i = 0, k = 0; i < NUM_CELLS_Y; ++i)
172 for (size_t j = 0; j < NUM_CELLS_X; ++j, ++k)
173 LLtoXYZ(
174 cell_coordinates_x[j], cell_coordinates_y[i], tgt_cell_coordinates[k]);
176 grid, YAC_LOC_CELL, tgt_cell_coordinates);
177 } else { // is src
178 int * src_corner_mask =
179 xmalloc(grid_data.num_vertices * sizeof(*src_corner_mask));
180 for (size_t i = 0; i < grid_data.num_vertices; ++i)
181 src_corner_mask[i] =
182 ((int*)(&(src_global_corner_mask[0][0])))[grid_data.vertex_ids[i]];
184 grid, YAC_LOC_CORNER, src_corner_mask, NULL);
185 }
186
187 struct yac_dist_grid_pair * grid_pair =
188 yac_dist_grid_pair_new(grid, empty_grid, MPI_COMM_WORLD);
189
190 struct yac_interp_field src_fields[] =
191 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = 0}};
192 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
193 struct yac_interp_field tgt_field =
194 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
195
196 struct yac_interp_grid * interp_grid =
200
201 // Test different DNN configurations:
202 struct yac_interp_method_dnn_config dnn_configs[] = {
203 // Fixed search distance (1.3 degrees in radians), AVG weighting
205 .search_distance =
208 .search_distance = {.fixed = 1.3 * YAC_RAD}},
212 // Fixed search distance, DIST weighting
214 .search_distance =
217 .search_distance = {.fixed = 1.3 * YAC_RAD}},
221 // Fixed search distance, GAUSS weighting
223 .search_distance =
226 .search_distance = {.fixed = 1.3 * YAC_RAD}},
230 // Smaller fixed search distance (0.4 degrees in radians)
232 .search_distance =
235 .search_distance = {.fixed = 0.4 * YAC_RAD}},
239 // Very smaller fixed search distance (0.1 degrees in radians)
241 .search_distance =
244 .search_distance = {.fixed = 0.4 * YAC_RAD}},
248 // Cell area search distance with scale 1.0
250 .search_distance =
253 .search_distance = {.scale = 1.0}},
257 // Cell area search distance with larger scale
259 .search_distance =
262 .search_distance = {.scale = 2.0}},
266 // RBF weighting with fixed search distance
268 .search_distance =
271 .search_distance = {.fixed = 1.3 * YAC_RAD}},
275 // Fixed search distance with a minimum number of 3 source points
277 .search_distance =
280 .search_distance = {.fixed = 1.3 * YAC_RAD}},
281 .n_min = 3,
284 // Fixed search distance with a minimum number of 5 source points
286 .search_distance =
289 .search_distance = {.fixed = 1.3 * YAC_RAD}},
290 .n_min = 5,
293 };
294 enum {NUM_DNN_CONFIGS = sizeof(dnn_configs)/sizeof(dnn_configs[0])};
295
296 for (size_t i = 0; i < NUM_DNN_CONFIGS; ++i) {
297
298 double ref_tgt_results[NUM_CELLS_X * NUM_CELLS_Y];
299
300 // compute reference data
301 if (is_tgt) {
302
303 utest_compute_reference_result(
304 dnn_configs[i], coordinates_x, coordinates_y,
305 (int const *)(&(src_global_corner_mask[0][0])),
308 ref_tgt_results);
309 }
310
311 // generate interpolation method stack
312 struct interp_method * method_stack[3] =
313 {yac_interp_method_dnn_new(dnn_configs[i]),
315
316 // generate weights
317 struct yac_interp_weights * weights =
318 yac_interp_method_do_search(method_stack, interp_grid);
319 yac_interp_method_delete(method_stack);
320
321 for (size_t j = 0; j < NUM_REORDER_TYPES; ++j) {
322 enum {COLLECTION_SIZE = 1, COLLECTION_IDX = 0};
323
324 struct yac_interpolation * interpolation =
326 weights, reorder_type[j], COLLECTION_SIZE,
327 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
328
329 // prepare data
330 double *** src_data = NULL;
331 double ** tgt_data = NULL;
332 if (is_tgt) {
333
334 tgt_data = xmalloc(COLLECTION_SIZE * sizeof(*tgt_data));
335 tgt_data[COLLECTION_IDX] =
336 xmalloc(grid_data.num_cells * sizeof(**tgt_data));
337 for (size_t k = 0; k < grid_data.num_cells; ++k) {
338 tgt_data[COLLECTION_IDX][k] = -999.0;
339 }
340
341 } else { // is src
342
343 src_data = xmalloc(COLLECTION_SIZE * sizeof(*src_data));
344
345 // only one field
346 src_data[COLLECTION_IDX] = xmalloc(1 * sizeof(**src_data));
347 src_data[COLLECTION_IDX][0] =
348 xmalloc(grid_data.num_vertices * sizeof(***src_data));
349 for (size_t k = 0; k < grid_data.num_vertices; ++k) {
350 src_data[COLLECTION_IDX][0][k] =
351 (double)(grid_data.vertex_ids[k]);
352 }
353 }
354
355 // do exchange
356 yac_interpolation_execute(interpolation, src_data, tgt_data);
357
358 // check interpolation result
359 if (is_tgt) {
360
361 // verify results based on weight type
362 for (size_t k = 0; k < grid_data.num_cells; ++k) {
363
364 if (fabs(tgt_data[COLLECTION_IDX][k] - ref_tgt_results[k]) > 1e-6) {
365 PUT_ERR("wrong result");
366 }
367 }
368 }
369
370 // cleanup
371 if (is_tgt) {
372
373 free(tgt_data[COLLECTION_IDX]);
374 free(tgt_data);
375
376 } else { // is src
377
378 free(src_data[COLLECTION_IDX][0]);
379 free(src_data[COLLECTION_IDX]);
380 free(src_data);
381 }
382
383 yac_interpolation_delete(interpolation);
384 } // NUM_REORDER_TYPES
386 } // NUM_STACKS
387 yac_interp_grid_delete(interp_grid);
388 yac_dist_grid_pair_delete(grid_pair);
389 yac_basic_grid_delete(empty_grid);
391 }
392
393 xt_finalize();
394 MPI_Finalize();
395
396 return TEST_EXIT_CODE;
397}
398
428static void utest_determine_src_points(
429 double const * src_coordinates_x, double const * src_coordinates_y,
430 size_t const src_size_x, size_t const src_size_y,
431 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
432 size_t const tgt_size_x, size_t const tgt_size_y,
433 double const inc_angle, int const * src_mask,
434 size_t * num_src_points, size_t ** src_points) {
435
436 *src_points =
437 xmalloc(
438 src_size_x * src_size_y * tgt_size_x * tgt_size_y * sizeof(**src_points));
439 size_t total_num_src_points = 0;
440
441 for (size_t tgt_y = 0, tgt_point_idx = 0; tgt_y < tgt_size_y; ++tgt_y) {
442
443 for (size_t tgt_x = 0; tgt_x < tgt_size_x; ++tgt_x, ++tgt_point_idx) {
444
445 // compute target point coordinates in 3D
446 double tgt_coord[3];
447 LLtoXYZ(tgt_coordinates_x[tgt_x], tgt_coordinates_y[tgt_y], tgt_coord);
448
449 size_t curr_num_src = 0;
450
451 // iterate over all source points
452 for (size_t src_y = 0, src_point_idx = 0; src_y < src_size_y; ++src_y) {
453 for (size_t src_x = 0; src_x < src_size_x; ++src_x, ++src_point_idx) {
454
455 // compute source point coordinates in 3D
456 double src_coord[3];
457 LLtoXYZ(
458 src_coordinates_x[src_x], src_coordinates_y[src_y], src_coord);
459
460 // compute angle between target and source point
461 double const angle = get_vector_angle(tgt_coord, src_coord);
462
463 // check if source point is within the bounding circle and not masked
464 if (angle <= inc_angle && src_mask[src_point_idx]) {
465 (*src_points)[total_num_src_points] = src_point_idx;
466 ++total_num_src_points;
467 ++curr_num_src;
468 }
469 }
470 }
471
472 num_src_points[tgt_point_idx] = curr_num_src;
473 }
474 }
475
476 *src_points =
477 xrealloc(*src_points, total_num_src_points * sizeof(**src_points));
478}
479
480static double utest_compute_avg_result(
481 size_t const n, size_t const * src_indices, size_t const tgt_index,
482 double const * src_coordinates_x, double const * src_coordinates_y,
483 size_t const src_size_x,
484 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
485 size_t const tgt_size_x) {
486
487 UNUSED(tgt_index);
488 UNUSED(src_coordinates_x);
489 UNUSED(src_coordinates_y);
490 UNUSED(src_size_x);
491 UNUSED(tgt_coordinates_x);
492 UNUSED(tgt_coordinates_y);
493 UNUSED(tgt_size_x);
494
495 double sum = 0.0;
496 for (size_t i = 0; i < n; ++i) {
497 sum += (double)(src_indices[i]);
498 }
499 return sum / (double)n;
500}
501
502static double utest_compute_dist_result(
503 size_t const n, size_t const * src_indices, size_t const tgt_index,
504 double const * src_coordinates_x, double const * src_coordinates_y,
505 size_t const src_size_x,
506 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
507 size_t const tgt_size_x) {
508
509 double tgt_coord[3];
510 LLtoXYZ(
511 tgt_coordinates_x[tgt_index%tgt_size_x],
512 tgt_coordinates_y[tgt_index/tgt_size_x], tgt_coord);
513
514 double result = 0.0;
515 double weights_sum = 0.0;
516
517 for (size_t i = 0; i < n; ++i) {
518
519 double src_coord[3];
520 LLtoXYZ(src_coordinates_x[src_indices[i]%src_size_x],
521 src_coordinates_y[src_indices[i]/src_size_x], src_coord);
522
523 double weight = 1.0 / get_vector_angle(tgt_coord, src_coord);
524 result += weight * (double)src_indices[i];
525 weights_sum += weight;
526 }
527 return result / weights_sum;
528}
529
530static double utest_compute_gauss_result(
531 size_t const n, size_t const * src_indices, size_t const tgt_index,
532 double const * src_coordinates_x, double const * src_coordinates_y,
533 size_t const src_size_x,
534 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
535 size_t const tgt_size_x) {
536
537 // return early if there is only a single source point
538 if (n == 1) {
539 return (double)src_indices[0];
540 }
541
542 double src_coords[n][3];
543
544 for (size_t i = 0; i < n; ++i) {
545 LLtoXYZ(src_coordinates_x[src_indices[i]%src_size_x],
546 src_coordinates_y[src_indices[i]/src_size_x], src_coords[i]);
547 }
548
549 // "- n" because we do not count the diagonal
550 double src_distances_sum = 0.0;
551 for (size_t i = 0; i < n; ++i)
552 for (size_t j = 0; j < n; ++j)
553 src_distances_sum += get_vector_angle(src_coords[i], src_coords[j]);
554
555 size_t src_distance_count = n * n - n;
556
557 // compute mean distance
558 double src_distance_mean = src_distances_sum / (double)src_distance_count;
559 double src_distance_mean_sq = src_distance_mean * src_distance_mean;
560
561 // compute weights
562 double tgt_coord[3];
563 LLtoXYZ(tgt_coordinates_x[tgt_index%tgt_size_x],
564 tgt_coordinates_y[tgt_index/tgt_size_x], tgt_coord);
565 double weights[n];
566 for (size_t i = 0; i < n; ++i) {
567 double tgt_distance = get_vector_angle(src_coords[i], tgt_coord);
568 weights[i] =
569 exp(-1.0 * (tgt_distance * tgt_distance) /
570 (YAC_INTERP_DNN_GAUSS_SCALE_DEFAULT * src_distance_mean_sq));
571 }
572
573 // compute sum of weights
574 double weights_sum = 0.0;
575 for (size_t i = 0; i < n; ++i) weights_sum += weights[i];
576 for (size_t i = 0; i < n; ++i) weights[i] /= weights_sum;
577
578 // compute interpolation results
579 double result = 0.0;
580 for (size_t i = 0; i < n; ++i) {
581 result += weights[i] * (double)src_indices[i];
582 }
583
584 return result;
585}
586
587static void utest_inverse(double * A, size_t n);
588
589static double utest_compute_rbf_result(
590 size_t const n, size_t const * src_indices, size_t const tgt_index,
591 double const * src_coordinates_x, double const * src_coordinates_y,
592 size_t const src_size_x,
593 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
594 size_t const tgt_size_x) {
595
596 double src_coords[n][3];
597 for (size_t i = 0; i < n; ++i) {
598 LLtoXYZ(src_coordinates_x[src_indices[i]%src_size_x],
599 src_coordinates_y[src_indices[i]/src_size_x], src_coords[i]);
600 }
601
602 double A[n][n];
603 double sum_d = 0.0;
604
605 // compute distance matrix for all source points
606 for (size_t i = 0; i < n; ++i) A[i][i] = 0.0;
607 for (size_t i = 0; i < n - 1; ++i) {
608 for (size_t j = i + 1; j < n; ++j) {
609 double d = get_vector_angle(src_coords[i], src_coords[j]);
610 A[i][j] = d;
611 A[j][i] = d;
612 sum_d += d;
613 }
614 }
615
616 // compute and apply scale factor for distance matrix
617 double scale_d = 1.0;
618 if (sum_d > 0.0)
619 scale_d = ((double)((n - 1) * n)) / (2.0 * sum_d);
621
622 double sq_scale_d = scale_d * scale_d;
623
624 // compute matrix A[n][n] with rbf(A)
625 for (size_t i = 0; i < n; ++i) {
626 for (size_t j = 0; j < n; ++j) {
627 double d = A[i][j];
628 A[i][j] = exp(-1.0 * d * d * sq_scale_d);
629 }
630 }
631
632 // compute inverse of A
633 utest_inverse(&A[0][0], n);
634
635 // compute a[n] - distances from target to sources with rbf applied
636 double tgt_coord[3];
637 LLtoXYZ(tgt_coordinates_x[tgt_index%tgt_size_x],
638 tgt_coordinates_y[tgt_index/tgt_size_x], tgt_coord);
639
640 double a[n];
641 for (size_t i = 0; i < n; ++i) {
642 double d = get_vector_angle(tgt_coord, src_coords[i]);
643 a[i] = exp(-1.0 * d * d * sq_scale_d);
644 }
645
646 // compute weights: w_i = SUM(A_inv[i][j]*a[j])
647 double weights[n];
648 for (size_t i = 0; i < n; ++i) {
649 weights[i] = 0.0;
650 for (size_t j = 0; j < n; ++j) weights[i] += A[i][j] * a[j];
651 }
652
653 // compute interpolation result
654 double result = 0.0;
655 for (size_t i = 0; i < n; ++i) {
656 result += weights[i] * (double)src_indices[i];
657 }
658
659 return result;
660}
661
662static void utest_inverse(double * A, size_t n) {
663
664// LAPACKE_dsytrf_work and LAPACKE_dsytri might not be available
665// (see yac_lapack_interface.h).
666#ifdef YAC_LAPACK_NO_DSYTR
667 lapack_int ipiv[n+1];
668 double work[n*n];
669
670 for (size_t i = 0; i < n+1; ++i) ipiv[i] = 0;
671 for (size_t i = 0; i < n*n; ++i) work[i] = 0;
672
674 !LAPACKE_dgetrf(
675 LAPACK_COL_MAJOR, (lapack_int) n, (lapack_int) n,
676 A, (lapack_int) n, ipiv), "internal ERROR: dgetrf")
677
679 !LAPACKE_dgetri_work(
680 LAPACK_COL_MAJOR, (lapack_int) n, A, (lapack_int) n,
681 ipiv, work, (lapack_int) (n * n)), "internal ERROR: dgetri")
682#else
683 lapack_int ipiv[n];
684 double work[n];
685
687 !LAPACKE_dsytrf_work(
688 LAPACK_COL_MAJOR, 'L', (lapack_int) n , A,
689 (lapack_int) n, ipiv, work, (lapack_int) n), "internal ERROR: dsytrf")
690
692 !LAPACKE_dsytri_work(
693 LAPACK_COL_MAJOR, 'L', (lapack_int) n , A,
694 (lapack_int) n, ipiv, work), "internal ERROR: dsytri")
695
696 for (size_t i = 0; i < n; ++i)
697 for (size_t j = i + 1; j < n; ++j)
698 A[j*n+i] = A[i*n+j];
699#endif
700}
701
702static void utest_compute_reference_result(
703 struct yac_interp_method_dnn_config const dnn_config,
704 double const * src_coordinates_x, double const * src_coordinates_y,
705 int const * src_global_mask, size_t const src_size_x, size_t const src_size_y,
706 double const * tgt_coordinates_x, double const * tgt_coordinates_y,
707 size_t const tgt_size_x, size_t const tgt_size_y,
708 double * ref_tgt_results) {
709
710 // determine search distance
711 double search_distance;
712 YAC_ASSERT(dnn_config.search_distance != NULL, "search_distance is NULL")
713 switch (dnn_config.search_distance->type) {
714 YAC_UNREACHABLE_DEFAULT("invalid search distance type");
716 search_distance = dnn_config.search_distance->search_distance.fixed;
717 break;
718 }
720 // the search distance computation is simplified and assumes a planar cell
721 // and bounding circle, but for this test it should be sufficient
722 double cell_area = YAC_RAD * YAC_RAD;
723 search_distance =
725 sqrt(cell_area / M_PI);
726 break;
727 }
728 }
729
730 // compute source points overlapping with bounding circles of each
731 // target point
732 size_t * src_points = NULL;
733 size_t num_src_per_tgt[tgt_size_x * tgt_size_y];
734 utest_determine_src_points(
735 src_coordinates_x, src_coordinates_y, src_size_x, src_size_y,
736 tgt_coordinates_x, tgt_coordinates_y, tgt_size_x, tgt_size_y,
737 search_distance, src_global_mask, num_src_per_tgt, &src_points);
738
739 // get pointer to weight computation function
740 // (based on dnn_configs[i].type)
741 double (*compute_result)(
742 size_t const, size_t const *, size_t const,
743 double const *, double const *, size_t const,
744 double const *, double const *, size_t const) = NULL;
745 switch (dnn_config.type) {
746 YAC_UNREACHABLE_DEFAULT("invalid DNN_WEIGHT_TYPE");
748 compute_result = utest_compute_avg_result;
749 break;
751 compute_result = utest_compute_dist_result;
752 break;
754 compute_result = utest_compute_gauss_result;
755 break;
757 compute_result = utest_compute_rbf_result;
758 break;
759 }
760
761 // determine the minimum number of source points that have to be found
762 // within the search distance in order to interpolate a target point
763 size_t n_min = (size_t)dnn_config.n_min;
764
765 // compute reference tgt results
766 size_t src_offset = 0;
767 for (size_t k = 0; k < tgt_size_x * tgt_size_y; ++k) {
768
769 if (num_src_per_tgt[k] >= n_min) {
770 size_t * curr_src_points = &src_points[src_offset];
771 ref_tgt_results[k] =
772 compute_result(
773 num_src_per_tgt[k], curr_src_points, k,
774 src_coordinates_x, src_coordinates_y, src_size_x,
775 tgt_coordinates_x, tgt_coordinates_y, tgt_size_x);
776 } else {
777 // No valid source points in search distance, use fallback value
778 ref_tgt_results[k] = fixed_value;
779 }
780 src_offset += num_src_per_tgt[k];
781 }
782
783 free(src_points);
784}
#define YAC_ASSERT(exp, msg)
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:57
size_t yac_basic_grid_add_coordinates_nocpy(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates)
Definition basic_grid.c:202
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
size_t yac_basic_grid_add_mask_nocpy(struct yac_basic_grid *grid, enum yac_location location, int const *mask, char const *mask_name)
Definition basic_grid.c:244
#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
#define YAC_RAD
static double get_vector_angle(double const a[3], double const b[3])
Definition geometry.h:472
void yac_interp_grid_delete(struct yac_interp_grid *interp_grid)
struct yac_interp_grid * yac_interp_grid_new(struct yac_dist_grid_pair *grid_pair, char const *src_grid_name, char const *tgt_grid_name, size_t num_src_fields, struct yac_interp_field const *src_fields, struct yac_interp_field const tgt_field)
Definition interp_grid.c:31
void yac_interp_method_delete(struct interp_method **method)
Delete an interpolation stack and free its resources (but not the pointer array).
struct yac_interp_weights * yac_interp_method_do_search(struct interp_method **method, struct yac_interp_grid *interp_grid)
Perform weight computation using given interpolation stack and grid.
Defines the interface of the interpolation method "base class" in YAC.
enum callback_type type
struct interp_method * yac_interp_method_dnn_new(struct yac_interp_method_dnn_config config)
@ YAC_INTERP_DNN_WEIGHT_AVG
average of source points within search distance
@ YAC_INTERP_DNN_WEIGHT_DIST
distance weighted average of source points
@ YAC_INTERP_DNN_WEIGHT_GAUSS
Gauss weighted average of source points.
@ YAC_INTERP_DNN_WEIGHT_RBF
radial basis function weighted average
#define YAC_INTERP_DNN_RBF_SCALE_DEFAULT
#define YAC_INTERP_DNN_GAUSS_SCALE_DEFAULT
#define YAC_INTERP_DNN_N_MIN_DEFAULT
@ YAC_INTERP_DNN_SEARCH_DISTANCE_FIXED
use a fixed search distance (in radians)
@ YAC_INTERP_DNN_SEARCH_DISTANCE_CELL_AREA
struct interp_method * yac_interp_method_fixed_new(double value)
struct yac_interpolation * yac_interp_weights_get_interpolation(struct yac_interp_weights *weights, enum yac_interp_weights_reorder_type reorder, size_t collection_size, double frac_mask_fallback_value, double scaling_factor, double scaling_summand, char const *yaxt_exchanger_name, int is_source, int is_target)
void yac_interp_weights_delete(struct yac_interp_weights *weights)
yac_interp_weights_reorder_type
@ YAC_MAPPING_ON_TGT
weights will be applied at target processes
@ YAC_MAPPING_ON_SRC
weights will be applied at source processes
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.
double const YAC_FRAC_MASK_NO_VALUE
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_CELL
Definition location.h:14
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xmalloc(size)
Definition ppm_xfuncs.h:66
enum yac_location location
Definition basic_grid.h:16
struct yac_interp_field tgt_field
Definition interp_grid.c:26
size_t num_src_fields
Definition interp_grid.c:27
struct yac_dist_grid_pair * grid_pair
Definition interp_grid.c:25
struct yac_interp_field src_fields[]
Definition interp_grid.c:28
union yac_interp_method_dnn_config_search_distance::@28 search_distance
enum yac_interp_dnn_weight_type type
weighting type
struct yac_interp_method_dnn_config_search_distance * search_distance
@ COLLECTION_SIZE
char const src_grid_name[]
char const tgt_grid_name[]
static double const fixed_value
double coordinates_x[]
size_t num_cells[2]
double cell_coordinates_y[]
double coordinates_y[]
double cell_coordinates_x[]
#define TEST_EXIT_CODE
Definition tests.h:15
#define PUT_ERR(string)
Definition tests.h:10
#define NUM_CELLS_X
#define NUM_CELLS_Y
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587
#define YAC_UNREACHABLE_DEFAULT(msg)
Definition yac_assert.h:56
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21