YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interp_grid_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 <stdlib.h>
6#include <string.h>
7#include <float.h>
8
9#include <mpi.h>
10#include <yaxt.h>
11
12#include "tests.h"
13#include "test_common.h"
14#include "geometry.h"
15#include "read_icon_grid.h"
17#include "dist_grid_utils.h"
18#include "yac_mpi.h"
19
25static int utest_check_global_ids(
26 yac_int * global_ids, int count, int ref_global_count, MPI_Comm comm);
27static int utest_compare_global_ids(
28 yac_int * global_ids, yac_int * ref_global_ids, size_t count);
29
30int main(int argc, char** argv) {
31
32 MPI_Init(NULL, NULL);
33
34 xt_initialize(MPI_COMM_WORLD);
35
36 int comm_rank, comm_size;
37 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
38 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
39
40 utest_set_even_io_rank_list(MPI_COMM_WORLD);
41
42 { // general test using ICON grid files
43
44 if (argc != 2) {
45 PUT_ERR("ERROR: missing grid file directory");
46 xt_finalize();
47 MPI_Finalize();
48 return TEST_EXIT_CODE;
49 }
50
51 char * filenames[2];
52 char * grid_filenames[] =
53 {"icon_grid_R02B01.nc", "icon_grid_R03B01.nc"};
54 for (int i = 0; i < 2; ++i)
55 filenames[i] =
56 strcat(
57 strcpy(
58 malloc(strlen(argv[1]) + strlen(grid_filenames[i]) + 2), argv[1]),
59 grid_filenames[i]);
60
62 char const * grid_names[2] = {"R02B02", "R02B03"};
63
64 for (int i = 0; i < 2; ++i)
65 grid_data[i] =
67 filenames[i], MPI_COMM_WORLD);
68
69 struct yac_basic_grid * grids[2] =
72
73 struct yac_dist_grid_pair * grid_pair =
74 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
75
76 struct yac_interp_field src_fields[] =
77 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
78 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
80 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
81
82 struct yac_interp_grid * interp_grid =
85
86 if (strcmp(
88 PUT_ERR("error in yac_interp_grid_get_src_grid_name");
89
90 if (strcmp(
92 PUT_ERR("error in yac_interp_grid_get_tgt_grid_name");
93
94 if (yac_interp_grid_get_num_src_fields(interp_grid) != 1)
95 PUT_ERR("error in yac_interp_grid_get_num_src_fields");
96
97 if (yac_interp_grid_get_src_field_location(interp_grid, 0) !=
99 PUT_ERR("error in yac_interp_grid_get_src_field_location");
100
101 yac_interp_grid_delete(interp_grid);
103
104 for (int i = 0; i < 2; ++i) {
105 yac_basic_grid_delete(grids[i]);
106 free(filenames[i]);
107 }
108 }
109
110 if (comm_size >= 4) { // test with artificial grids
111
112 // we only need 4 processes
113 int do_test = comm_rank < 4;
114 MPI_Comm comm;
115 MPI_Comm_split(MPI_COMM_WORLD, do_test, 0, &comm);
116 int comm_rank, comm_size;
117 MPI_Comm_rank(comm, &comm_rank);
118 MPI_Comm_size(comm, &comm_size);
119
120 if (do_test) {
121
122 {
123
124 int is_tgt = comm_rank >= 2;
125
126 double coordinates_x[2][5] = {{0.0,1.0,2.0,3.0,4.0}, {0.5,1.5,2.5,3.5,-1.0}};
127 double coordinates_y[2][4] = {{0.0,1.0,2.0,3.0}, {0.5,1.5,2.5,-1.0}};
128 size_t num_cells[2][2] = {{4,3},{3,2}};
129 size_t local_start[4][2] = {{0,0},{2,0},{0,0},{2,0}};
130 size_t local_count[4][2] = {{2,3},{2,3},{2,2},{1,2}};
131 int with_halo = 0;
132 for (int i = 0; i < 2; ++i){
133 for (int j = 0; j < 5; ++j) coordinates_x[i][j] *= YAC_RAD;
134 for (int j = 0; j < 4; ++j) coordinates_y[i][j] *= YAC_RAD;
135 }
136
138 utest_generate_basic_grid_data_reg2d(
139 coordinates_x[is_tgt], coordinates_y[is_tgt], num_cells[is_tgt],
140 local_start[comm_rank], local_count[comm_rank], with_halo);
141
142 char const * grid_names[2] = {"src_grid", "tgt_grid"};
143 struct yac_basic_grid * grids[] =
146
147 struct yac_dist_grid_pair * grid_pair =
148 yac_dist_grid_pair_new(grids[0], grids[1], comm);
149
150 struct yac_interp_field src_fields[] =
151 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX},
152 {.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX},
153 {.location = YAC_LOC_EDGE, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
154 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
156 {.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
157
158 struct yac_interp_grid * interp_grid =
161
162 // check
163
164 size_t * tgt_indices, tgt_count;
165 yac_interp_grid_get_tgt_points(interp_grid, &tgt_indices, &tgt_count);
166
167 yac_int tgt_global_ids[12];
169 interp_grid, tgt_indices, tgt_count, tgt_global_ids);
170
171 double tgt_coordinates[12][3];
173 interp_grid, tgt_indices, tgt_count, tgt_coordinates);
174
175 {
176 int count_ = (int)tgt_count, counts[4], displs[4];
177 MPI_Allgather(&count_, 1, MPI_INT, counts, 1, MPI_INT, comm);
178 for (int i = 0, accu = 0; i < comm_size; accu += counts[i++])
179 displs[i] = accu;
180
181 int global_count = 0;
182 for (int i = 0; i < comm_size; ++i) global_count += counts[i];
183 if (global_count != 12)
184 PUT_ERR("error in yac_interp_grid_get_tgt_points");
185
186 yac_int all_tgt_global_ids[12];
187 MPI_Gatherv(
188 tgt_global_ids, count_, yac_int_dt, all_tgt_global_ids,
189 counts, displs, yac_int_dt, 0, comm);
190 double all_tgt_coordinates[12][3];
191 for (int i = 0; i < comm_size; ++i) counts[i] *= 3;
192 for (int i = 0; i < comm_size; ++i) displs[i] *= 3;
193 MPI_Gatherv(
194 tgt_coordinates, 3*count_, MPI_DOUBLE, all_tgt_coordinates,
195 counts, displs, MPI_DOUBLE, 0, comm);
196
197 if (comm_rank == 0) {
198 double ref_tgt_coords[12][3];
199 for (size_t i = 0, k = 0; i < num_cells[1][1]+1; ++i)
200 for (size_t j = 0; j < num_cells[1][0]+1; ++j, ++k)
201 LLtoXYZ(
202 coordinates_x[1][j], coordinates_y[1][i],
203 &(ref_tgt_coords[k][0]));
204 for (yac_int i = 0; i < 12; ++i) {
205 if ((all_tgt_global_ids[i] >= 12) || (all_tgt_global_ids[i] < 0))
206 PUT_ERR("error in yac_interp_grid_get_tgt_points");
207 if (get_vector_angle(ref_tgt_coords[all_tgt_global_ids[i]],
208 all_tgt_coordinates[i]) > yac_angle_tol)
209 PUT_ERR("error in yac_interp_grid_get_tgt_points");
210 }
211 }
212 }
213
214 size_t ref_global_count[3] = {12, 20, 31};
215 for (size_t src_field_idx = 0; src_field_idx < 3; ++src_field_idx) {
216
218 interp_grid, src_field_idx) != src_fields[src_field_idx].location)
219 PUT_ERR("error in yac_interp_grid_get_src_field_location");
220
221 size_t * src_indices, src_count;
223 interp_grid, src_field_idx, &src_indices, &src_count);
224
225 yac_int src_global_ids[31];
227 interp_grid, src_indices, src_count, src_field_idx, src_global_ids);
228
229 if (utest_check_global_ids(
230 src_global_ids, src_count, ref_global_count[src_field_idx], comm))
231 PUT_ERR("error in yac_interp_grid_get_src_points or "
232 "yac_interp_grid_get_src_global_ids");
233 free(src_indices);
234 }
235
236 {
237 double search_coords[15][3];
238 for (size_t i = 0, k = 0; i < num_cells[1][1]+1; ++i)
239 for (size_t j = 0; j < num_cells[1][0]+1; ++j, ++k)
240 LLtoXYZ(
241 coordinates_x[1][j], coordinates_y[1][i], &(search_coords[k][0]));
242 LLtoXYZ(4.5*YAC_RAD, 0.5*YAC_RAD, &(search_coords[12][0]));
243 LLtoXYZ(4.5*YAC_RAD, 1.5*YAC_RAD, &(search_coords[13][0]));
244 LLtoXYZ(4.5*YAC_RAD, 2.5*YAC_RAD, &(search_coords[14][0]));
245
246 // test yac_interp_grid_do_points_search
247 size_t src_cells[15];
249 interp_grid, search_coords, 15, src_cells);
250
251 struct yac_grid_cell cell;
252 yac_init_grid_cell(&cell);
253
254 struct yac_const_basic_grid_data * src_grid_data =
256
257 // check search results
258 for (size_t i = 0; i < 15; ++i) {
259
260 size_t curr_src_cell = src_cells[i];
261 if (curr_src_cell != SIZE_MAX) {
263 src_grid_data, curr_src_cell, &cell);
264 if (!yac_point_in_cell(search_coords[i], cell))
265 PUT_ERR("error in yac_interp_grid_do_points_search");
266 }
267 }
268
269 yac_free_grid_cell(&cell);
270 }
271
272 {
273 double a[3], b[3];
274 struct bounding_circle bnd_circles[5];
275 size_t count = sizeof(bnd_circles) / sizeof(bnd_circles[0]);
276
277 LLtoXYZ_deg(0.0, 0.0, a);
278 LLtoXYZ_deg(0.4, 0.4, b);
279 LLtoXYZ_deg(0.0, 0.0, bnd_circles[0].base_vector);
280 bnd_circles[0].inc_angle = get_vector_angle_2(a, b);
281 bnd_circles[0].sq_crd = DBL_MAX;
282
283 LLtoXYZ_deg(0.0, 0.0, a);
284 LLtoXYZ_deg(0.0, 0.9, b);
285 LLtoXYZ_deg(0.0, 0.0, bnd_circles[1].base_vector);
286 bnd_circles[1].inc_angle = get_vector_angle_2(a, b);
287 bnd_circles[1].sq_crd = DBL_MAX;
288
289 LLtoXYZ_deg(-1.0, -1.0, a);
290 LLtoXYZ_deg(-0.9, -0.0, b);
291 LLtoXYZ_deg(-1.0, -1.0, bnd_circles[2].base_vector);
292 bnd_circles[2].inc_angle = get_vector_angle_2(a, b);
293 bnd_circles[2].sq_crd = DBL_MAX;
294
295 LLtoXYZ_deg(2.0, 1.5, a);
296 LLtoXYZ_deg(4.0, 3.0, b);
297 LLtoXYZ_deg(2.0, 1.5, bnd_circles[3].base_vector);
298 bnd_circles[3].inc_angle = get_vector_angle_2(a, b);
299 bnd_circles[3].sq_crd = DBL_MAX;
300
301 LLtoXYZ_deg(2.0, 1.5, a);
302 LLtoXYZ_deg(2.1, 1.5, b);
303 LLtoXYZ_deg(2.0, 1.5, bnd_circles[4].base_vector);
304 bnd_circles[4].inc_angle = get_vector_angle_2(a, b);
305 bnd_circles[4].sq_crd = DBL_MAX;
306
307 size_t ref_num_src_per_bnd_circle[] = {1, 3, 0, 12, 2};
308 yac_int ref_src_cell_global_ids[] =
309 {0, 0,1,4, 0,1,2,3,4,5,6,7,8,9,10,11, 5,6};
310
311 size_t * cells, num_cells_per_bnd_circle[count];
312
314 interp_grid, bnd_circles, count, 0,
315 &cells, num_cells_per_bnd_circle);
316
317 for (size_t i = 0, displ = 0; i < count; ++i) {
318 if (num_cells_per_bnd_circle[i] != ref_num_src_per_bnd_circle[i]) {
319 PUT_ERR("error in yac_interp_grid_do_bnd_circle_search_src");
320 } else {
321 yac_int src_cell_global_ids[20];
323 interp_grid, cells + displ, num_cells_per_bnd_circle[i], 0,
324 src_cell_global_ids);
325 if (utest_compare_global_ids(
326 src_cell_global_ids, ref_src_cell_global_ids + displ,
327 num_cells_per_bnd_circle[i]))
328 PUT_ERR("error in yac_interp_grid_do_bnd_circle_search_src");
329 }
330 displ += num_cells_per_bnd_circle[i];
331 }
332 free(cells);
333 }
334
335 // test yac_interp_grid_do_dnn_search_src/tgt
336 {
337 struct {
338 struct {
339 double lon, lat; // center of bounding circle in deg
340 } center;
341 double inc_angle;
342 } bnd_circle_configs[] = {
343 {.center.lon = 0.0, .center.lat = 0.0, .inc_angle = 0.1},
344 {.center.lon = 0.0, .center.lat = 0.0, .inc_angle = 0.9},
345 {.center.lon = 0.0, .center.lat = 0.0, .inc_angle = 2.0},
346 {.center.lon = -1.0, .center.lat = -1.0, .inc_angle = 0.5},
347 {.center.lon = 1.0, .center.lat = 1.0, .inc_angle = 0.5},
348 {.center.lon = 2.0, .center.lat = 1.5, .inc_angle = 2.5},
349 {.center.lon = 2.0, .center.lat = 2.0, .inc_angle = 10.0},
350 };
351 enum {
352 NUM_BND_CIRCLE_CONFIGS =
353 sizeof(bnd_circle_configs) / sizeof(bnd_circle_configs[0])};
354 struct bounding_circle bnd_circles[NUM_BND_CIRCLE_CONFIGS];
355 for (size_t i = 0; i < NUM_BND_CIRCLE_CONFIGS; ++i) {
357 bnd_circle_configs[i].center.lon,
358 bnd_circle_configs[i].center.lat, bnd_circles[i].base_vector);
359 double inc_angle_rad = bnd_circle_configs[i].inc_angle * YAC_RAD;
360 bnd_circles[i].inc_angle =
361 sin_cos_angle_new(sin(inc_angle_rad), cos(inc_angle_rad));
362 bnd_circles[i].sq_crd = DBL_MAX;
363 }
364
365 { // yac_interp_grid_do_dnn_search_src
366 size_t * points = NULL;
367 size_t num_points_per_bnd_circle[NUM_BND_CIRCLE_CONFIGS];
368
369 int const src_field_idx = 1; // corner
371 interp_grid, bnd_circles, NUM_BND_CIRCLE_CONFIGS, src_field_idx,
372 &points, num_points_per_bnd_circle);
373
374 // check that results are valid
375 for (size_t i = 0, displ = 0; i < NUM_BND_CIRCLE_CONFIGS; ++i) {
376 // we cannot predict exact counts for points, but they should
377 // be >= 0 and the global ids should be valid
378 if (num_points_per_bnd_circle[i] > 0) {
379 yac_int src_point_global_ids[100];
381 xmalloc(num_points_per_bnd_circle[i] * sizeof(*src_coords));
383 interp_grid, points + displ, num_points_per_bnd_circle[i],
384 src_field_idx, src_point_global_ids);
386 interp_grid, points + displ, num_points_per_bnd_circle[i],
387 src_field_idx, src_coords);
388
389 // check that all points are within the bounding circle
390 for (size_t j = 0; j < num_points_per_bnd_circle[i]; ++j) {
391 struct sin_cos_angle angle =
393 bnd_circles[i].base_vector, src_coords[j]);
394 if (compare_angles(angle, bnd_circles[i].inc_angle) > 0)
395 PUT_ERR("error in yac_interp_grid_do_dnn_search_src: "
396 "point outside bounding circle");
397 }
398 free(src_coords);
399 }
400 displ += num_points_per_bnd_circle[i];
401 }
402 free(points);
403 }
404
405 { // yac_interp_grid_do_dnn_search_tgt
406 size_t * points = NULL;
407 size_t num_points_per_bnd_circle[NUM_BND_CIRCLE_CONFIGS];
408
410 interp_grid, bnd_circles, NUM_BND_CIRCLE_CONFIGS,
411 &points, num_points_per_bnd_circle);
412
413 // check that results are valid
414 for (size_t i = 0, displ = 0; i < NUM_BND_CIRCLE_CONFIGS; ++i) {
415 // we cannot predict exact counts for points, but they should
416 // be >= 0 and the global ids should be valid
417 if (num_points_per_bnd_circle[i] > 0) {
418 yac_int tgt_point_global_ids[50];
420 xmalloc(num_points_per_bnd_circle[i] * sizeof(*tgt_coords));
422 interp_grid, points + displ, num_points_per_bnd_circle[i],
423 tgt_point_global_ids);
425 interp_grid, points + displ, num_points_per_bnd_circle[i],
426 tgt_coords);
427
428 // check that all points are within the bounding circle
429 for (size_t j = 0; j < num_points_per_bnd_circle[i]; ++j) {
430 struct sin_cos_angle angle =
432 bnd_circles[i].base_vector, tgt_coords[j]);
433 if (compare_angles(angle, bnd_circles[i].inc_angle) > 0)
434 PUT_ERR("error in yac_interp_grid_do_dnn_search_tgt: "
435 "point outside bounding circle");
436 }
437 free(tgt_coords);
438 }
439 displ += num_points_per_bnd_circle[i];
440 }
441 free(points);
442 }
443 }
444
445 // test yac_interp_grid_do_dnn_search_tgt
446 {
447 size_t count = 3;
448 struct bounding_circle bnd_circles[count];
449 double a[3], b[3];
450
451 // create bounding circles around different target regions
452 LLtoXYZ_deg(0.5, 0.5, a);
453 LLtoXYZ_deg(1.0, 1.0, b);
454 LLtoXYZ_deg(0.5, 0.5, bnd_circles[0].base_vector);
455 bnd_circles[0].inc_angle = get_vector_angle_2(a, b);
456 bnd_circles[0].sq_crd = DBL_MAX;
457
458 LLtoXYZ_deg(1.5, 1.5, a);
459 LLtoXYZ_deg(2.0, 2.0, b);
460 LLtoXYZ_deg(1.5, 1.5, bnd_circles[1].base_vector);
461 bnd_circles[1].inc_angle = get_vector_angle_2(a, b);
462 bnd_circles[1].sq_crd = DBL_MAX;
463
464 LLtoXYZ_deg(-0.5, -0.5, a);
465 LLtoXYZ_deg(-0.4, -0.4, b);
466 LLtoXYZ_deg(-0.5, -0.5, bnd_circles[2].base_vector);
467 bnd_circles[2].inc_angle = get_vector_angle_2(a, b);
468 bnd_circles[2].sq_crd = DBL_MAX;
469
470 size_t * points = NULL;
471 size_t num_points_per_bnd_circle[count];
472
474 interp_grid, bnd_circles, count,
475 &points, num_points_per_bnd_circle);
476
477 // check that results are valid
478 for (size_t i = 0, displ = 0; i < count; ++i) {
479 // we cannot predict exact counts for points, but they should be >= 0
480 // and the global ids should be valid
481 if (num_points_per_bnd_circle[i] > 0) {
482 yac_int tgt_point_global_ids[50];
484 xmalloc(num_points_per_bnd_circle[i] * sizeof(*tgt_coords));
486 interp_grid, points + displ, num_points_per_bnd_circle[i],
487 tgt_point_global_ids);
489 interp_grid, points + displ, num_points_per_bnd_circle[i],
490 tgt_coords);
491
492 // check that all points are within the bounding circle
493 for (size_t j = 0; j < num_points_per_bnd_circle[i]; ++j) {
494 struct sin_cos_angle angle =
495 get_vector_angle_2(bnd_circles[i].base_vector, tgt_coords[j]);
496 if (compare_angles(angle, bnd_circles[i].inc_angle) > 0)
497 PUT_ERR("error in yac_interp_grid_do_dnn_search_tgt: "
498 "point outside bounding circle");
499 }
500 free(tgt_coords);
501 }
502 displ += num_points_per_bnd_circle[i];
503 }
504 free(points);
505 }
506
507 {
508 size_t * tgt_cells, num_tgt_cells_per_corner[12];
510 interp_grid, tgt_indices, tgt_count,
511 &tgt_cells, num_tgt_cells_per_corner);
512
513 yac_int const * tgt_global_corner_ids =
515 interp_grid)->ids[YAC_LOC_CORNER];
516 yac_int const * tgt_global_cell_ids =
518 interp_grid)->ids[YAC_LOC_CELL];
519
520 yac_int ref_tgt_corner_cells[12][4] =
521 {{0}, {0,1}, {1,2}, {2},
522 {0,3}, {0,1,3,4}, {1,2,4,5}, {2,5},
523 {3}, {3,4}, {4,5}, {5}};
524 size_t ref_num_tgt_cells_per_corner[12] =
525 {1,2,2,1, 2,4,4,2, 1,2,2,1};
526
527 for (size_t i = 0, k = 0; i < tgt_count; ++i) {
528 if (ref_num_tgt_cells_per_corner[
529 tgt_global_corner_ids[tgt_indices[i]]] !=
530 num_tgt_cells_per_corner[i])
531 PUT_ERR("ERROR in yac_interp_grid_get_tgt_corner_cells");
532
533 for (size_t j = 0; j < num_tgt_cells_per_corner[i]; ++j, ++k)
534 if (ref_tgt_corner_cells[
535 tgt_global_corner_ids[tgt_indices[i]]][j] !=
536 tgt_global_cell_ids[tgt_cells[k]])
537 PUT_ERR("ERROR in yac_interp_grid_get_tgt_corner_cells");
538 }
539
540 free(tgt_cells);
541 }
542
543 {
544 for (size_t src_field_idx = 0; src_field_idx < 3; ++src_field_idx) {
545
547 interp_grid, src_field_idx) != YAC_LOC_CORNER) continue;
548
549 size_t * src_indices, src_count;
551 interp_grid, src_field_idx, &src_indices, &src_count);
552
553 yac_int src_global_ids[31];
555 interp_grid, src_indices, src_count, src_field_idx, src_global_ids);
556
557 size_t * src_cells, num_src_cells_per_corner[12];
559 interp_grid, src_indices, src_count,
560 &src_cells, num_src_cells_per_corner);
561
562 yac_int const * src_global_corner_ids =
564 interp_grid)->ids[YAC_LOC_CORNER];
565 yac_int const * src_global_cell_ids =
567 interp_grid)->ids[YAC_LOC_CELL];
568
569 yac_int ref_src_corner_cells[20][4] =
570 {{0}, {0,1}, {1,2}, {2,3}, {3},
571 {0,4}, {0,1,4,5}, {1,2,5,6}, {2,3,6,7}, {3,7},
572 {4,8}, {4,5,8,9}, {5,6,9,10}, {6,7,10,11}, {7,11},
573 {8}, {8,9}, {9,10}, {10,11}, {11}};
574 size_t ref_num_src_cells_per_corner[20] =
575 {1,2,2,2,1, 2,4,4,4,2, 2,4,4,4,2, 1,2,2,2,1};
576
577 for (size_t i = 0, k = 0; i < src_count; ++i) {
578 if (ref_num_src_cells_per_corner[
579 src_global_corner_ids[src_indices[i]]] !=
580 num_src_cells_per_corner[i])
581 PUT_ERR("ERROR in yac_interp_grid_get_src_corner_cells");
582
583 for (size_t j = 0; j < num_src_cells_per_corner[i]; ++j, ++k)
584 if (ref_src_corner_cells[
585 src_global_corner_ids[src_indices[i]]][j] !=
586 src_global_cell_ids[src_cells[k]])
587 PUT_ERR("ERROR in yac_interp_grid_get_src_corner_cells");
588 }
589
590 free(src_cells);
591 free(src_indices);
592 }
593 }
594
595 free(tgt_indices);
596 yac_interp_grid_delete(interp_grid);
597 yac_dist_grid_pair_delete(grid_pair);
598 yac_basic_grid_delete(grids[1]);
599 yac_basic_grid_delete(grids[0]);
600 }
601
602 { // test yac_interp_grid_relocate_src_tgt_pairs_orig
603
604 for (int to_tgt_owner = 0; to_tgt_owner <= 1; ++to_tgt_owner) {
605
606 int is_tgt = comm_rank >= 2;
607
608 double coordinates_x[2][5] = {{0.0,1.0,2.0,3.0,4.0},
609 {0.5,1.5,2.5,3.5,-1.0}};
610 double coordinates_y[2][4] = {{0.0,1.0,2.0,3.0},
611 {0.5,1.5,2.5,-1.0}};
612 size_t num_cells[2][2] = {{4,3},{3,2}};
613 size_t local_start[4][2] = {{0,0},{2,0},{0,0},{2,0}};
614 size_t local_count[4][2] = {{2,3},{2,3},{2,2},{1,2}};
615 int with_halo = 0;
616 for (int i = 0; i < 2; ++i){
617 for (int j = 0; j < 5; ++j) coordinates_x[i][j] *= YAC_RAD;
618 for (int j = 0; j < 4; ++j) coordinates_y[i][j] *= YAC_RAD;
619 }
620
622 utest_generate_basic_grid_data_reg2d(
623 coordinates_x[is_tgt], coordinates_y[is_tgt], num_cells[is_tgt],
624 local_start[comm_rank], local_count[comm_rank], with_halo);
625
626 char const * grid_names[2] = {"src_grid", "tgt_grid"};
627 struct yac_basic_grid * grids[] =
630
631 if (!is_tgt) {
632
633 yac_coordinate_pointer src_cell_coordinates =
634 malloc(grid_data.num_cells * sizeof(*src_cell_coordinates));
635 for (size_t i = 0; i < grid_data.num_cells; ++i) {
636 for (int j = 0; j < 3; ++j) src_cell_coordinates[i][j] = 0.0;
637 size_t * cell_vertices =
638 grid_data.cell_to_vertex + grid_data.cell_to_vertex_offsets[i];
639 for (int j = 0; j < grid_data.num_vertices_per_cell[i]; ++j)
640 for (int k = 0; k < 3; ++k)
641 src_cell_coordinates[i][k] +=
642 grid_data.vertex_coordinates[cell_vertices[j]][k];
643 normalise_vector(src_cell_coordinates[i]);
644 }
645
647 grids[0], YAC_LOC_CELL, src_cell_coordinates, grid_data.num_cells);
648 free(src_cell_coordinates);
649 }
650
651 struct yac_dist_grid_pair * grid_pair =
652 yac_dist_grid_pair_new(grids[0], grids[1], comm);
653
654 struct yac_interp_field src_fields[] =
655 {{.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX}};
656 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
658 {.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX,
659 .masks_idx = SIZE_MAX};
660
661 struct yac_interp_grid * interp_grid =
664
665 // get local tgt indices
666 size_t * tgt_points, tgt_count;
667 yac_interp_grid_get_tgt_points(interp_grid, &tgt_points, &tgt_count);
668
669 // get local global tgt ids
670 yac_int tgt_global_ids[12];
672 interp_grid, tgt_points, tgt_count, tgt_global_ids);
673
674 // get local tgt coordinates
675 yac_coordinate_pointer tgt_coordinates =
676 malloc(tgt_count * sizeof(*tgt_coordinates));
678 interp_grid, tgt_points, tgt_count, tgt_coordinates);
679
680 // get matching source cells for each local tgt point
681 size_t * src_points = malloc(tgt_count * sizeof(*src_points));
683 interp_grid, tgt_coordinates, tgt_count, 1, src_points, M_PI);
684 free(tgt_coordinates);
685
686 // generate dummy weights
687 double * weights = malloc(tgt_count * sizeof(*weights));
688 for (size_t i = 0; i < tgt_count; ++i)
689 weights[i] = (double)tgt_global_ids[i];
690
691 // relocate target and matching source points to original owners
693 interp_grid, to_tgt_owner, YAC_LOC_CELL, &src_points,
694 &tgt_points, &weights, &tgt_count);
695
696 // sort src points, tgt points and weights
697 yac_int src_global_ids[12];
699 interp_grid, src_points, tgt_count, 0, src_global_ids);
701 interp_grid, tgt_points, tgt_count, tgt_global_ids);
703 tgt_global_ids, tgt_count, src_global_ids, weights);
704
705 // check results
706 size_t ref_num_points[2][4] = {{6,6,0,0},{0,0,9,3}};
707 yac_int ref_global_ids[2][4][9] =
708 {{{0,1,4,5,8,9},{2,3,6,7,10,11},{-1},{-1}},
709 {{-1},{-1},{0,1,2,4,5,6,8,9,10},{3,7,11}}};
710 if (tgt_count != ref_num_points[to_tgt_owner][comm_rank])
711 PUT_ERR(
712 "error in yac_interp_grid_relocate_src_tgt_pairs_orig");
713 for (size_t i = 0; i < tgt_count; ++i) {
714 if (src_global_ids[i] != ref_global_ids[to_tgt_owner][comm_rank][i])
715 PUT_ERR(
716 "error in yac_interp_grid_relocate_src_tgt_pairs_orig");
717 if (tgt_global_ids[i] != ref_global_ids[to_tgt_owner][comm_rank][i])
718 PUT_ERR(
719 "error in yac_interp_grid_relocate_src_tgt_pairs_orig");
720 if (weights[i] != (double)ref_global_ids[to_tgt_owner][comm_rank][i])
721 PUT_ERR(
722 "error in yac_interp_grid_relocate_src_tgt_pairs_orig");
723 }
724
725 free(tgt_points);
726 free(weights);
727 free(src_points);
728 yac_interp_grid_delete(interp_grid);
730 yac_basic_grid_delete(grids[1]);
731 yac_basic_grid_delete(grids[0]);
732 }
733 }
734
735 { // test with identical source and target grid
736 double coordinates_x[5] = {0.0,1.0,2.0,3.0,4.0};
737 double coordinates_y[4] = {0.0,1.0,2.0,3.0};
738 size_t num_cells[2] = {4,3};
739 size_t local_start[4][2] = {{0,0},{1,0},{2,0},{3,0}};
740 size_t local_count[2] = {1,3};
741 int with_halo = 0;
742 for (int j = 0; j < 5; ++j) coordinates_x[j] *= YAC_RAD;
743 for (int j = 0; j < 4; ++j) coordinates_y[j] *= YAC_RAD;
745 utest_generate_basic_grid_data_reg2d(
747 local_start[comm_rank], local_count, with_halo);
748 const char *grid_name = "identical_artificial_grid";
749 struct yac_basic_grid *grid = yac_basic_grid_new(grid_name, grid_data);
750 struct yac_dist_grid_pair *grid_pair =
751 yac_dist_grid_pair_new(grid, grid, comm);
752 struct yac_interp_field src_fields[] =
753 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
754 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
756 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
757 struct yac_interp_grid *interp_grid =
759 grid_pair, grid_name, grid_name,
761 // Basic checks
762 if (strcmp(yac_interp_grid_get_src_grid_name(interp_grid), grid_name))
763 PUT_ERR("error in identical grid src name");
764 if (strcmp(yac_interp_grid_get_tgt_grid_name(interp_grid), grid_name))
765 PUT_ERR("error in identical grid tgt name");
766 // Clean up
767 yac_interp_grid_delete(interp_grid);
770 }
771 } // do_test
772
773 MPI_Comm_free(&comm);
774
775 } else {
776 PUT_ERR("insufficient number of processes");
777 }
778
779 xt_finalize();
780
781 MPI_Finalize();
782
783 return TEST_EXIT_CODE;
784}
785
786static int utest_check_global_ids(
787 yac_int * global_ids, int count, int ref_global_count, MPI_Comm comm) {
788
789 int error_count = 0;
790
791 int comm_rank, comm_size;
792 MPI_Comm_rank(comm, &comm_rank);
793 MPI_Comm_size(comm, &comm_size);
794
795 int * counts = xmalloc((size_t)comm_size * sizeof(*counts));
796 int * displs = xmalloc((size_t)comm_size * sizeof(*displs));
797 MPI_Allgather(&count, 1, MPI_INT, counts, 1, MPI_INT, comm);
798 for (int i = 0, accu = 0; i < comm_size; accu += counts[i++])
799 displs[i] = accu;
800
801 int global_count = 0;
802 for (int i = 0; i < comm_size; ++i) global_count += counts[i];
803
804 yac_int * all_global_ids =
805 (comm_rank == 0)?
806 xmalloc((size_t)global_count * sizeof(*all_global_ids)):
807 NULL;
808 MPI_Gatherv(
809 global_ids, count, yac_int_dt, all_global_ids,
810 counts, displs, yac_int_dt, 0, comm);
811
812 if (comm_rank == 0) {
813 int * flag = xcalloc((size_t)ref_global_count, sizeof(*flag));
814 int flag_count = 0;
815 for (int i = 0; i < global_count; ++i) {
816 if ((all_global_ids[i] >= ref_global_count) ||
817 (all_global_ids[i] < 0)) {
818 ++error_count;
819 } else {
820 if (!flag[all_global_ids[i]]) ++flag_count;
821 flag[all_global_ids[i]] = 1;
822 }
823 }
824 if (flag_count != ref_global_count) ++error_count;
825 free(flag);
826 }
827
828 free(all_global_ids);
829 free(displs);
830 free(counts);
831
832 return error_count;
833}
834
835static int utest_compare_global_ids(
836 yac_int * global_ids, yac_int * ref_global_ids, size_t count) {
837
838 size_t match_count = 0;
839 for (size_t i = 0; i < count; ++i)
840 for (size_t j = 0; j < count; ++j)
841 if (global_ids[i] == ref_global_ids[j]) ++match_count;
842 return match_count != count;
843}
char const * grid_names[]
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(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates, size_t count)
Definition basic_grid.c:222
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
int yac_point_in_cell(double point_coords[3], struct yac_grid_cell cell)
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2377
struct yac_dist_grid_pair * yac_dist_grid_pair_new(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Comm comm)
Definition dist_grid.c:2089
void yac_const_basic_grid_data_get_grid_cell(struct yac_const_basic_grid_data *grid_data, size_t cell_idx, struct yac_grid_cell *buffer_cell)
Definition dist_grid.c:2418
#define YAC_RAD
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
Definition geometry.h:493
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
Definition geometry.h:278
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
Definition geometry.h:506
#define yac_angle_tol
Definition geometry.h:26
static void normalise_vector(double v[])
Definition geometry.h:754
static double get_vector_angle(double const a[3], double const b[3])
Definition geometry.h:472
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
Definition geometry.h:483
void yac_init_grid_cell(struct yac_grid_cell *cell)
Definition grid_cell.c:14
void yac_free_grid_cell(struct yac_grid_cell *cell)
Definition grid_cell.c:44
void yac_interp_grid_do_points_search(struct yac_interp_grid *interp_grid, yac_coordinate_pointer search_coords, size_t count, size_t *src_cells)
size_t yac_interp_grid_get_num_src_fields(struct yac_interp_grid *interp_grid)
char const * yac_interp_grid_get_src_grid_name(struct yac_interp_grid *interp_grid)
Definition interp_grid.c:77
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
char const * yac_interp_grid_get_tgt_grid_name(struct yac_interp_grid *interp_grid)
Definition interp_grid.c:82
void yac_interp_grid_do_dnn_search_src(struct yac_interp_grid *interp_grid, const_bounding_circle_pointer bnd_circles, size_t count, size_t src_field_idx, size_t **src_points, size_t *num_src_per_bnd_circle)
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
void yac_interp_grid_do_bnd_circle_search_src(struct yac_interp_grid *interp_grid, const_bounding_circle_pointer bnd_circles, size_t count, size_t src_field_idx, size_t **src_cells, size_t *num_src_per_bnd_circle)
void yac_interp_grid_get_tgt_corner_cells(struct yac_interp_grid *interp_grid, size_t *tgt_corners, size_t count, size_t **tgt_cells, size_t *num_cells_per_corner)
void yac_interp_grid_get_src_points(struct yac_interp_grid *interp_grid, size_t src_field_idx, size_t **src_indices, size_t *count)
Definition interp_grid.c:87
enum yac_location yac_interp_grid_get_src_field_location(struct yac_interp_grid *interp_grid, size_t src_field_idx)
void yac_interp_grid_do_dnn_search_tgt(struct yac_interp_grid *interp_grid, const_bounding_circle_pointer bnd_circles, size_t count, size_t **tgt_points, size_t *num_tgt_per_bnd_circle)
void yac_interp_grid_get_src_coordinates(struct yac_interp_grid *interp_grid, size_t *src_points, size_t count, size_t src_field_idx, yac_coordinate_pointer src_coordinates)
void yac_interp_grid_do_nnn_search_src(struct yac_interp_grid *interp_grid, yac_coordinate_pointer search_coords, size_t count, size_t n, size_t *src_points, double max_search_distance)
void yac_interp_grid_get_src_corner_cells(struct yac_interp_grid *interp_grid, size_t *src_corners, size_t count, size_t **src_cells, size_t *num_cells_per_corner)
void yac_interp_grid_get_tgt_coordinates(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, yac_coordinate_pointer tgt_coordinates)
struct yac_const_basic_grid_data * yac_interp_grid_get_basic_grid_data_tgt(struct yac_interp_grid *interp_grid)
void yac_interp_grid_get_src_global_ids(struct yac_interp_grid *interp_grid, size_t *src_points, size_t count, size_t src_field_idx, yac_int *src_global_ids)
void yac_interp_grid_relocate_src_tgt_pairs_orig(struct yac_interp_grid *interp_grid, int to_tgt_owner, enum yac_location src_location, size_t **src_points, size_t **tgt_points, double **weights, size_t *count)
struct yac_const_basic_grid_data * yac_interp_grid_get_basic_grid_data_src(struct yac_interp_grid *interp_grid)
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_EDGE
Definition location.h:16
@ YAC_LOC_CELL
Definition location.h:14
#define xcalloc(nmemb, size)
Definition ppm_xfuncs.h:64
#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)
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
Definition geometry.h:53
double base_vector[3]
Definition geometry.h:51
const const_yac_int_pointer ids[3]
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
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
int const * location
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587
void yac_quicksort_index_yac_int_yac_int_double(yac_int *a, size_t n, yac_int *b, double *c)
YAC_INT yac_int
Definition yac_types.h:15
#define yac_int_dt
Definition yac_types.h:18
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21